diff --git a/.changeset/cyan-laws-bow.md b/.changeset/cyan-laws-bow.md new file mode 100644 index 00000000..afdfc4ad --- /dev/null +++ b/.changeset/cyan-laws-bow.md @@ -0,0 +1,5 @@ +--- +'@solidmaterial/material': minor +--- + +Add separate components for leading buttons in app bar diff --git a/.changeset/forty-kiwis-jump.md b/.changeset/forty-kiwis-jump.md new file mode 100644 index 00000000..0e34b54d --- /dev/null +++ b/.changeset/forty-kiwis-jump.md @@ -0,0 +1,5 @@ +--- +'@solidmaterial/calculator': patch +--- + +Use new component for back button in app bar diff --git a/.changeset/green-rice-melt.md b/.changeset/green-rice-melt.md new file mode 100644 index 00000000..a45f68f9 --- /dev/null +++ b/.changeset/green-rice-melt.md @@ -0,0 +1,5 @@ +--- +'@solidmaterial/landing-page': patch +--- + +Avoid unstable text reflow in hero section when changing the orientation on mobile diff --git a/.changeset/long-horses-rule.md b/.changeset/long-horses-rule.md new file mode 100644 index 00000000..dcb4879e --- /dev/null +++ b/.changeset/long-horses-rule.md @@ -0,0 +1,5 @@ +--- +'@solidmaterial/landing-page': minor +--- + +Add app bars with menu button to pages diff --git a/.changeset/seven-pans-speak.md b/.changeset/seven-pans-speak.md new file mode 100644 index 00000000..0854c55f --- /dev/null +++ b/.changeset/seven-pans-speak.md @@ -0,0 +1,5 @@ +--- +'@solidmaterial/landing-page': patch +--- + +Use new component for back button in app bar diff --git a/.changeset/tricky-keys-act.md b/.changeset/tricky-keys-act.md new file mode 100644 index 00000000..28be0c7a --- /dev/null +++ b/.changeset/tricky-keys-act.md @@ -0,0 +1,5 @@ +--- +'@solidmaterial/material': patch +--- + +Fix modal hidden navigation rail blinking when navigating to a page diff --git a/apps/calculator/src/routes/about.tsx b/apps/calculator/src/routes/about.tsx index cb23a44c..70ef947c 100644 --- a/apps/calculator/src/routes/about.tsx +++ b/apps/calculator/src/routes/about.tsx @@ -5,7 +5,7 @@ import favIconUrl from '/assets/favicon.svg?url&no-inline'; // import { MetaProvider, Title } from '@solidjs/meta'; import { useNavigate } from '@solidjs/router'; -import { MaterialAppBar } from '@solidmaterial/material/components/app-bar'; +import { MaterialAppBar, MaterialAppBarBackButton } from '@solidmaterial/material/components/app-bar'; import { H2, H3 } from '@solidmaterial/material/components/typography'; import { MaterialBodyLayout, MaterialPane } from '@solidmaterial/material/layouts'; @@ -24,7 +24,11 @@ const RouteAbout: Component = () => { - + } + />
logo

diff --git a/apps/calculator/src/routes/settings.tsx b/apps/calculator/src/routes/settings.tsx index dbb58f38..4d6f6f7f 100644 --- a/apps/calculator/src/routes/settings.tsx +++ b/apps/calculator/src/routes/settings.tsx @@ -3,7 +3,7 @@ import type { Component, VoidComponent } from 'solid-js'; import { MetaProvider, Title } from '@solidjs/meta'; import { useNavigate } from '@solidjs/router'; -import { MaterialAppBar } from '@solidmaterial/material/components/app-bar'; +import { MaterialAppBar, MaterialAppBarBackButton } from '@solidmaterial/material/components/app-bar'; import { MaterialButton } from '@solidmaterial/material/components/button'; import { MaterialDialog } from '@solidmaterial/material/components/dialog'; import { MaterialIcon } from '@solidmaterial/material/components/icon'; @@ -99,7 +99,11 @@ const RouteSettings: Component = () => { - + } + />

