@noxlovette/material 0.5.1 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/material-claude-skill.js +31 -0
- package/claude-skill/material-design/SKILL.md +68 -0
- package/claude-skill/material-design/references/accessibility-checklist.md +29 -0
- package/claude-skill/material-design/references/component-patterns.md +55 -0
- package/claude-skill/material-design/references/motion-guide.md +163 -0
- package/claude-skill/material-design/references/tokens-and-styles.md +68 -0
- package/dist/animation/Shapes.stories.svelte +10 -6
- package/dist/animation/TransitionPatterns.stories.svelte +30 -20
- package/dist/animation/containerTransform.d.ts +4 -2
- package/dist/animation/containerTransform.js +4 -2
- package/dist/animation/enterExit.js +5 -2
- package/dist/animation/skeleton.d.ts +1 -1
- package/dist/animation/skeleton.js +1 -1
- package/dist/components/badge/Badge.mdx +70 -0
- package/dist/components/badge/Badge.stories.svelte +38 -20
- package/dist/components/badge/Badge.svelte +12 -5
- package/dist/components/badge/theme.d.ts +30 -7
- package/dist/components/badge/theme.js +25 -5
- package/dist/components/badge/types.d.ts +18 -4
- package/dist/components/buttons/Button.mdx +85 -0
- package/dist/components/buttons/Button.stories.svelte +62 -27
- package/dist/components/buttons/Button.svelte +29 -25
- package/dist/components/buttons/Button.svelte.d.ts +11 -9
- package/dist/components/buttons/ButtonIcon.mdx +52 -0
- package/dist/components/buttons/ButtonIcon.stories.svelte +72 -48
- package/dist/components/buttons/ButtonIcon.svelte +58 -36
- package/dist/components/buttons/ButtonIcon.svelte.d.ts +9 -7
- package/dist/components/buttons/FAB.mdx +84 -0
- package/dist/components/buttons/FAB.stories.svelte +103 -24
- package/dist/components/buttons/FAB.stories.svelte.d.ts +2 -17
- package/dist/components/buttons/FAB.svelte +353 -29
- package/dist/components/buttons/FAB.svelte.d.ts +11 -6
- package/dist/components/buttons/FABMenu.svelte +27 -8
- package/dist/components/buttons/FABMenu.svelte.d.ts +7 -3
- package/dist/components/buttons/FABMenuItem.svelte +20 -16
- package/dist/components/buttons/FABMenuItem.svelte.d.ts +3 -3
- package/dist/components/buttons/Toggle.stories.svelte +31 -23
- package/dist/components/buttons/Toggle.stories.svelte.d.ts +2 -17
- package/dist/components/buttons/Toggle.svelte +28 -25
- package/dist/components/buttons/Toggle.svelte.d.ts +5 -5
- package/dist/components/buttons/button-group/ButtonGroup.mdx +39 -0
- package/dist/components/buttons/button-group/ButtonGroup.stories.svelte +62 -43
- package/dist/components/buttons/button-group/ButtonGroup.stories.svelte.d.ts +2 -17
- package/dist/components/buttons/button-group/ButtonGroup.svelte +102 -8
- package/dist/components/buttons/button-group/ButtonGroup.svelte.d.ts +6 -7
- package/dist/components/buttons/button-group/theme.d.ts +46 -16
- package/dist/components/buttons/button-group/theme.js +14 -9
- package/dist/components/buttons/button-group/types.d.ts +13 -7
- package/dist/components/buttons/connected/ConnectedButtonGroup.mdx +43 -0
- package/dist/components/buttons/connected/ConnectedButtonGroup.stories.svelte +56 -74
- package/dist/components/buttons/connected/ConnectedButtonGroup.stories.svelte.d.ts +2 -17
- package/dist/components/buttons/connected/ConnectedButtonGroup.svelte +16 -4
- package/dist/components/buttons/connected/ConnectedButtonGroup.svelte.d.ts +4 -4
- package/dist/components/buttons/connected/ConnectedButtonGroupItem.svelte +35 -8
- package/dist/components/buttons/connected/ConnectedButtonGroupItem.svelte.d.ts +2 -3
- package/dist/components/buttons/connected/theme.d.ts +34 -19
- package/dist/components/buttons/connected/theme.js +33 -10
- package/dist/components/buttons/connected/types.d.ts +36 -9
- package/dist/components/buttons/shapeMorph.d.ts +26 -0
- package/dist/components/buttons/shapeMorph.js +142 -0
- package/dist/components/buttons/split-button/SplitButton.mdx +48 -0
- package/dist/components/buttons/split-button/SplitButton.stories.svelte +9 -14
- package/dist/components/buttons/split-button/SplitButton.svelte +66 -49
- package/dist/components/buttons/split-button/SplitButton.svelte.d.ts +6 -11
- package/dist/components/buttons/split-button/theme.d.ts +111 -18
- package/dist/components/buttons/split-button/theme.js +75 -17
- package/dist/components/buttons/split-button/types.d.ts +24 -18
- package/dist/components/buttons/theme.d.ts +423 -231
- package/dist/components/buttons/theme.js +287 -381
- package/dist/components/buttons/types.d.ts +130 -125
- package/dist/components/cards/Card.mdx +44 -0
- package/dist/components/cards/Card.stories.svelte +11 -11
- package/dist/components/cards/theme.js +6 -6
- package/dist/components/chips/Chip.mdx +68 -0
- package/dist/components/chips/Chip.stories.svelte +4 -4
- package/dist/components/chips/theme.d.ts +1 -1
- package/dist/components/chips/theme.js +4 -4
- package/dist/components/containers/action-rail/ActionRail.stories.svelte +1 -0
- package/dist/components/containers/action-rail/theme.d.ts +1 -1
- package/dist/components/containers/action-rail/theme.js +2 -2
- package/dist/components/containers/app/theme.d.ts +1 -1
- package/dist/components/containers/app/theme.js +1 -1
- package/dist/components/containers/bottom-sheet/BottomSheet.mdx +64 -0
- package/dist/components/containers/bottom-sheet/BottomSheet.stories.svelte +108 -12
- package/dist/components/containers/bottom-sheet/BottomSheet.svelte +179 -109
- package/dist/components/containers/bottom-sheet/BottomSheet.svelte.d.ts +10 -5
- package/dist/components/containers/bottom-sheet/index.d.ts +1 -0
- package/dist/components/containers/bottom-sheet/index.js +1 -0
- package/dist/components/containers/bottom-sheet/theme.d.ts +45 -0
- package/dist/components/containers/bottom-sheet/theme.js +42 -0
- package/dist/components/containers/bottom-sheet/types.d.ts +37 -5
- package/dist/components/containers/carousel/Carousel.mdx +80 -0
- package/dist/components/containers/carousel/Carousel.stories.svelte +131 -0
- package/dist/components/containers/carousel/Carousel.stories.svelte.d.ts +4 -0
- package/dist/components/containers/carousel/Carousel.svelte +194 -0
- package/dist/components/containers/carousel/Carousel.svelte.d.ts +25 -0
- package/dist/components/containers/carousel/index.d.ts +3 -0
- package/dist/components/containers/{stack → carousel}/index.js +1 -2
- package/dist/components/containers/carousel/keylines.d.ts +32 -0
- package/dist/components/containers/carousel/keylines.js +88 -0
- package/dist/components/containers/carousel/theme.d.ts +162 -0
- package/dist/components/containers/carousel/theme.js +67 -0
- package/dist/components/containers/carousel/types.d.ts +52 -0
- package/dist/components/containers/context-menu/ContextMenu.stories.svelte +1 -0
- package/dist/components/containers/context-menu/ContextMenu.svelte +2 -2
- package/dist/components/containers/context-menu/ContextMenu.svelte.d.ts +1 -1
- package/dist/components/containers/context-menu/theme.d.ts +1 -1
- package/dist/components/containers/context-menu/theme.js +11 -11
- package/dist/components/containers/dialogue/Dialogue.mdx +65 -0
- package/dist/components/containers/dialogue/Dialogue.stories.svelte +4 -4
- package/dist/components/containers/dialogue/Dialogue.svelte +2 -2
- package/dist/components/containers/dialogue/theme.d.ts +1 -1
- package/dist/components/containers/dialogue/theme.js +4 -4
- package/dist/components/containers/dialogue/types.d.ts +1 -1
- package/dist/components/containers/divider/Divider.stories.svelte +2 -1
- package/dist/components/containers/divider/Divider.svelte +2 -2
- package/dist/components/containers/divider/theme.d.ts +7 -7
- package/dist/components/containers/divider/theme.js +3 -3
- package/dist/components/containers/index.d.ts +1 -1
- package/dist/components/containers/index.js +1 -1
- package/dist/components/containers/link-preview/theme.d.ts +1 -1
- package/dist/components/containers/link-preview/theme.js +3 -3
- package/dist/components/containers/list/List.svelte +18 -0
- package/dist/components/containers/list/List.svelte.d.ts +4 -0
- package/dist/components/containers/list/ListItem.mdx +100 -0
- package/dist/components/containers/list/ListItem.stories.svelte +177 -42
- package/dist/components/containers/list/ListItem.stories.svelte.d.ts +2 -17
- package/dist/components/containers/list/ListItem.svelte +92 -37
- package/dist/components/containers/list/ListItem.svelte.d.ts +1 -1
- package/dist/components/containers/list/context.d.ts +6 -0
- package/dist/components/containers/list/context.js +4 -0
- package/dist/components/containers/list/index.d.ts +1 -0
- package/dist/components/containers/list/index.js +1 -0
- package/dist/components/containers/list/theme.d.ts +487 -12
- package/dist/components/containers/list/theme.js +141 -14
- package/dist/components/containers/list/types.d.ts +39 -5
- package/dist/components/containers/menu/Menu.mdx +52 -0
- package/dist/components/containers/menu/Menu.stories.svelte +14 -14
- package/dist/components/containers/menu/Menu.svelte +2 -2
- package/dist/components/containers/menu/MenuGroup.svelte +1 -1
- package/dist/components/containers/menu/MenuGroup.svelte.d.ts +1 -1
- package/dist/components/containers/menu/MenuSub.svelte +1 -1
- package/dist/components/containers/menu/menu-item/MenuItem.svelte +1 -1
- package/dist/components/containers/menu/theme.d.ts +1 -1
- package/dist/components/containers/menu/theme.js +9 -9
- package/dist/components/containers/pane/DraggablePane.stories.svelte +4 -3
- package/dist/components/containers/pane/DraggablePane.svelte +2 -2
- package/dist/components/containers/pane/Pane.stories.svelte +11 -10
- package/dist/components/containers/pane/Pane.svelte +24 -2
- package/dist/components/containers/pane/PaneGrid.stories.svelte +19 -18
- package/dist/components/containers/pane/PaneGrid.svelte +3 -2
- package/dist/components/containers/pane/PaneGrid.svelte.d.ts +2 -1
- package/dist/components/containers/pane/PaneHandle.svelte +48 -2
- package/dist/components/containers/pane/PaneHandle.svelte.d.ts +4 -0
- package/dist/components/containers/pane/resizeStore.svelte.d.ts +10 -1
- package/dist/components/containers/pane/resizeStore.svelte.js +13 -2
- package/dist/components/containers/pane/theme.d.ts +1 -1
- package/dist/components/containers/pane/theme.js +131 -47
- package/dist/components/containers/pane/types.d.ts +3 -2
- package/dist/components/containers/popover/Popover.mdx +45 -0
- package/dist/components/containers/popover/Popover.stories.svelte +1 -1
- package/dist/components/containers/popover/Popover.svelte +1 -1
- package/dist/components/containers/popover/theme.d.ts +1 -1
- package/dist/components/containers/popover/theme.js +4 -4
- package/dist/components/containers/scroll-area/theme.js +3 -3
- package/dist/components/containers/side-sheet/SideSheet.mdx +71 -0
- package/dist/components/containers/side-sheet/SideSheet.stories.svelte +113 -17
- package/dist/components/containers/side-sheet/SideSheet.svelte +113 -66
- package/dist/components/containers/side-sheet/SideSheet.svelte.d.ts +8 -7
- package/dist/components/containers/side-sheet/index.d.ts +1 -0
- package/dist/components/containers/side-sheet/index.js +1 -0
- package/dist/components/containers/side-sheet/theme.d.ts +108 -0
- package/dist/components/containers/side-sheet/theme.js +72 -0
- package/dist/components/containers/side-sheet/types.d.ts +35 -7
- package/dist/components/date/DateField.stories.svelte +4 -3
- package/dist/components/date/DateField.svelte +11 -2
- package/dist/components/date/DateRangeField.stories.svelte +4 -3
- package/dist/components/date/DateRangeField.svelte +12 -3
- package/dist/components/date/theme.d.ts +8 -8
- package/dist/components/date/theme.js +32 -32
- package/dist/components/forms/checkbox/Checkbox.mdx +35 -0
- package/dist/components/forms/checkbox/Checkbox.stories.svelte +2 -2
- package/dist/components/forms/checkbox/Checkbox.svelte +1 -1
- package/dist/components/forms/checkbox/theme.d.ts +1 -1
- package/dist/components/forms/checkbox/theme.js +4 -4
- package/dist/components/forms/command/Command.stories.svelte +1 -0
- package/dist/components/forms/command/theme.d.ts +1 -1
- package/dist/components/forms/command/theme.js +10 -10
- package/dist/components/forms/pin/theme.d.ts +1 -1
- package/dist/components/forms/pin/theme.js +5 -5
- package/dist/components/forms/radio-group/RadioGroup.svelte +1 -1
- package/dist/components/forms/radio-group/theme.d.ts +1 -1
- package/dist/components/forms/radio-group/theme.js +6 -6
- package/dist/components/forms/search/Search.mdx +38 -0
- package/dist/components/forms/search/Search.stories.svelte +19 -9
- package/dist/components/forms/search/Search.svelte +40 -17
- package/dist/components/forms/search/Search.svelte.d.ts +2 -2
- package/dist/components/forms/search/theme.d.ts +46 -13
- package/dist/components/forms/search/theme.js +14 -9
- package/dist/components/forms/search/types.d.ts +18 -12
- package/dist/components/forms/select/Select.mdx +53 -0
- package/dist/components/forms/select/Select.stories.svelte +4 -4
- package/dist/components/forms/select/Select.svelte +12 -4
- package/dist/components/forms/select/SelectItem.svelte +1 -1
- package/dist/components/forms/select/theme.d.ts +1 -1
- package/dist/components/forms/select/theme.js +14 -14
- package/dist/components/forms/slider/Slider.mdx +85 -0
- package/dist/components/forms/slider/Slider.stories.svelte +7 -7
- package/dist/components/forms/slider/Slider.svelte +46 -28
- package/dist/components/forms/slider/theme.d.ts +15 -1
- package/dist/components/forms/slider/theme.js +29 -18
- package/dist/components/forms/slider/types.d.ts +3 -2
- package/dist/components/forms/switch/Switch.mdx +38 -0
- package/dist/components/forms/switch/Switch.stories.svelte +3 -3
- package/dist/components/forms/switch/theme.d.ts +1 -1
- package/dist/components/forms/switch/theme.js +7 -7
- package/dist/components/forms/textfield/Textfield.mdx +53 -0
- package/dist/components/forms/textfield/Textfield.stories.svelte +6 -6
- package/dist/components/forms/textfield/Textfield.svelte +1 -0
- package/dist/components/forms/textfield/theme.d.ts +1 -1
- package/dist/components/forms/textfield/theme.js +20 -20
- package/dist/components/forms/toggle-group/theme.d.ts +1 -1
- package/dist/components/forms/toggle-group/theme.js +3 -3
- package/dist/components/forms/tooltip/Tooltip.stories.svelte +1 -0
- package/dist/components/forms/tooltip/theme.d.ts +1 -1
- package/dist/components/forms/tooltip/theme.js +4 -4
- package/dist/components/misc/Avatar.stories.svelte +5 -4
- package/dist/components/misc/ThemeSettings.svelte +9 -9
- package/dist/components/misc/ThemeSwitcher.svelte +3 -3
- package/dist/components/misc/theme.js +5 -5
- package/dist/components/nav/appbar/AppBar.mdx +71 -0
- package/dist/components/nav/appbar/AppBar.stories.svelte +93 -3
- package/dist/components/nav/appbar/AppBar.stories.svelte.d.ts +2 -17
- package/dist/components/nav/appbar/AppBar.svelte +90 -37
- package/dist/components/nav/appbar/AppBar.svelte.d.ts +9 -2
- package/dist/components/nav/appbar/theme.d.ts +86 -19
- package/dist/components/nav/appbar/theme.js +160 -24
- package/dist/components/nav/appbar/types.d.ts +46 -9
- package/dist/components/nav/breadcrumb/Breadcrumb.stories.svelte +1 -0
- package/dist/components/nav/breadcrumb/theme.d.ts +1 -1
- package/dist/components/nav/breadcrumb/theme.js +6 -6
- package/dist/components/nav/navbar/Navbar.mdx +38 -0
- package/dist/components/nav/navbar/Navbar.svelte +1 -1
- package/dist/components/nav/navbar/NavbarItem.svelte +12 -9
- package/dist/components/nav/navbar/theme.d.ts +3 -3
- package/dist/components/nav/navbar/theme.js +7 -7
- package/dist/components/nav/rail/Rail.mdx +73 -0
- package/dist/components/nav/rail/Rail.stories.svelte +3 -7
- package/dist/components/nav/rail/Rail.svelte +5 -2
- package/dist/components/nav/rail/RailItem.svelte +12 -9
- package/dist/components/nav/rail/theme.d.ts +1 -1
- package/dist/components/nav/rail/theme.js +14 -14
- package/dist/components/nav/rail/types.d.ts +8 -1
- package/dist/components/nav/tabs/Tabs.mdx +62 -0
- package/dist/components/nav/tabs/Tabs.stories.svelte +1 -1
- package/dist/components/nav/tabs/theme.d.ts +1 -1
- package/dist/components/nav/tabs/theme.js +5 -5
- package/dist/components/pill/Pill.mdx +32 -0
- package/dist/components/pill/Pill.stories.svelte +1 -1
- package/dist/components/pill/theme.d.ts +2 -2
- package/dist/components/pill/theme.js +2 -2
- package/dist/components/progress/LinearProgress.svelte +2 -2
- package/dist/components/progress/Progress.mdx +50 -0
- package/dist/components/progress/Progress.stories.svelte +6 -6
- package/dist/components/snackbar/Snackbar.mdx +52 -0
- package/dist/components/snackbar/Snackbar.stories.svelte +5 -5
- package/dist/components/snackbar/Snackbar.svelte +1 -1
- package/dist/components/snackbar/theme.d.ts +4 -4
- package/dist/components/snackbar/theme.js +5 -5
- package/dist/components/table/Table.stories.svelte +1 -0
- package/dist/components/table/TableHeader.svelte +1 -1
- package/dist/components/table/theme.d.ts +1 -1
- package/dist/components/table/theme.js +4 -4
- package/dist/components/time/TimeField.stories.svelte +3 -2
- package/dist/components/time/TimeField.svelte +2 -2
- package/dist/components/time/TimepickerInput.svelte +1 -1
- package/dist/components/time/theme.d.ts +1 -1
- package/dist/components/time/theme.js +6 -6
- package/dist/components/toolbar/Toolbar.stories.svelte +1 -0
- package/dist/components/toolbar/Toolbar.svelte +1 -1
- package/dist/components/toolbar/Toolbar.svelte.d.ts +1 -1
- package/dist/components/toolbar/theme.d.ts +1 -1
- package/dist/components/toolbar/theme.js +15 -15
- package/dist/components/typography/Typography.mdx +67 -0
- package/dist/components/typography/body/Body.stories.svelte +2 -1
- package/dist/components/typography/body/theme.d.ts +16 -13
- package/dist/components/typography/body/theme.js +20 -5
- package/dist/components/typography/body/types.d.ts +2 -1
- package/dist/components/typography/display/Display.stories.svelte +2 -1
- package/dist/components/typography/display/theme.d.ts +16 -13
- package/dist/components/typography/display/theme.js +20 -5
- package/dist/components/typography/display/types.d.ts +2 -1
- package/dist/components/typography/headline/Headline.stories.svelte +2 -1
- package/dist/components/typography/headline/theme.d.ts +16 -13
- package/dist/components/typography/headline/theme.js +20 -5
- package/dist/components/typography/headline/types.d.ts +2 -1
- package/dist/components/typography/kbd/Kbd.stories.svelte +2 -1
- package/dist/components/typography/kbd/theme.d.ts +5 -5
- package/dist/components/typography/kbd/theme.js +3 -3
- package/dist/components/typography/label/Label.stories.svelte +2 -1
- package/dist/components/typography/label/theme.d.ts +15 -12
- package/dist/components/typography/label/theme.js +20 -5
- package/dist/components/typography/label/types.d.ts +2 -1
- package/dist/components/typography/title/Title.stories.svelte +2 -1
- package/dist/components/typography/title/theme.d.ts +16 -13
- package/dist/components/typography/title/theme.js +20 -5
- package/dist/components/typography/title/types.d.ts +2 -1
- package/dist/index.css +2 -0
- package/dist/styles/component.css +78 -175
- package/dist/styles/elevation.css +9 -0
- package/dist/styles/layers.css +33 -0
- package/dist/styles/spacing.css +29 -0
- package/dist/styles/typescale.css +635 -20
- package/dist/utils/Layer.svelte +1 -1
- package/dist/utils/icon/Icon.svelte +8 -6
- package/dist/utils/icon/theme.d.ts +1 -1
- package/dist/utils/icon/theme.js +1 -1
- package/dist/utils/tv.d.ts +6 -0
- package/dist/utils/tv.js +12 -0
- package/package.json +19 -15
- package/dist/components/containers/stack/HStack.svelte +0 -23
- package/dist/components/containers/stack/HStack.svelte.d.ts +0 -5
- package/dist/components/containers/stack/VStack.svelte +0 -23
- package/dist/components/containers/stack/VStack.svelte.d.ts +0 -5
- package/dist/components/containers/stack/index.d.ts +0 -4
- package/dist/components/containers/stack/theme.d.ts +0 -66
- package/dist/components/containers/stack/theme.js +0 -26
- package/dist/components/containers/stack/types.d.ts +0 -12
- /package/dist/components/containers/{stack → carousel}/types.js +0 -0
|
@@ -1,38 +1,174 @@
|
|
|
1
|
-
import { tv } from '
|
|
1
|
+
import { tv } from '../../../utils/tv.js';
|
|
2
|
+
/*
|
|
3
|
+
M3 Expressive app bar (https://m3.material.io/components/app-bars/specs), laid out on one
|
|
4
|
+
3-column grid (leading · text · trailing) so the size can change per breakpoint in CSS alone:
|
|
5
|
+
- small: 64dp, one row, title between the buttons.
|
|
6
|
+
- medium/large flexible: an actions row (8dp top, 48dp) above a headline block spanning all
|
|
7
|
+
columns (16dp inset, 12dp bottom) that wraps and grows; min height 112/120dp, or 136/152dp
|
|
8
|
+
with a subtitle.
|
|
9
|
+
4dp container padding and 0 gap between 48dp icon buttons throughout. Every class below is a
|
|
10
|
+
literal so the Tailwind scanner sees it; `appbarSize` picks them per breakpoint.
|
|
11
|
+
*/
|
|
12
|
+
const sizeClasses = {
|
|
13
|
+
small: {
|
|
14
|
+
small: {
|
|
15
|
+
row: 'grid-rows-[4rem] pt-spacing-0 min-h-spacing-800',
|
|
16
|
+
rowSubtitle: '',
|
|
17
|
+
textContainer: 'col-start-2 col-span-1 row-start-1 self-center ps-(--lead) pe-(--trail) pt-spacing-0 pb-spacing-0',
|
|
18
|
+
title: 'md-sys-typescale-title-large line-clamp-1',
|
|
19
|
+
subtitle: 'md-sys-typescale-label-medium line-clamp-1'
|
|
20
|
+
},
|
|
21
|
+
medium: {
|
|
22
|
+
row: 'grid-rows-[3rem_1fr] pt-spacing-100 min-h-28',
|
|
23
|
+
rowSubtitle: 'min-h-34',
|
|
24
|
+
textContainer: 'col-start-1 col-span-3 row-start-2 self-end ps-spacing-200 pe-spacing-200 pt-spacing-50 pb-spacing-150',
|
|
25
|
+
title: 'md-sys-typescale-headline-medium line-clamp-none',
|
|
26
|
+
subtitle: 'md-sys-typescale-title-small line-clamp-none'
|
|
27
|
+
},
|
|
28
|
+
large: {
|
|
29
|
+
row: 'grid-rows-[3rem_1fr] pt-spacing-100 min-h-30',
|
|
30
|
+
rowSubtitle: 'min-h-38',
|
|
31
|
+
textContainer: 'col-start-1 col-span-3 row-start-2 self-end ps-spacing-200 pe-spacing-200 pt-spacing-50 pb-spacing-150',
|
|
32
|
+
title: 'md-sys-typescale-display-small line-clamp-none',
|
|
33
|
+
subtitle: 'md-sys-typescale-title-medium line-clamp-none'
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
medium: {
|
|
37
|
+
small: {
|
|
38
|
+
row: 'md:grid-rows-[4rem] md:pt-spacing-0 md:min-h-spacing-800',
|
|
39
|
+
rowSubtitle: '',
|
|
40
|
+
textContainer: 'md:col-start-2 md:col-span-1 md:row-start-1 md:self-center md:ps-(--lead) md:pe-(--trail) md:pt-spacing-0 md:pb-spacing-0',
|
|
41
|
+
title: 'md:md-sys-typescale-title-large md:line-clamp-1',
|
|
42
|
+
subtitle: 'md:md-sys-typescale-label-medium md:line-clamp-1'
|
|
43
|
+
},
|
|
44
|
+
medium: {
|
|
45
|
+
row: 'md:grid-rows-[3rem_1fr] md:pt-spacing-100 md:min-h-28',
|
|
46
|
+
rowSubtitle: 'md:min-h-34',
|
|
47
|
+
textContainer: 'md:col-start-1 md:col-span-3 md:row-start-2 md:self-end md:ps-spacing-200 md:pe-spacing-200 md:pt-spacing-50 md:pb-spacing-150',
|
|
48
|
+
title: 'md:md-sys-typescale-headline-medium md:line-clamp-none',
|
|
49
|
+
subtitle: 'md:md-sys-typescale-title-small md:line-clamp-none'
|
|
50
|
+
},
|
|
51
|
+
large: {
|
|
52
|
+
row: 'md:grid-rows-[3rem_1fr] md:pt-spacing-100 md:min-h-30',
|
|
53
|
+
rowSubtitle: 'md:min-h-38',
|
|
54
|
+
textContainer: 'md:col-start-1 md:col-span-3 md:row-start-2 md:self-end md:ps-spacing-200 md:pe-spacing-200 md:pt-spacing-50 md:pb-spacing-150',
|
|
55
|
+
title: 'md:md-sys-typescale-display-small md:line-clamp-none',
|
|
56
|
+
subtitle: 'md:md-sys-typescale-title-medium md:line-clamp-none'
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
large: {
|
|
60
|
+
small: {
|
|
61
|
+
row: 'lg:grid-rows-[4rem] lg:pt-spacing-0 lg:min-h-spacing-800',
|
|
62
|
+
rowSubtitle: '',
|
|
63
|
+
textContainer: 'lg:col-start-2 lg:col-span-1 lg:row-start-1 lg:self-center lg:ps-(--lead) lg:pe-(--trail) lg:pt-spacing-0 lg:pb-spacing-0',
|
|
64
|
+
title: 'lg:md-sys-typescale-title-large lg:line-clamp-1',
|
|
65
|
+
subtitle: 'lg:md-sys-typescale-label-medium lg:line-clamp-1'
|
|
66
|
+
},
|
|
67
|
+
medium: {
|
|
68
|
+
row: 'lg:grid-rows-[3rem_1fr] lg:pt-spacing-100 lg:min-h-28',
|
|
69
|
+
rowSubtitle: 'lg:min-h-34',
|
|
70
|
+
textContainer: 'lg:col-start-1 lg:col-span-3 lg:row-start-2 lg:self-end lg:ps-spacing-200 lg:pe-spacing-200 lg:pt-spacing-50 lg:pb-spacing-150',
|
|
71
|
+
title: 'lg:md-sys-typescale-headline-medium lg:line-clamp-none',
|
|
72
|
+
subtitle: 'lg:md-sys-typescale-title-small lg:line-clamp-none'
|
|
73
|
+
},
|
|
74
|
+
large: {
|
|
75
|
+
row: 'lg:grid-rows-[3rem_1fr] lg:pt-spacing-100 lg:min-h-30',
|
|
76
|
+
rowSubtitle: 'lg:min-h-38',
|
|
77
|
+
textContainer: 'lg:col-start-1 lg:col-span-3 lg:row-start-2 lg:self-end lg:ps-spacing-200 lg:pe-spacing-200 lg:pt-spacing-50 lg:pb-spacing-150',
|
|
78
|
+
title: 'lg:md-sys-typescale-display-small lg:line-clamp-none',
|
|
79
|
+
subtitle: 'lg:md-sys-typescale-title-medium lg:line-clamp-none'
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
extraLarge: {
|
|
83
|
+
small: {
|
|
84
|
+
row: 'xl:grid-rows-[4rem] xl:pt-spacing-0 xl:min-h-spacing-800',
|
|
85
|
+
rowSubtitle: '',
|
|
86
|
+
textContainer: 'xl:col-start-2 xl:col-span-1 xl:row-start-1 xl:self-center xl:ps-(--lead) xl:pe-(--trail) xl:pt-spacing-0 xl:pb-spacing-0',
|
|
87
|
+
title: 'xl:md-sys-typescale-title-large xl:line-clamp-1',
|
|
88
|
+
subtitle: 'xl:md-sys-typescale-label-medium xl:line-clamp-1'
|
|
89
|
+
},
|
|
90
|
+
medium: {
|
|
91
|
+
row: 'xl:grid-rows-[3rem_1fr] xl:pt-spacing-100 xl:min-h-28',
|
|
92
|
+
rowSubtitle: 'xl:min-h-34',
|
|
93
|
+
textContainer: 'xl:col-start-1 xl:col-span-3 xl:row-start-2 xl:self-end xl:ps-spacing-200 xl:pe-spacing-200 xl:pt-spacing-50 xl:pb-spacing-150',
|
|
94
|
+
title: 'xl:md-sys-typescale-headline-medium xl:line-clamp-none',
|
|
95
|
+
subtitle: 'xl:md-sys-typescale-title-small xl:line-clamp-none'
|
|
96
|
+
},
|
|
97
|
+
large: {
|
|
98
|
+
row: 'xl:grid-rows-[3rem_1fr] xl:pt-spacing-100 xl:min-h-30',
|
|
99
|
+
rowSubtitle: 'xl:min-h-38',
|
|
100
|
+
textContainer: 'xl:col-start-1 xl:col-span-3 xl:row-start-2 xl:self-end xl:ps-spacing-200 xl:pe-spacing-200 xl:pt-spacing-50 xl:pb-spacing-150',
|
|
101
|
+
title: 'xl:md-sys-typescale-display-small xl:line-clamp-none',
|
|
102
|
+
subtitle: 'xl:md-sys-typescale-title-medium xl:line-clamp-none'
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
/**
|
|
107
|
+
* Resolves `size` (one value, or one per breakpoint like `PaneGrid`'s props) into per-slot
|
|
108
|
+
* classes. Sizes cascade upward from the smallest breakpoint given, like Tailwind prefixes.
|
|
109
|
+
*/
|
|
110
|
+
export function appbarSize(size, hasSubtitle) {
|
|
111
|
+
const tiers = typeof size === 'string' ? { small: size } : { small: 'small', ...size };
|
|
112
|
+
const pick = (slot) => Object.entries(tiers)
|
|
113
|
+
.map(([bp, s]) => sizeClasses[bp][s][slot])
|
|
114
|
+
.join(' ');
|
|
115
|
+
return {
|
|
116
|
+
row: `${pick('row')} ${hasSubtitle ? pick('rowSubtitle') : ''}`,
|
|
117
|
+
textContainer: pick('textContainer'),
|
|
118
|
+
title: pick('title'),
|
|
119
|
+
subtitle: pick('subtitle')
|
|
120
|
+
};
|
|
121
|
+
}
|
|
2
122
|
export const appbar = tv({
|
|
3
123
|
slots: {
|
|
4
|
-
base: 'fixed top-0 left-0 w-full flex flex-col z-
|
|
5
|
-
row: '
|
|
6
|
-
childrenRow: 'w-full px-
|
|
124
|
+
base: 'fixed top-spacing-0 left-spacing-0 w-full flex flex-col z-layer-bar transition-colors md-sys-motion-effects',
|
|
125
|
+
row: 'grid w-full items-center px-spacing-50',
|
|
126
|
+
childrenRow: 'w-full px-spacing-100 pb-spacing-100',
|
|
7
127
|
ghost: 'w-full shrink-0 pointer-events-none',
|
|
8
|
-
textContainer: 'flex flex-col
|
|
9
|
-
title: 'text-md-sys-color-on-surface
|
|
10
|
-
subtitle: 'text-md-sys-color-on-surface-variant
|
|
11
|
-
leading: 'text-md-sys-color-on-surface
|
|
12
|
-
trailing: 'text-md-sys-color-on-surface-variant
|
|
128
|
+
textContainer: 'flex min-w-spacing-0 flex-col gap-spacing-25 [--lead:0.25rem] [--trail:0.25rem]',
|
|
129
|
+
title: 'text-md-sys-color-on-surface',
|
|
130
|
+
subtitle: 'text-md-sys-color-on-surface-variant',
|
|
131
|
+
leading: 'text-md-sys-color-on-surface col-start-1 row-start-1 flex shrink-0 items-center justify-self-start',
|
|
132
|
+
trailing: 'text-md-sys-color-on-surface-variant col-start-3 row-start-1 flex shrink-0 items-center justify-self-end',
|
|
133
|
+
search: 'state-layer relative flex h-spacing-700 w-full min-w-spacing-0 cursor-text items-center rounded-full ps-spacing-200 pe-spacing-200 transition-colors md-sys-motion-effects before:rounded-full hover:before:bg-md-sys-color-on-surface/8 focus-within:outline-3 focus-within:outline-offset-2 focus-within:outline-md-sys-color-secondary',
|
|
134
|
+
searchInput: 'md-sys-typescale-body-large text-md-sys-color-on-surface placeholder:text-md-sys-color-on-surface-variant w-full min-w-spacing-0 bg-transparent text-start outline-none placeholder-shown:text-center [&::-webkit-search-cancel-button]:hidden',
|
|
135
|
+
searchTrailing: 'text-md-sys-color-on-surface-variant flex shrink-0 items-center'
|
|
13
136
|
},
|
|
14
137
|
variants: {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}
|
|
20
|
-
},
|
|
21
|
-
searchContainer: {
|
|
22
|
-
true: '',
|
|
23
|
-
false: ''
|
|
138
|
+
align: {
|
|
139
|
+
start: { row: 'grid-cols-[auto_1fr_auto]', textContainer: 'items-start text-start' },
|
|
140
|
+
// 1fr side columns centre a small bar's title on the bar, not between uneven button groups.
|
|
141
|
+
center: { row: 'grid-cols-[1fr_auto_1fr]', textContainer: 'items-center text-center' }
|
|
24
142
|
},
|
|
25
|
-
|
|
143
|
+
scrolled: {
|
|
26
144
|
true: {
|
|
27
|
-
|
|
145
|
+
base: 'bg-md-sys-color-surface-container',
|
|
146
|
+
search: 'bg-md-sys-color-surface-container-highest'
|
|
28
147
|
},
|
|
29
|
-
false: ''
|
|
148
|
+
false: { base: 'bg-md-sys-color-surface', search: 'bg-md-sys-color-surface-container' }
|
|
30
149
|
},
|
|
31
|
-
|
|
150
|
+
// Search app bar: the search container fills the text column, 8dp from the buttons.
|
|
151
|
+
searchContainer: {
|
|
32
152
|
true: {
|
|
33
|
-
|
|
153
|
+
row: 'grid-cols-[auto_1fr_auto]',
|
|
154
|
+
textContainer: '[--lead:0.5rem] [--trail:0.5rem]'
|
|
34
155
|
},
|
|
35
156
|
false: ''
|
|
36
|
-
}
|
|
157
|
+
},
|
|
158
|
+
hasSearchTrailing: { true: { search: 'pe-spacing-50' }, false: '' },
|
|
159
|
+
noTrailing: { true: '', false: '' },
|
|
160
|
+
noLeading: { true: '', false: '' }
|
|
161
|
+
},
|
|
162
|
+
compoundVariants: [
|
|
163
|
+
// A title with no button beside it sits at the 16dp inset.
|
|
164
|
+
{ align: 'start', noLeading: true, class: { textContainer: '[--lead:1rem]' } },
|
|
165
|
+
{ align: 'start', noTrailing: true, class: { textContainer: '[--trail:1rem]' } },
|
|
166
|
+
{ searchContainer: true, noLeading: true, class: { textContainer: '[--lead:0.75rem]' } },
|
|
167
|
+
{ searchContainer: true, noTrailing: true, class: { textContainer: '[--trail:0.75rem]' } }
|
|
168
|
+
],
|
|
169
|
+
defaultVariants: {
|
|
170
|
+
align: 'start',
|
|
171
|
+
scrolled: false,
|
|
172
|
+
searchContainer: false
|
|
37
173
|
}
|
|
38
174
|
});
|
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
|
-
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
-
import type {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
*/
|
|
7
|
-
export type AppBarProps = AppbarVariants & HTMLAttributes<HTMLElementTagNameMap['nav']> & {
|
|
2
|
+
import type { HTMLAttributes, HTMLInputAttributes } from 'svelte/elements';
|
|
3
|
+
import type { Responsive } from '../../containers/pane/theme.js';
|
|
4
|
+
import type { AppBarSize, AppbarVariants } from './theme.js';
|
|
5
|
+
type AppBarBaseProps = Pick<AppbarVariants, 'align'> & HTMLAttributes<HTMLElementTagNameMap['nav']> & {
|
|
8
6
|
/** Extra content rendered in a full-width row below the title, e.g. a Breadcrumb trail. */
|
|
9
7
|
children?: Snippet;
|
|
10
|
-
/** The main title of the app bar. */
|
|
11
|
-
title: string;
|
|
12
8
|
/** An optional subtitle displayed below the title. */
|
|
13
9
|
subtitle?: string;
|
|
14
10
|
/** Additional props for the title `<h1>` element (e.g. `data-cy`). */
|
|
@@ -19,10 +15,51 @@ export type AppBarProps = AppbarVariants & HTMLAttributes<HTMLElementTagNameMap[
|
|
|
19
15
|
leading?: Snippet;
|
|
20
16
|
/** A snippet to be rendered on the right side (e.g., action icons). */
|
|
21
17
|
trailing?: Snippet;
|
|
22
|
-
/**
|
|
18
|
+
/** Renders a back button in the leading section (ignored when `leading` is set). */
|
|
23
19
|
showBack?: boolean;
|
|
20
|
+
/** Called by the back button. Defaults to `history.back()`. */
|
|
21
|
+
onback?: () => void;
|
|
22
|
+
/**
|
|
23
|
+
* The element whose scroll switches the bar to its on-scroll color. Defaults to the page
|
|
24
|
+
* (`window`); pass a scrolling container, e.g. a `Pane`'s element, when content scrolls there.
|
|
25
|
+
*/
|
|
26
|
+
scrollContainer?: HTMLElement | null;
|
|
24
27
|
/** Renders an invisible same-height spacer after the fixed bar so page content isn't obscured. */
|
|
25
28
|
ghost?: boolean;
|
|
26
29
|
/** Additional classes passed onto the row element */
|
|
27
30
|
rowClass?: string;
|
|
28
31
|
};
|
|
32
|
+
/** A titled app bar: small, or the Expressive medium/large flexible bars. */
|
|
33
|
+
export type TitleAppBarProps = AppBarBaseProps & {
|
|
34
|
+
/** The main title of the app bar. */
|
|
35
|
+
title: string;
|
|
36
|
+
/**
|
|
37
|
+
* `small` (64dp, one line), `medium` or `large` (flexible, wrapping headline). Pass one per
|
|
38
|
+
* breakpoint to adapt to the window, e.g. `{ small: 'small', large: 'large' }`; tiers you
|
|
39
|
+
* leave out inherit from the one below, and below the first given tier the bar is `small`.
|
|
40
|
+
*/
|
|
41
|
+
size?: Responsive<AppBarSize>;
|
|
42
|
+
search?: never;
|
|
43
|
+
query?: never;
|
|
44
|
+
searchProps?: never;
|
|
45
|
+
searchTrailing?: never;
|
|
46
|
+
};
|
|
47
|
+
/** A search app bar: a search field in place of the title, always 64dp. */
|
|
48
|
+
export type SearchAppBarProps = AppBarBaseProps & {
|
|
49
|
+
/** Hint text in the search field. Setting it makes this a search app bar. */
|
|
50
|
+
search: string;
|
|
51
|
+
/** The search query. */
|
|
52
|
+
query?: string;
|
|
53
|
+
/** Screen title; rendered for assistive tech only. */
|
|
54
|
+
title?: string;
|
|
55
|
+
/** Props for the search `<input>`, e.g. `onfocus` to open a search view. */
|
|
56
|
+
searchProps?: HTMLInputAttributes;
|
|
57
|
+
/** An action inside the search field, e.g. a mic icon button. */
|
|
58
|
+
searchTrailing?: Snippet;
|
|
59
|
+
size?: never;
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* Props for the AppBar component.
|
|
63
|
+
*/
|
|
64
|
+
export type AppBarProps = TitleAppBarProps | SearchAppBarProps;
|
|
65
|
+
export {};
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { tv } from '
|
|
1
|
+
import { tv } from '../../../utils/tv.js';
|
|
2
2
|
export const breadcrumb = tv({
|
|
3
3
|
slots: {
|
|
4
4
|
base: 'flex',
|
|
5
|
-
list: 'flex flex-wrap items-center gap-
|
|
6
|
-
item: 'flex items-center gap-
|
|
7
|
-
link: 'md-sys-typescale-label-large text-md-sys-color-on-surface-variant md-sys-state-focus-indicator relative inline-flex min-h-
|
|
8
|
-
text: 'md-sys-typescale-label-large text-md-sys-color-on-surface-variant px-
|
|
9
|
-
current: 'md-sys-typescale-label-large
|
|
5
|
+
list: 'flex flex-wrap items-center gap-spacing-50',
|
|
6
|
+
item: 'flex items-center gap-spacing-50',
|
|
7
|
+
link: 'md-sys-typescale-label-large text-md-sys-color-on-surface-variant md-sys-state-focus-indicator relative inline-flex min-h-spacing-600 items-center rounded-full px-spacing-150 transition-colors md-sys-motion-fast-effects',
|
|
8
|
+
text: 'md-sys-typescale-label-large text-md-sys-color-on-surface-variant px-spacing-50 py-spacing-25',
|
|
9
|
+
current: 'md-sys-typescale-emphasized-label-large px-spacing-50 py-spacing-25',
|
|
10
10
|
separator: 'text-md-sys-color-on-surface-variant inline-flex shrink-0'
|
|
11
11
|
},
|
|
12
12
|
variants: {
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Meta, Title, Subtitle, Canvas, Controls } from '@storybook/addon-docs/blocks';
|
|
2
|
+
import * as NavbarStories from './Navbar.stories.svelte';
|
|
3
|
+
|
|
4
|
+
<Meta of={NavbarStories} />
|
|
5
|
+
|
|
6
|
+
<Title />
|
|
7
|
+
|
|
8
|
+
<Subtitle>
|
|
9
|
+
Navigation bars give access to 3–5 primary destinations at the bottom of small windows.
|
|
10
|
+
</Subtitle>
|
|
11
|
+
|
|
12
|
+
[M3 spec](https://m3.material.io/components/navigation-bar/specs) ·
|
|
13
|
+
`import { Navbar, NavbarItem } from '@noxlovette/material';`
|
|
14
|
+
|
|
15
|
+
<Canvas of={NavbarStories.Playground} />
|
|
16
|
+
|
|
17
|
+
<Controls of={NavbarStories.Playground} />
|
|
18
|
+
|
|
19
|
+
## Pairing with Rail
|
|
20
|
+
|
|
21
|
+
The bar is fixed to the bottom of the window and hides itself from `md` up, where a `Rail` takes
|
|
22
|
+
over. Give both the same destinations. `ghost` adds a spacer the height of the bar, so the end of
|
|
23
|
+
the page isn't hidden behind it.
|
|
24
|
+
|
|
25
|
+
```svelte
|
|
26
|
+
<Navbar ghost>
|
|
27
|
+
<NavbarItem label="Home" href="/" iconProps={{ name: 'house' }} />
|
|
28
|
+
<NavbarItem label="Messages" href="/messages" iconProps={{ name: 'mail' }} badge={5} />
|
|
29
|
+
<NavbarItem label="Settings" href="/settings" iconProps={{ name: 'settings' }} />
|
|
30
|
+
</Navbar>
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Accessibility
|
|
34
|
+
|
|
35
|
+
- **Landmark.** The bar is a navigation list, so assistive tech announces it as navigation.
|
|
36
|
+
- **Active item.** The active item gets `aria-current="page"`.
|
|
37
|
+
- **Badges.** A `badge` isn't announced on its own; put the count in the item's label if it
|
|
38
|
+
matters.
|
|
@@ -48,15 +48,18 @@ A single destination within a navigation bar.
|
|
|
48
48
|
<div class={content()}>
|
|
49
49
|
<div class={iconContainer()}>
|
|
50
50
|
<Layer />
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
51
|
+
<!-- Badge offsets are measured from the icon's corner, not the indicator's. -->
|
|
52
|
+
<span class="relative inline-flex">
|
|
53
|
+
<Icon
|
|
54
|
+
{...iconProps}
|
|
55
|
+
class={icon()}
|
|
56
|
+
wght={isActive ? 600 : 400}
|
|
57
|
+
fill={isActive ? 1 : 0}
|
|
58
|
+
/>
|
|
59
|
+
{#if badge}
|
|
60
|
+
<Badge size={badge === -1 ? 'sm' : 'lg'} number={badge} />
|
|
61
|
+
{/if}
|
|
62
|
+
</span>
|
|
60
63
|
</div>
|
|
61
64
|
<span class={labelClass()}>
|
|
62
65
|
{label}
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
export declare const navbar: import("tailwind-variants").TVReturnType<{
|
|
2
2
|
[key: string]: {
|
|
3
3
|
[key: string]: import("tailwind-variants").ClassValue | {
|
|
4
|
+
fab?: import("tailwind-variants").ClassValue;
|
|
4
5
|
base?: import("tailwind-variants").ClassValue;
|
|
5
6
|
items?: import("tailwind-variants").ClassValue;
|
|
6
7
|
ghost?: import("tailwind-variants").ClassValue;
|
|
7
|
-
fab?: import("tailwind-variants").ClassValue;
|
|
8
8
|
};
|
|
9
9
|
};
|
|
10
10
|
} | {
|
|
11
11
|
[x: string]: {
|
|
12
12
|
[x: string]: import("tailwind-variants").ClassValue | {
|
|
13
|
+
fab?: import("tailwind-variants").ClassValue;
|
|
13
14
|
base?: import("tailwind-variants").ClassValue;
|
|
14
15
|
items?: import("tailwind-variants").ClassValue;
|
|
15
16
|
ghost?: import("tailwind-variants").ClassValue;
|
|
16
|
-
fab?: import("tailwind-variants").ClassValue;
|
|
17
17
|
};
|
|
18
18
|
};
|
|
19
19
|
} | {}, {
|
|
@@ -24,10 +24,10 @@ export declare const navbar: import("tailwind-variants").TVReturnType<{
|
|
|
24
24
|
}, undefined, {
|
|
25
25
|
[key: string]: {
|
|
26
26
|
[key: string]: import("tailwind-variants").ClassValue | {
|
|
27
|
+
fab?: import("tailwind-variants").ClassValue;
|
|
27
28
|
base?: import("tailwind-variants").ClassValue;
|
|
28
29
|
items?: import("tailwind-variants").ClassValue;
|
|
29
30
|
ghost?: import("tailwind-variants").ClassValue;
|
|
30
|
-
fab?: import("tailwind-variants").ClassValue;
|
|
31
31
|
};
|
|
32
32
|
};
|
|
33
33
|
} | {}, {
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import { tv } from '
|
|
1
|
+
import { tv } from '../../../utils/tv.js';
|
|
2
2
|
export const navbar = tv({
|
|
3
3
|
slots: {
|
|
4
|
-
base: 'shadow-elevation-2 bg-md-sys-color-surface-container
|
|
4
|
+
base: 'shadow-elevation-2 bg-md-sys-color-surface-container z-layer-bar flex h-20 fixed bottom-spacing-0 w-full left-spacing-0 justify-around py-spacing-150 md:hidden',
|
|
5
5
|
items: 'flex justify-around w-full',
|
|
6
|
-
fab: 'bottom-24 right-
|
|
6
|
+
fab: 'bottom-24 right-spacing-200 absolute',
|
|
7
7
|
ghost: 'h-20 w-full shrink-0 md:hidden pointer-events-none'
|
|
8
8
|
}
|
|
9
9
|
});
|
|
10
10
|
export const navitem = tv({
|
|
11
11
|
slots: {
|
|
12
|
-
base: 'group relative flex flex-1 flex-col items-center justify-center min-w-0 max-w-[168px] h-full transition-colors md-sys-motion-fast-effects',
|
|
13
|
-
content: 'flex flex-col items-center justify-center gap-
|
|
14
|
-
iconContainer: 'relative flex items-center justify-center h-
|
|
15
|
-
icon: 'text-[24px] size-
|
|
12
|
+
base: 'group relative flex flex-1 flex-col items-center justify-center min-w-spacing-0 max-w-[168px] h-full transition-colors md-sys-motion-fast-effects',
|
|
13
|
+
content: 'flex flex-col items-center justify-center gap-spacing-50 w-full',
|
|
14
|
+
iconContainer: 'relative flex items-center justify-center h-spacing-400 w-spacing-800 rounded-full transition-colors md-sys-motion-effects',
|
|
15
|
+
icon: 'text-[24px] size-spacing-300',
|
|
16
16
|
label: 'md-sys-typescale-label-medium truncate w-full text-center'
|
|
17
17
|
},
|
|
18
18
|
variants: {
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { Meta, Title, Subtitle, Canvas, Controls } from '@storybook/addon-docs/blocks';
|
|
2
|
+
import * as RailStories from './Rail.stories.svelte';
|
|
3
|
+
|
|
4
|
+
<Meta of={RailStories} />
|
|
5
|
+
|
|
6
|
+
<Title />
|
|
7
|
+
|
|
8
|
+
<Subtitle>
|
|
9
|
+
Navigation rails give access to 3–7 primary destinations on medium and larger windows.
|
|
10
|
+
</Subtitle>
|
|
11
|
+
|
|
12
|
+
[M3 spec](https://m3.material.io/components/navigation-rail/specs) ·
|
|
13
|
+
`import { Rail, RailItem } from '@noxlovette/material';`
|
|
14
|
+
|
|
15
|
+
<Canvas of={RailStories.Playground} />
|
|
16
|
+
|
|
17
|
+
<Controls of={RailStories.Playground} />
|
|
18
|
+
|
|
19
|
+
## Anatomy
|
|
20
|
+
|
|
21
|
+
- **`Rail`** is the container: the sidebar, a spacer that reserves its width in the page, and the
|
|
22
|
+
scrim shown while it's expanded on medium windows.
|
|
23
|
+
- **`RailItem`** is one destination. It detects the active route, shows an optional `badge` (a
|
|
24
|
+
count, or `-1` for a dot), and lays itself out for the collapsed or expanded rail.
|
|
25
|
+
- **`railStore`** exposes the collapsed state to components outside the rail.
|
|
26
|
+
|
|
27
|
+
## Window sizes
|
|
28
|
+
|
|
29
|
+
The rail shows from `md` up and is hidden below it. For small windows, mount a `Navbar` with the
|
|
30
|
+
same destinations; it hides itself from `md` up, so the two never show together.
|
|
31
|
+
|
|
32
|
+
| Window | Collapsed rail | Expanded rail |
|
|
33
|
+
| -------------- | -------------- | --------------------------------------------------- |
|
|
34
|
+
| Small (< `md`) | Hidden | Hidden |
|
|
35
|
+
| Medium (`md`) | 96dp | Overlays content over a scrim; outside click closes |
|
|
36
|
+
| Large (`lg`+) | 96dp | Pushes content aside |
|
|
37
|
+
|
|
38
|
+
## Layout
|
|
39
|
+
|
|
40
|
+
The rail renders a spacer next to itself that takes the rail's width. Put the rail and your
|
|
41
|
+
content in a flex row and the content moves aside on its own, with no `margin-left`:
|
|
42
|
+
|
|
43
|
+
```svelte
|
|
44
|
+
<div class="flex min-h-dvh">
|
|
45
|
+
<Rail bind:collapsed>
|
|
46
|
+
<RailItem label="Home" href="/" iconProps={{ name: 'house' }} />
|
|
47
|
+
<RailItem label="Messages" href="/messages" iconProps={{ name: 'mail' }} badge={5} />
|
|
48
|
+
</Rail>
|
|
49
|
+
<div class="min-w-spacing-0 flex-1">
|
|
50
|
+
{@render children()}
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
53
|
+
|
|
54
|
+
<Navbar>
|
|
55
|
+
<NavbarItem label="Home" href="/" iconProps={{ name: 'house' }} />
|
|
56
|
+
<NavbarItem label="Messages" href="/messages" iconProps={{ name: 'mail' }} badge={5} />
|
|
57
|
+
</Navbar>
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
- **Under an app bar:** pass the bar's height in px to `railTop` so the rail starts below it.
|
|
61
|
+
- **Anchoring:** `anchor="viewport"` (the default) fixes the rail to the window's leading edge.
|
|
62
|
+
`anchor="parent"` positions it inside the nearest positioned ancestor, for embedded layouts
|
|
63
|
+
and demos.
|
|
64
|
+
- **Extras:** the `fab` snippet places a FAB above the destinations. `expandable={false}` removes
|
|
65
|
+
the menu toggle.
|
|
66
|
+
|
|
67
|
+
<Canvas of={RailStories.WithFAB} />
|
|
68
|
+
|
|
69
|
+
## Accessibility
|
|
70
|
+
|
|
71
|
+
- **Active item.** The active item gets `aria-current="page"`.
|
|
72
|
+
- **Disabled items** set `aria-disabled` and leave the tab order but stay visible.
|
|
73
|
+
- **Keyboard.** Every item is a link reachable with Tab; the menu toggle is a real button.
|
|
@@ -14,15 +14,13 @@
|
|
|
14
14
|
anchor: {
|
|
15
15
|
control: 'select',
|
|
16
16
|
options: ['viewport', 'parent']
|
|
17
|
-
}
|
|
18
|
-
withNavbar: { control: 'boolean' }
|
|
17
|
+
}
|
|
19
18
|
},
|
|
20
19
|
args: {
|
|
21
20
|
collapsed: true,
|
|
22
21
|
expandable: true,
|
|
23
22
|
rounded: false,
|
|
24
|
-
anchor: 'parent'
|
|
25
|
-
withNavbar: false
|
|
23
|
+
anchor: 'parent'
|
|
26
24
|
}
|
|
27
25
|
});
|
|
28
26
|
</script>
|
|
@@ -35,7 +33,6 @@
|
|
|
35
33
|
collapsed={args.collapsed}
|
|
36
34
|
expandable={args.expandable}
|
|
37
35
|
rounded={args.rounded}
|
|
38
|
-
withNavbar={args.withNavbar}
|
|
39
36
|
>
|
|
40
37
|
<RailItem label="Home" href="/" iconProps={{ name: 'house' }} selected />
|
|
41
38
|
<RailItem label="Inbox" href="#" iconProps={{ name: 'mail' }} badge={4} />
|
|
@@ -55,10 +52,9 @@
|
|
|
55
52
|
collapsed={args.collapsed}
|
|
56
53
|
expandable={args.expandable}
|
|
57
54
|
rounded={args.rounded}
|
|
58
|
-
withNavbar={args.withNavbar}
|
|
59
55
|
>
|
|
60
56
|
{#snippet fab()}
|
|
61
|
-
<FAB
|
|
57
|
+
<FAB iconProps={{ name: 'add' }} label="New" />
|
|
62
58
|
{/snippet}
|
|
63
59
|
<RailItem label="Home" href="/" iconProps={{ name: 'house' }} selected />
|
|
64
60
|
<RailItem label="Inbox" href="#" iconProps={{ name: 'mail' }} badge={4} />
|
|
@@ -25,6 +25,8 @@ On mobile (< md) it automatically renders as a bottom navigation bar.
|
|
|
25
25
|
collapsed = $bindable(true),
|
|
26
26
|
anchor = 'viewport',
|
|
27
27
|
railTop = 0,
|
|
28
|
+
expandLabel = 'Expand navigation',
|
|
29
|
+
collapseLabel = 'Collapse navigation',
|
|
28
30
|
class: className
|
|
29
31
|
}: RailProps = $props();
|
|
30
32
|
|
|
@@ -66,8 +68,9 @@ On mobile (< md) it automatically renders as a bottom navigation bar.
|
|
|
66
68
|
>
|
|
67
69
|
{#if expandable}
|
|
68
70
|
<ButtonIcon
|
|
71
|
+
variant="standard"
|
|
69
72
|
type="button"
|
|
70
|
-
tooltipContent={collapsed ?
|
|
73
|
+
tooltipContent={collapsed ? expandLabel : collapseLabel}
|
|
71
74
|
iconProps={{ name: `${collapsed ? 'menu' : 'menu_open'}` }}
|
|
72
75
|
class={toggleClass}
|
|
73
76
|
onclick={() => (collapsed = !collapsed)}
|
|
@@ -97,6 +100,6 @@ On mobile (< md) it automatically renders as a bottom navigation bar.
|
|
|
97
100
|
opacity: 1;
|
|
98
101
|
pointer-events: auto;
|
|
99
102
|
background-color: rgb(0 0 0 / 0.4);
|
|
100
|
-
z-index:
|
|
103
|
+
z-index: var(--z-layer-rail);
|
|
101
104
|
}
|
|
102
105
|
</style>
|
|
@@ -99,15 +99,18 @@ In mobile (navbar) mode the same item renders as a bottom-bar tab.
|
|
|
99
99
|
<div class={content()}>
|
|
100
100
|
<div class={iconContainer()}>
|
|
101
101
|
<Layer />
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
102
|
+
<!-- Badge offsets are measured from the icon's corner, not the indicator's. -->
|
|
103
|
+
<span class="relative inline-flex">
|
|
104
|
+
<Icon
|
|
105
|
+
{...iconProps}
|
|
106
|
+
class={icon()}
|
|
107
|
+
wght={isActive ? 600 : 400}
|
|
108
|
+
fill={isActive ? 1 : 0}
|
|
109
|
+
/>
|
|
110
|
+
{#if badge}
|
|
111
|
+
<Badge size={badge === -1 ? 'sm' : 'lg'} number={badge} />
|
|
112
|
+
{/if}
|
|
113
|
+
</span>
|
|
111
114
|
</div>
|
|
112
115
|
<p class={labelClass()}>
|
|
113
116
|
{label}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type VariantProps } from '
|
|
1
|
+
import { type VariantProps } from '../../../utils/tv.js';
|
|
2
2
|
export type RailVariants = VariantProps<typeof rail>;
|
|
3
3
|
export type RailItemVariants = VariantProps<typeof railElement>;
|
|
4
4
|
export declare const rail: import("tailwind-variants").TVReturnType<{
|