Theme diff --git a/apps/landing-page/src/examples/calculator/Calculator.tsx b/apps/landing-page/src/examples/calculator/Calculator.tsx index 8abd052a..98455f50 100644 --- a/apps/landing-page/src/examples/calculator/Calculator.tsx +++ b/apps/landing-page/src/examples/calculator/Calculator.tsx @@ -1,7 +1,7 @@ import type { VoidComponent } from 'solid-js'; import { useNavigate } from '@solidjs/router'; -import { MaterialAppBar } from '@solidmaterial/material/components/app-bar'; +import { MaterialAppBar, MaterialAppBarBackButton } from '@solidmaterial/material/components/app-bar'; import { MaterialIconButton } from '@solidmaterial/material/components/icon-button'; import { Breakpoints } from '@solidmaterial/material/utils'; import { createSignal } from 'solid-js'; @@ -31,7 +31,7 @@ export const Calculator: VoidComponent = props => { } trailingButtons={ = props => { target="_blank" /> } - onNavigate={navigateBackToList} />
diff --git a/apps/landing-page/src/examples/todo-list/TodoList.tsx b/apps/landing-page/src/examples/todo-list/TodoList.tsx index 955a5818..a6796c78 100644 --- a/apps/landing-page/src/examples/todo-list/TodoList.tsx +++ b/apps/landing-page/src/examples/todo-list/TodoList.tsx @@ -1,7 +1,7 @@ import type { VoidComponent } from 'solid-js'; import { useNavigate } from '@solidjs/router'; -import { MaterialAppBar } from '@solidmaterial/material/components/app-bar'; +import { MaterialAppBar, MaterialAppBarBackButton } from '@solidmaterial/material/components/app-bar'; import { MaterialButton } from '@solidmaterial/material/components/button'; import { MaterialCheckbox } from '@solidmaterial/material/components/checkbox'; import { MaterialIconButton } from '@solidmaterial/material/components/icon-button'; @@ -68,8 +68,7 @@ export const TodoList: VoidComponent = props => { } />
diff --git a/apps/landing-page/src/pages/home/sections/hero/SectionHero.module.css b/apps/landing-page/src/pages/home/sections/hero/SectionHero.module.css index 1eb71e5a..43b17fc0 100644 --- a/apps/landing-page/src/pages/home/sections/hero/SectionHero.module.css +++ b/apps/landing-page/src/pages/home/sections/hero/SectionHero.module.css @@ -12,6 +12,12 @@ transition-duration: var(--md-sys-motion-duration-spatial-fast); transition-timing-function: var(--md-sys-motion-spring-spatial-fast); + /* Avoid unstable text reflow when changing the orientation on mobile */ + @media (width < 600px) or (height < 480px) { + transition-duration: var(--md-sys-motion-duration-standard-spatial-fast); + transition-timing-function: var(--md-sys-motion-spring-standard-spatial-fast); + } + padding: var(--md-user-spacing-4xl); gap: var(--md-user-spacing-2xl); diff --git a/apps/landing-page/src/routes/components/[[name]].module.css b/apps/landing-page/src/routes/components/[[name]].module.css index 51c60fac..b32ddb94 100644 --- a/apps/landing-page/src/routes/components/[[name]].module.css +++ b/apps/landing-page/src/routes/components/[[name]].module.css @@ -1,11 +1,20 @@ .list-pane { --md-comp-pane-container-color: var(--md-sys-color-surface-container-low); - h1 { - margin-block-end: var(--md-user-spacing-md); - } + --md-comp-app-bar-container-color: transparent; + + aside { + h1 { + margin-block-end: var(--md-user-spacing-md); + } - sm-list + h1 { - margin-block-start: var(--md-user-spacing-xl); + sm-list + h1 { + margin-block-start: var(--md-user-spacing-xl); + } } } + +/* Adjust app bar container color when it's not the only pane */ +sm-body-layout:not(:has(> :only-child)) .list-pane { + --md-comp-app-bar-on-scroll-container-color: var(--md-comp-pane-container-color); +} diff --git a/apps/landing-page/src/routes/components/[[name]].tsx b/apps/landing-page/src/routes/components/[[name]].tsx index 0896fac7..dc335d3c 100644 --- a/apps/landing-page/src/routes/components/[[name]].tsx +++ b/apps/landing-page/src/routes/components/[[name]].tsx @@ -2,8 +2,13 @@ import type { Component } from 'solid-js'; import { MetaProvider, Title } from '@solidjs/meta'; import { useParams } from '@solidjs/router'; +import { MaterialAppBar } from '@solidmaterial/material/components/app-bar'; import { H1 } from '@solidmaterial/material/components/typography'; -import { MaterialListDetailLayout, MaterialPane } from '@solidmaterial/material/layouts'; +import { + MaterialListDetailLayout, + MaterialNavigationRailLayoutMenuButton, + MaterialPane +} from '@solidmaterial/material/layouts'; import { Show, createMemo } from 'solid-js'; import { EmptyState } from '../../components/empty-state/EmptyState'; @@ -43,32 +48,39 @@ const PageComponents: Component = () => { - +
+ } + /> + +
diff --git a/apps/landing-page/src/routes/examples/[[name]].module.css b/apps/landing-page/src/routes/examples/[[name]].module.css index fcce6644..44db75d0 100644 --- a/apps/landing-page/src/routes/examples/[[name]].module.css +++ b/apps/landing-page/src/routes/examples/[[name]].module.css @@ -1,3 +1,10 @@ .list-pane { --md-comp-pane-container-color: var(--md-sys-color-surface-container-low); + + --md-comp-app-bar-container-color: transparent; +} + +/* Adjust app bar container color when it's not the only pane */ +sm-body-layout:not(:has(> :only-child)) .list-pane { + --md-comp-app-bar-on-scroll-container-color: var(--md-comp-pane-container-color); } diff --git a/apps/landing-page/src/routes/examples/[[name]].tsx b/apps/landing-page/src/routes/examples/[[name]].tsx index 6ff770ee..fb605215 100644 --- a/apps/landing-page/src/routes/examples/[[name]].tsx +++ b/apps/landing-page/src/routes/examples/[[name]].tsx @@ -3,7 +3,12 @@ import type { ParentComponent } from 'solid-js'; import { MetaProvider, Title } from '@solidjs/meta'; import { useParams } from '@solidjs/router'; -import { MaterialListDetailLayout, MaterialPane } from '@solidmaterial/material/layouts'; +import { MaterialAppBar } from '@solidmaterial/material/components/app-bar'; +import { + MaterialListDetailLayout, + MaterialNavigationRailLayoutMenuButton, + MaterialPane +} from '@solidmaterial/material/layouts'; import { Show, createMemo } from 'solid-js'; import { Dynamic } from 'solid-js/web'; @@ -33,9 +38,16 @@ const PageExamples: ParentComponent = () => { } > - +
+ } + /> + +
{ - const navigate = useNavigate(); - const navigateBackToList = () => navigate('..', { state: { transition: 'top-level' } }); - const isMobile = () => Breakpoints.isCompactWidth(); const [activeTab, setActiveTab] = createSignal<'pnpm' | 'yarn' | 'npm'>('pnpm'); @@ -39,8 +39,7 @@ const PageGetStarted: Component = () => { } />
diff --git a/apps/landing-page/src/routes/index.tsx b/apps/landing-page/src/routes/index.tsx index 64c23420..a4c3b6e1 100644 --- a/apps/landing-page/src/routes/index.tsx +++ b/apps/landing-page/src/routes/index.tsx @@ -4,7 +4,11 @@ import { MetaProvider, Title } from '@solidjs/meta'; import { MaterialAppBar } from '@solidmaterial/material/components/app-bar'; import { MaterialIconButton } from '@solidmaterial/material/components/icon-button'; import { H2 } from '@solidmaterial/material/components/typography'; -import { MaterialBodyLayout, MaterialPane } from '@solidmaterial/material/layouts'; +import { + MaterialBodyLayout, + MaterialNavigationRailLayoutMenuButton, + MaterialPane +} from '@solidmaterial/material/layouts'; import { createSignal } from 'solid-js'; /* Used as a social button to link to GitHub project (see https://brand.github.com/foundations/logo) */ @@ -39,6 +43,7 @@ const PageHome: Component = () => { } trailingButtons={ <> , trailingButtons: } /> } }); @@ -113,8 +113,7 @@ export const LeadingButtonBack = meta.story({ args: { variant: 'small', title: 'Title', - leadingButtonAriaLabel: 'Go back', - onNavigate: fn() + leadingButton: } }); @@ -122,9 +121,7 @@ export const LeadingButtonMenu = meta.story({ args: { variant: 'small', title: 'Title', - leadingButtonType: 'menu', - leadingButtonAriaLabel: 'Open menu', - onNavigate: fn() + leadingButton: } }); diff --git a/packages/material/src/components/app-bar/MaterialAppBar.tsx b/packages/material/src/components/app-bar/MaterialAppBar.tsx index 8eb24aa0..0e60d3be 100644 --- a/packages/material/src/components/app-bar/MaterialAppBar.tsx +++ b/packages/material/src/components/app-bar/MaterialAppBar.tsx @@ -1,34 +1,28 @@ import type { JSX, VoidComponent } from 'solid-js'; import { createViewportObserver } from '@solid-primitives/intersection-observer'; -import { Match, Show, Switch, createMemo, createSignal, onCleanup, onMount } from 'solid-js'; +import { Match, Show, Switch, createSignal, onCleanup, onMount } from 'solid-js'; -import { MaterialIconButton } from '../icon-button/MaterialIconButton'; import { H1, H2 } from '../typography/Typography'; import styles from './MaterialAppBar.module.css'; -import ArrowBackIcon from '@solidmaterial/icons/400/outlined/arrow_back.svg'; -import ArrowBackIosNewIcon from '@solidmaterial/icons/400/outlined/arrow_back_ios_new.svg'; -import MenuIcon from '@solidmaterial/icons/400/outlined/menu.svg'; - export type MaterialAppBarVariant = 'small' | 'medium' | 'large'; -export type MaterialLeadingButtonType = 'back' | 'menu'; - export interface MaterialAppBarProps { variant: MaterialAppBarVariant; title: string; subtitle?: string; center?: boolean; - leadingButtonType?: MaterialLeadingButtonType; - leadingButtonAriaLabel?: string; + /** + * A leading button, placed in front of the title and subtitle + * + * Use this prop to render a {@link MaterialAppBarBackButton} or {@link MaterialNavigationRailLayoutMenuButton}. + */ + leadingButton?: JSX.Element; trailingButtons?: JSX.Element; - onNavigate?: (event: PointerEvent) => void; } -const isIOS = () => /iphone|ipad/iu.test(globalThis.navigator.userAgent); - export const MaterialAppBar: VoidComponent = props => { const [intersectionRatio, setIntersectionRatio] = createSignal(1); @@ -59,32 +53,12 @@ export const MaterialAppBar: VoidComponent = props => { const appBarTextOpacity = () => (hasAppendixContent() ? (0.4 - Math.min(0.4, intersectionRatio())) / 0.4 : 1); const appendixTextOpacity = () => (Math.max(0.5, intersectionRatio()) - 0.5) / 0.5; - const leadingButtonType = createMemo(() => props.leadingButtonType ?? 'back'); - return ( <> - -
- - - }> - - - - - - - - } - ariaLabel={props.leadingButtonAriaLabel} - onClick={(event: PointerEvent) => props.onNavigate?.(event)} - /> -
+ +
{props.leadingButton}
/iphone|ipad/iu.test(globalThis.navigator.userAgent); + +export interface MaterialAppBarBackButtonProps { + ariaLabel?: string; + title?: string; + onClick?: (event: PointerEvent) => void; +} + +/** + * Render a back button for an app bar + * + * Should be used in the `leadingButton` prop of the {@link MaterialAppBar}. + */ +export const MaterialAppBarBackButton: VoidComponent = props => { + return ( + }> + + + } + ariaLabel={props.ariaLabel} + title={props.title} + onClick={(event: PointerEvent) => props.onClick?.(event)} + /> + ); +}; diff --git a/packages/material/src/components/app-bar/index.ts b/packages/material/src/components/app-bar/index.ts index 6b5cbe76..72c6cd19 100644 --- a/packages/material/src/components/app-bar/index.ts +++ b/packages/material/src/components/app-bar/index.ts @@ -1,2 +1,4 @@ export { MaterialAppBar } from './MaterialAppBar'; -export type { MaterialAppBarProps, MaterialAppBarVariant, MaterialLeadingButtonType } from './MaterialAppBar'; +export type { MaterialAppBarProps, MaterialAppBarVariant } from './MaterialAppBar'; +export { MaterialAppBarBackButton } from './MaterialAppBarBackButton'; +export type { MaterialAppBarBackButtonProps } from './MaterialAppBarBackButton'; diff --git a/packages/material/src/components/navigation-rail/MaterialNavigationRail.module.css b/packages/material/src/components/navigation-rail/MaterialNavigationRail.module.css index 24da9334..27beb551 100644 --- a/packages/material/src/components/navigation-rail/MaterialNavigationRail.module.css +++ b/packages/material/src/components/navigation-rail/MaterialNavigationRail.module.css @@ -25,6 +25,13 @@ .container { position: relative; + /** + * Make the rail part of the view transition (although it has no actual + * view transition) so that the rail, when it is modal, does not get + * temporily painted below the panes (which do have an actual view transition) + */ + view-transition-name: md-nav-rail; + &[data-modal] { position: fixed; left: 0; @@ -38,10 +45,6 @@ &[data-always-expanded] { &[data-show] { - .fixed-menu-button { - visibility: hidden; - } - /** * If modal and always expanded, keep width fixed and instead * animate translate from -100% to 0% @@ -77,21 +80,6 @@ sm-icon-button { margin: 12px 8px; } - - .fixed-menu-button { - position: absolute; - top: 0; - left: 20px; - - /** - * When the navigation rail is hidden on small screens, its pointer events - * are disabled above so that the user can click on elements which are found - * on the left side of the screen (and 'behind' the expanded rail). - * - * Except for the absolutely-positioned menu button, which remains visible. - */ - pointer-events: all; - } } /* Rail containing FAB and items */ diff --git a/packages/material/src/components/navigation-rail/MaterialNavigationRail.tsx b/packages/material/src/components/navigation-rail/MaterialNavigationRail.tsx index 640da0b7..bfac880c 100644 --- a/packages/material/src/components/navigation-rail/MaterialNavigationRail.tsx +++ b/packages/material/src/components/navigation-rail/MaterialNavigationRail.tsx @@ -130,15 +130,6 @@ export const MaterialNavigationRail: VoidComponent
- -
- -
-
); }; diff --git a/packages/material/src/layouts/index.ts b/packages/material/src/layouts/index.ts index ad2fff0e..ea971fd5 100644 --- a/packages/material/src/layouts/index.ts +++ b/packages/material/src/layouts/index.ts @@ -11,4 +11,6 @@ export { MaterialListDetailLayout } from './canonical-layouts/list-detail-layout export { MaterialNavigationBarLayout } from './navigation-bar-layout/MaterialNavigationBarLayout'; export { MaterialNavigationLayout } from './navigation-layout/MaterialNavigationLayout'; export { MaterialNavigationRailLayout } from './navigation-rail-layout/MaterialNavigationRailLayout'; +export { MaterialNavigationRailLayoutMenuButton } from './navigation-rail-layout/MaterialNavigationRailLayoutMenuButton'; +export type { MaterialNavigationRailLayoutMenuButtonProps } from './navigation-rail-layout/MaterialNavigationRailLayoutMenuButton'; export { MaterialPane } from './pane/MaterialPane'; diff --git a/packages/material/src/layouts/navigation-rail-layout/MaterialNavigationRailLayout.module.css b/packages/material/src/layouts/navigation-rail-layout/MaterialNavigationRailLayout.module.css index 136d83b6..55e18996 100644 --- a/packages/material/src/layouts/navigation-rail-layout/MaterialNavigationRailLayout.module.css +++ b/packages/material/src/layouts/navigation-rail-layout/MaterialNavigationRailLayout.module.css @@ -16,13 +16,6 @@ z-index: 2; content-visibility: visible; - /** - * Make the rail part of the view transition (although it has no actual - * view transition) so that the rail, when it is modal, does not get - * temporily painted below the panes (which do have an actual view transition) - */ - view-transition-name: md-nav-rail; - /* Prevents collapsed navigation rail to be modal */ &[data-show]:has(sm-navigation-rail[data-modal]:not([data-always-expanded])) { min-width: var(--md-comp-nav-rail-container-width); diff --git a/packages/material/src/layouts/navigation-rail-layout/MaterialNavigationRailLayout.tsx b/packages/material/src/layouts/navigation-rail-layout/MaterialNavigationRailLayout.tsx index f4d58b80..81fc3f65 100644 --- a/packages/material/src/layouts/navigation-rail-layout/MaterialNavigationRailLayout.tsx +++ b/packages/material/src/layouts/navigation-rail-layout/MaterialNavigationRailLayout.tsx @@ -1,7 +1,7 @@ import type { Accessor, Context, FlowComponent } from 'solid-js'; import { createElementSize } from '@solid-primitives/resize-observer'; -import { createContext, createEffect, createSignal } from 'solid-js'; +import { createContext, createEffect, createMemo, createSignal } from 'solid-js'; import type { MaterialNavigationLayoutProps } from '../navigation-layout/MaterialNavigationLayout.types'; @@ -15,12 +15,22 @@ import styles from './MaterialNavigationRailLayout.module.css'; export const MaterialNavigationLayoutRailWidthContext: Context | undefined> = createContext>(); +export const MaterialNavigationRailMenuContext: Context< + [Accessor, Accessor, (event: PointerEvent) => void] +> = createContext<[Accessor, Accessor, (event: PointerEvent) => void]>([ + () => false, + () => false, + () => { + // Empty + } +]); + export const MaterialNavigationRailLayout: FlowComponent = props => { const numberOfItemsForRail = () => props.items.length + (props.secondary?.items.length ?? 0); const hasManyItemsForRail = () => Breakpoints.isCompactHeight() && (props.fab ? numberOfItemsForRail() > 3 : numberOfItemsForRail() > 4); - const showRail = () => props.show !== false && !shouldShowBar(props.items.length, props.preferSpace); + const showRail = createMemo(() => props.show !== false && !shouldShowBar(props.items.length, props.preferSpace)); const [target, setTarget] = createSignal(); const elementSize = createElementSize(target); @@ -39,6 +49,20 @@ export const MaterialNavigationRailLayout: FlowComponent setIsExpanded(expanded => !expanded); + const isModal = createMemo( + () => + Breakpoints.isCompactWidth() || + Breakpoints.isMediumWidth() || + (Breakpoints.isExpandedWidth() && props.preferSpace === 'horizontal') || + hasManyItemsForRail() + ); + + const isHideWhenCollapsed = createMemo(() => Breakpoints.isCompactWidth() || hasManyItemsForRail()); + + const isHiddenWhenCollapsed = createMemo( + () => props.menuButton !== undefined && showRail() && isModal() && isHideWhenCollapsed() + ); + return (
@@ -49,20 +73,17 @@ export const MaterialNavigationRailLayout: FlowComponent
- {props.children} + + {props.children} +
); diff --git a/packages/material/src/layouts/navigation-rail-layout/MaterialNavigationRailLayoutMenuButton.test.tsx b/packages/material/src/layouts/navigation-rail-layout/MaterialNavigationRailLayoutMenuButton.test.tsx new file mode 100644 index 00000000..c6f8dbdf --- /dev/null +++ b/packages/material/src/layouts/navigation-rail-layout/MaterialNavigationRailLayoutMenuButton.test.tsx @@ -0,0 +1,42 @@ +import { render } from '@solidjs/testing-library'; +import { describe, expect, it, vi } from 'vitest'; +import { page } from 'vitest/browser'; + +import { MaterialTheme } from '../../styling/material-theme/MaterialTheme'; + +import { MaterialNavigationRailMenuContext } from './MaterialNavigationRailLayout'; +import { MaterialNavigationRailLayoutMenuButton } from './MaterialNavigationRailLayoutMenuButton'; + +describe('MaterialNavigationRailLayoutMenuButton', () => { + describe('Visual', () => { + it('renders a button when rail is modal and hidden when collapsed', async () => { + const { baseElement } = render( + () => ( + true, () => false, vi.fn()]}> + + + ), + { wrapper: MaterialTheme } + ); + const screen = page.elementLocator(baseElement); + + const button = screen.getByRole('switch', { name: 'Menu button' }); + await expect.element(button).toBeVisible(); + }); + + it('renders nothing when rail is not modal or hidden when collapsed', async () => { + const { baseElement } = render( + () => ( + false, () => false, vi.fn()]}> + + + ), + { wrapper: MaterialTheme } + ); + const screen = page.elementLocator(baseElement); + + const button = screen.getByRole('switch', { name: 'Menu button' }); + await expect.element(button).not.toBeInTheDocument(); + }); + }); +}); diff --git a/packages/material/src/layouts/navigation-rail-layout/MaterialNavigationRailLayoutMenuButton.tsx b/packages/material/src/layouts/navigation-rail-layout/MaterialNavigationRailLayoutMenuButton.tsx new file mode 100644 index 00000000..97848200 --- /dev/null +++ b/packages/material/src/layouts/navigation-rail-layout/MaterialNavigationRailLayoutMenuButton.tsx @@ -0,0 +1,29 @@ +import type { VoidComponent } from 'solid-js'; + +import { Show, useContext } from 'solid-js'; + +import type { MaterialNavigationMenuButton } from '../../components/navigation-rail/MaterialNavigationRailMenuButton'; + +import { MaterialNavigationRailMenuButton } from '../../components/navigation-rail/MaterialNavigationRailMenuButton'; + +import { MaterialNavigationRailMenuContext } from './MaterialNavigationRailLayout'; + +export type MaterialNavigationRailLayoutMenuButtonProps = MaterialNavigationMenuButton; + +/** + * Render a menu button to show or hide a navigation rail if that rail + * is modal and hidden (when collapsed), otherwise renders nothing + * + * Should be used in the `leadingButton` prop of the {@link MaterialAppBar}. + */ +export const MaterialNavigationRailLayoutMenuButton: VoidComponent< + MaterialNavigationRailLayoutMenuButtonProps +> = props => { + const [isRailMenuButtonVisible, isRailExpanded, onClickMenuButton] = useContext(MaterialNavigationRailMenuContext); + + return ( + + + + ); +};