@noxlovette/material 0.5.0 → 0.6.0
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 +60 -0
- package/dist/animation/Shapes.stories.svelte.d.ts +3 -0
- package/dist/animation/TransitionPatterns.stories.svelte +32 -20
- package/dist/animation/containerTransform.d.ts +11 -0
- package/dist/animation/containerTransform.js +11 -0
- package/dist/animation/enterExit.d.ts +9 -0
- package/dist/animation/enterExit.js +6 -3
- package/dist/animation/index.d.ts +1 -0
- package/dist/animation/index.js +1 -0
- package/dist/animation/shapeMorph.svelte.d.ts +52 -0
- package/dist/animation/shapeMorph.svelte.js +112 -0
- package/dist/animation/shapesAnimatableSmall.d.ts +28 -22
- package/dist/animation/shapesAnimatableSmall.js +32 -23
- package/dist/animation/sharedAxisTransition.d.ts +22 -0
- package/dist/animation/sharedAxisTransition.js +25 -1
- package/dist/animation/skeleton.d.ts +6 -1
- package/dist/animation/skeleton.js +6 -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 +24 -4
- 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 +45 -15
- package/dist/components/buttons/button-group/theme.js +13 -8
- 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 +33 -18
- package/dist/components/buttons/connected/theme.js +32 -9
- 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 +65 -48
- package/dist/components/buttons/split-button/SplitButton.svelte.d.ts +6 -11
- package/dist/components/buttons/split-button/theme.d.ts +110 -17
- package/dist/components/buttons/split-button/theme.js +74 -16
- package/dist/components/buttons/split-button/types.d.ts +24 -18
- package/dist/components/buttons/theme.d.ts +422 -230
- package/dist/components/buttons/theme.js +286 -380
- 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 +5 -5
- package/dist/components/chips/Chip.mdx +68 -0
- package/dist/components/chips/Chip.stories.svelte +4 -4
- package/dist/components/chips/theme.js +3 -3
- package/dist/components/containers/action-rail/ActionRail.stories.svelte +1 -0
- package/dist/components/containers/action-rail/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.js +10 -10
- 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 +1 -1
- package/dist/components/containers/dialogue/theme.js +3 -3
- 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 +6 -6
- package/dist/components/containers/divider/theme.js +2 -2
- package/dist/components/containers/index.d.ts +1 -1
- package/dist/components/containers/index.js +1 -1
- package/dist/components/containers/link-preview/theme.js +2 -2
- 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 +140 -13
- 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 +1 -1
- 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/menu-item/MenuItem.svelte +1 -1
- package/dist/components/containers/menu/theme.js +8 -8
- 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.js +129 -45
- 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.js +3 -3
- package/dist/components/containers/scroll-area/theme.js +2 -2
- 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 +49 -26
- package/dist/components/date/DateField.svelte.d.ts +2 -0
- package/dist/components/date/DateRangeField.stories.svelte +4 -3
- package/dist/components/date/DateRangeField.svelte +54 -31
- package/dist/components/date/DateRangeField.svelte.d.ts +2 -0
- package/dist/components/date/calendarMotion.d.ts +9 -0
- package/dist/components/date/calendarMotion.js +23 -0
- package/dist/components/date/theme.d.ts +7 -7
- package/dist/components/date/theme.js +34 -30
- 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.js +3 -3
- package/dist/components/forms/command/Command.stories.svelte +1 -0
- package/dist/components/forms/command/theme.js +9 -9
- package/dist/components/forms/pin/theme.js +4 -4
- package/dist/components/forms/radio-group/RadioGroup.svelte +1 -1
- package/dist/components/forms/radio-group/theme.js +5 -5
- 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 +45 -12
- package/dist/components/forms/search/theme.js +13 -8
- 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 +10 -2
- package/dist/components/forms/select/SelectItem.svelte +1 -1
- package/dist/components/forms/select/theme.js +12 -12
- 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 +14 -0
- package/dist/components/forms/slider/theme.js +28 -17
- 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.js +6 -6
- 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 +3 -0
- package/dist/components/forms/textfield/theme.js +22 -19
- package/dist/components/forms/toggle-group/theme.js +2 -2
- package/dist/components/forms/tooltip/Tooltip.stories.svelte +1 -0
- package/dist/components/forms/tooltip/theme.js +3 -3
- 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 +4 -4
- 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 +85 -18
- package/dist/components/nav/appbar/theme.js +159 -23
- 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.js +5 -5
- 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.js +6 -6
- 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 +1 -0
- package/dist/components/nav/rail/RailItem.svelte +12 -9
- package/dist/components/nav/rail/theme.js +13 -13
- package/dist/components/nav/rail/types.d.ts +4 -1
- package/dist/components/nav/tabs/TabHolder.svelte +29 -3
- package/dist/components/nav/tabs/TabHolder.svelte.d.ts +3 -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.js +4 -4
- package/dist/components/pill/Pill.mdx +32 -0
- package/dist/components/pill/Pill.stories.svelte +1 -1
- package/dist/components/pill/theme.d.ts +1 -1
- package/dist/components/pill/theme.js +1 -1
- package/dist/components/progress/LinearProgress.svelte +1 -1
- 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 +3 -3
- package/dist/components/snackbar/theme.js +4 -4
- package/dist/components/table/Table.stories.svelte +1 -0
- package/dist/components/table/TableHeader.svelte +1 -1
- package/dist/components/table/theme.js +3 -3
- package/dist/components/time/TimeField.stories.svelte +3 -2
- package/dist/components/time/TimeField.svelte +14 -8
- package/dist/components/time/TimeField.svelte.d.ts +6 -0
- package/dist/components/time/TimepickerInput.svelte +9 -5
- package/dist/components/time/theme.js +5 -5
- package/dist/components/time/types.d.ts +11 -1
- 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.js +14 -14
- 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 +15 -12
- package/dist/components/typography/body/theme.js +19 -4
- 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 +15 -12
- package/dist/components/typography/display/theme.js +19 -4
- 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 +15 -12
- package/dist/components/typography/headline/theme.js +19 -4
- 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 +4 -4
- package/dist/components/typography/kbd/theme.js +2 -2
- 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 +19 -4
- 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 +15 -12
- package/dist/components/typography/title/theme.js +19 -4
- package/dist/components/typography/title/types.d.ts +2 -1
- package/dist/index.css +1 -0
- package/dist/styles/component.css +78 -175
- package/dist/styles/elevation.css +9 -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/loadingShapes.js +11 -10
- 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
|
@@ -17,20 +17,42 @@ export interface SharedAxisOptions extends NavigationOptions {
|
|
|
17
17
|
* axis while fading through each other.
|
|
18
18
|
* https://m3.material.io/styles/motion/transitions/transition-patterns#forward-and-backward
|
|
19
19
|
*
|
|
20
|
+
* The default for common hierarchical navigation (https://m3.material.io/styles/motion/transitions/applying-transitions).
|
|
21
|
+
* Don't use it for hero moments; use `containerTransform` for those. Keep one axis per relationship
|
|
22
|
+
* across the app (coherent spatial model), and move one `target` region as a unit instead of
|
|
23
|
+
* animating many elements independently.
|
|
24
|
+
*
|
|
20
25
|
* `update` performs the DOM change (`async () => { step++; await tick(); }`). Built on Motion's
|
|
21
26
|
* `animateView()` — both states never need to coexist in the DOM.
|
|
27
|
+
*
|
|
28
|
+
* Not built into any component: hierarchy levels and wizard steps live in the consuming app.
|
|
22
29
|
*/
|
|
23
30
|
export declare const sharedAxis: (update: () => void | Promise<void>, { target, axis, direction, spring }?: SharedAxisOptions) => import("motion-dom").ViewTransitionBuilder;
|
|
24
31
|
/**
|
|
25
32
|
* M3 lateral: peer screens at the same level (tabs, carousels) slide past each other edge to edge,
|
|
26
33
|
* without fading — the new screen pushes the old one out.
|
|
27
34
|
* https://m3.material.io/styles/motion/transitions/transition-patterns#lateral
|
|
35
|
+
*
|
|
36
|
+
* Only for peers in one set (https://m3.material.io/styles/motion/transitions/applying-transitions). Never use it for hierarchical screens
|
|
37
|
+
* (use `sharedAxis`) or navbar/rail/drawer destinations (use `fadeThrough`, since the implied swipe
|
|
38
|
+
* conflicts with carousels and swipeable list items). Don't add a fade: it hides the peer
|
|
39
|
+
* relationship and makes the slide look like forward/backward.
|
|
40
|
+
*
|
|
41
|
+
* Built in: `TabHolder` (switching content panels) and `DateField`/`DateRangeField` (changing the
|
|
42
|
+
* visible month). Any new component that pages between peer views must use this too.
|
|
28
43
|
*/
|
|
29
44
|
export declare const lateral: (update: () => void | Promise<void>, { target, direction, spring }?: NavigationOptions) => import("motion-dom").ViewTransitionBuilder;
|
|
30
45
|
/**
|
|
31
46
|
* M3 top level (fade through): destinations with no spatial relationship, e.g. navigation bar
|
|
32
47
|
* items. The outgoing screen fades out, then the incoming one fades in while scaling up from 92%.
|
|
33
48
|
* https://m3.material.io/styles/motion/transitions/transition-patterns#top-level
|
|
49
|
+
*
|
|
50
|
+
* The quick fade for navigation bar, rail and drawer destinations (https://m3.material.io/styles/motion/transitions/applying-transitions).
|
|
51
|
+
* It deliberately creates no spatial connection between screens, and it's the pattern to use
|
|
52
|
+
* instead of `lateral` there.
|
|
53
|
+
*
|
|
54
|
+
* Not built into `Navbar`/`Rail`: they don't own the content region that changes, so the app wraps
|
|
55
|
+
* its own route change in this.
|
|
34
56
|
*/
|
|
35
57
|
export declare const fadeThrough: (update: () => void | Promise<void>, { target, spring }?: Omit<NavigationOptions, "direction">) => import("motion-dom").ViewTransitionBuilder;
|
|
36
58
|
export {};
|
|
@@ -5,7 +5,9 @@ const view = (update, target, spring) => {
|
|
|
5
5
|
const builder = animateView(update, springTransition(spring));
|
|
6
6
|
return target ? builder.add(target) : builder;
|
|
7
7
|
};
|
|
8
|
-
/* Outgoing content clears quickly; incoming content waits a beat so the two never overlap fully.
|
|
8
|
+
/* Outgoing content clears quickly; incoming content waits a beat so the two never overlap fully.
|
|
9
|
+
M3 "clean fades" (https://m3.material.io/styles/motion/transitions/applying-transitions): fade out before fading in; any cross-fade stays short
|
|
10
|
+
and hidden in the fastest part of the motion. Don't lengthen these. */
|
|
9
11
|
const fadeOut = springTransition(springTokens.fastEffects);
|
|
10
12
|
const fadeIn = { ...springTransition(springTokens.effects), delay: 0.05 };
|
|
11
13
|
/**
|
|
@@ -13,8 +15,15 @@ const fadeIn = { ...springTransition(springTokens.effects), delay: 0.05 };
|
|
|
13
15
|
* axis while fading through each other.
|
|
14
16
|
* https://m3.material.io/styles/motion/transitions/transition-patterns#forward-and-backward
|
|
15
17
|
*
|
|
18
|
+
* The default for common hierarchical navigation (https://m3.material.io/styles/motion/transitions/applying-transitions).
|
|
19
|
+
* Don't use it for hero moments; use `containerTransform` for those. Keep one axis per relationship
|
|
20
|
+
* across the app (coherent spatial model), and move one `target` region as a unit instead of
|
|
21
|
+
* animating many elements independently.
|
|
22
|
+
*
|
|
16
23
|
* `update` performs the DOM change (`async () => { step++; await tick(); }`). Built on Motion's
|
|
17
24
|
* `animateView()` — both states never need to coexist in the DOM.
|
|
25
|
+
*
|
|
26
|
+
* Not built into any component: hierarchy levels and wizard steps live in the consuming app.
|
|
18
27
|
*/
|
|
19
28
|
export const sharedAxis = (update, { target, axis = 'x', direction = 'forward', spring = springTokens.spatial } = {}) => {
|
|
20
29
|
const forward = direction === 'forward';
|
|
@@ -33,6 +42,14 @@ export const sharedAxis = (update, { target, axis = 'x', direction = 'forward',
|
|
|
33
42
|
* M3 lateral: peer screens at the same level (tabs, carousels) slide past each other edge to edge,
|
|
34
43
|
* without fading — the new screen pushes the old one out.
|
|
35
44
|
* https://m3.material.io/styles/motion/transitions/transition-patterns#lateral
|
|
45
|
+
*
|
|
46
|
+
* Only for peers in one set (https://m3.material.io/styles/motion/transitions/applying-transitions). Never use it for hierarchical screens
|
|
47
|
+
* (use `sharedAxis`) or navbar/rail/drawer destinations (use `fadeThrough`, since the implied swipe
|
|
48
|
+
* conflicts with carousels and swipeable list items). Don't add a fade: it hides the peer
|
|
49
|
+
* relationship and makes the slide look like forward/backward.
|
|
50
|
+
*
|
|
51
|
+
* Built in: `TabHolder` (switching content panels) and `DateField`/`DateRangeField` (changing the
|
|
52
|
+
* visible month). Any new component that pages between peer views must use this too.
|
|
36
53
|
*/
|
|
37
54
|
export const lateral = (update, { target, direction = 'forward', spring = springTokens.spatial } = {}) => {
|
|
38
55
|
const sign = direction === 'forward' ? 1 : -1;
|
|
@@ -45,6 +62,13 @@ export const lateral = (update, { target, direction = 'forward', spring = spring
|
|
|
45
62
|
* M3 top level (fade through): destinations with no spatial relationship, e.g. navigation bar
|
|
46
63
|
* items. The outgoing screen fades out, then the incoming one fades in while scaling up from 92%.
|
|
47
64
|
* https://m3.material.io/styles/motion/transitions/transition-patterns#top-level
|
|
65
|
+
*
|
|
66
|
+
* The quick fade for navigation bar, rail and drawer destinations (https://m3.material.io/styles/motion/transitions/applying-transitions).
|
|
67
|
+
* It deliberately creates no spatial connection between screens, and it's the pattern to use
|
|
68
|
+
* instead of `lateral` there.
|
|
69
|
+
*
|
|
70
|
+
* Not built into `Navbar`/`Rail`: they don't own the content region that changes, so the app wraps
|
|
71
|
+
* its own route change in this.
|
|
48
72
|
*/
|
|
49
73
|
export const fadeThrough = (update, { target, spring = springTokens.spatial } = {}) => view(update, target, spring)
|
|
50
74
|
.old({ opacity: [1, 0] }, fadeOut)
|
|
@@ -4,8 +4,13 @@ import type { Attachment } from 'svelte/attachments';
|
|
|
4
4
|
* for the content with `presence(…, enterExit.fade)` so the reveal is a fade, not a cut.
|
|
5
5
|
* https://m3.material.io/styles/motion/transitions/transition-patterns#skeleton-loaders
|
|
6
6
|
*
|
|
7
|
+
* M3 "stable layouts" (https://m3.material.io/styles/motion/transitions/applying-transitions): the placeholder takes the loaded
|
|
8
|
+
* content's footprint so nothing pops in or shifts position when the data arrives.
|
|
9
|
+
*
|
|
10
|
+
* Not built into any component — none of them load their own data. Apps apply it to placeholders.
|
|
11
|
+
*
|
|
7
12
|
* ```svelte
|
|
8
|
-
* <div class="bg-md-sys-color-surface-container-highest h-
|
|
13
|
+
* <div class="bg-md-sys-color-surface-container-highest h-spacing-200 rounded-sm" {@attach skeleton}></div>
|
|
9
14
|
* ```
|
|
10
15
|
*/
|
|
11
16
|
export declare const skeleton: Attachment<HTMLElement>;
|
|
@@ -8,8 +8,13 @@ const PULSE_HOLD_S = 0.5;
|
|
|
8
8
|
* for the content with `presence(…, enterExit.fade)` so the reveal is a fade, not a cut.
|
|
9
9
|
* https://m3.material.io/styles/motion/transitions/transition-patterns#skeleton-loaders
|
|
10
10
|
*
|
|
11
|
+
* M3 "stable layouts" (https://m3.material.io/styles/motion/transitions/applying-transitions): the placeholder takes the loaded
|
|
12
|
+
* content's footprint so nothing pops in or shifts position when the data arrives.
|
|
13
|
+
*
|
|
14
|
+
* Not built into any component — none of them load their own data. Apps apply it to placeholders.
|
|
15
|
+
*
|
|
11
16
|
* ```svelte
|
|
12
|
-
* <div class="bg-md-sys-color-surface-container-highest h-
|
|
17
|
+
* <div class="bg-md-sys-color-surface-container-highest h-spacing-200 rounded-sm" {@attach skeleton}></div>
|
|
13
18
|
* ```
|
|
14
19
|
*/
|
|
15
20
|
export const skeleton = (node) => {
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { Meta, Title, Subtitle, Canvas, Controls } from '@storybook/addon-docs/blocks';
|
|
2
|
+
import * as BadgeStories from './Badge.stories.svelte';
|
|
3
|
+
|
|
4
|
+
<Meta of={BadgeStories} />
|
|
5
|
+
|
|
6
|
+
<Title />
|
|
7
|
+
|
|
8
|
+
<Subtitle>
|
|
9
|
+
Badges show notifications, counts, or status information on navigation items and icons.
|
|
10
|
+
</Subtitle>
|
|
11
|
+
|
|
12
|
+
[M3 spec](https://m3.material.io/components/badges/specs) ·
|
|
13
|
+
`import { Badge } from '@noxlovette/material';`
|
|
14
|
+
|
|
15
|
+
<Canvas of={BadgeStories.Playground} />
|
|
16
|
+
|
|
17
|
+
<Controls of={BadgeStories.Playground} />
|
|
18
|
+
|
|
19
|
+
## Choosing a size
|
|
20
|
+
|
|
21
|
+
| Size | Looks like | Use for |
|
|
22
|
+
| ---- | --------------------------------- | ------------------------------------------- |
|
|
23
|
+
| `sm` | 6dp dot, no text | A general notification ("something is new") |
|
|
24
|
+
| `lg` | 16dp-tall pill with a label-small | A specific count |
|
|
25
|
+
|
|
26
|
+
A large badge holds at most four characters, "+" included, so counts above `max` (999 by
|
|
27
|
+
default) show as `999+` in a 16×34dp container. A zero or missing `number` hides a large badge.
|
|
28
|
+
|
|
29
|
+
<Canvas of={BadgeStories.DotSmall} />
|
|
30
|
+
|
|
31
|
+
<Canvas of={BadgeStories.MaxCharacterCount} />
|
|
32
|
+
|
|
33
|
+
## Placement
|
|
34
|
+
|
|
35
|
+
`NavbarItem` and `RailItem` take a `badge` prop (a count, or `-1` for the dot) and place it for
|
|
36
|
+
you. Use `Badge` directly only on icons those components don't cover, such as a custom icon
|
|
37
|
+
button.
|
|
38
|
+
|
|
39
|
+
By default the badge is absolutely positioned, with offsets measured from the **icon's**
|
|
40
|
+
top-trailing corner:
|
|
41
|
+
|
|
42
|
+
- **Small:** its bottom-leading corner sits 6dp down and 6dp in, so the dot fills the icon's
|
|
43
|
+
top-trailing corner.
|
|
44
|
+
- **Large:** its bottom-leading corner sits 14dp down and 12dp in. The badge grows away from the
|
|
45
|
+
icon as the count gets wider.
|
|
46
|
+
|
|
47
|
+
So wrap the icon itself in a `relative inline-flex` element. Don't anchor the badge to a larger
|
|
48
|
+
indicator or button container, or the offsets will be measured from the wrong corner.
|
|
49
|
+
|
|
50
|
+
```svelte
|
|
51
|
+
<span class="relative inline-flex">
|
|
52
|
+
<Icon name="mail" />
|
|
53
|
+
<Badge number={5} />
|
|
54
|
+
</span>
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
In normal flow, such as a list item's trailing slot, pass `standalone`. `ListItem`'s `badge`
|
|
58
|
+
prop already does this.
|
|
59
|
+
|
|
60
|
+
<Canvas of={BadgeStories.Standalone} />
|
|
61
|
+
|
|
62
|
+
## Accessibility
|
|
63
|
+
|
|
64
|
+
- **Not announced on its own.** `Badge` renders a plain `<span>` with no role or live region.
|
|
65
|
+
Put the count in the anchor's accessible name (e.g. `aria-label="Inbox, 5 new"`), or use an
|
|
66
|
+
`aria-live` region if changes must be announced.
|
|
67
|
+
- **Contrast.** The badge uses the error/on-error pair in every theme, so its label keeps
|
|
68
|
+
contrast against its own container.
|
|
69
|
+
- **Clipping.** An anchored badge overhangs the icon by 2dp at the top and past the trailing edge
|
|
70
|
+
as it widens. Make sure no ancestor with `overflow: hidden` clips it.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
<!--
|
|
2
|
-
Badge renders `absolute`
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
Badge renders `absolute` by default, offset from its positioned ancestor's top-trailing corner
|
|
3
|
+
per the M3 spec, so that ancestor must hug the 24dp icon (not a larger indicator container).
|
|
4
|
+
NavbarItem/RailItem already wire this up internally via their `badge` prop; the stories below
|
|
5
|
+
reproduce that same `relative inline-flex` wrapper by hand so Badge can be previewed in
|
|
6
|
+
isolation. `standalone` renders it in normal flow instead (e.g. ListItem's trailing slot).
|
|
7
7
|
-->
|
|
8
8
|
<script module lang="ts">
|
|
9
9
|
import { defineMeta } from '@storybook/addon-svelte-csf';
|
|
@@ -18,41 +18,59 @@
|
|
|
18
18
|
control: 'select',
|
|
19
19
|
options: ['sm', 'lg']
|
|
20
20
|
},
|
|
21
|
-
number: { control: 'number' }
|
|
21
|
+
number: { control: 'number' },
|
|
22
|
+
max: { control: 'number' },
|
|
23
|
+
standalone: { control: 'boolean' }
|
|
22
24
|
},
|
|
23
25
|
args: {
|
|
24
26
|
size: 'lg',
|
|
25
|
-
number: 5
|
|
27
|
+
number: 5,
|
|
28
|
+
max: 999,
|
|
29
|
+
standalone: false
|
|
26
30
|
}
|
|
27
31
|
});
|
|
28
32
|
</script>
|
|
29
33
|
|
|
30
34
|
<Story name="Playground">
|
|
31
35
|
{#snippet template(args)}
|
|
32
|
-
<
|
|
36
|
+
<span class="relative inline-flex">
|
|
33
37
|
<Icon name="mail" />
|
|
34
|
-
<Badge size={args.size} number={args.number} />
|
|
35
|
-
</
|
|
38
|
+
<Badge size={args.size} number={args.number} max={args.max} standalone={args.standalone} />
|
|
39
|
+
</span>
|
|
36
40
|
{/snippet}
|
|
37
41
|
</Story>
|
|
38
42
|
|
|
39
|
-
<Story name="Dot (Small)" asChild>
|
|
40
|
-
<
|
|
43
|
+
<Story name="Dot (Small)" exportName="DotSmall" asChild>
|
|
44
|
+
<span class="relative inline-flex">
|
|
41
45
|
<Icon name="notifications" />
|
|
42
46
|
<Badge size="sm" />
|
|
43
|
-
</
|
|
47
|
+
</span>
|
|
44
48
|
</Story>
|
|
45
49
|
|
|
46
|
-
<Story name="Numbered (Large)" asChild>
|
|
47
|
-
<
|
|
50
|
+
<Story name="Numbered (Large)" exportName="NumberedLarge" asChild>
|
|
51
|
+
<span class="relative inline-flex">
|
|
48
52
|
<Icon name="mail" />
|
|
49
53
|
<Badge size="lg" number={7} />
|
|
50
|
-
</
|
|
54
|
+
</span>
|
|
51
55
|
</Story>
|
|
52
56
|
|
|
53
|
-
<Story name="
|
|
54
|
-
<
|
|
57
|
+
<Story name="Two digits" asChild>
|
|
58
|
+
<span class="relative inline-flex">
|
|
55
59
|
<Icon name="mail" />
|
|
56
|
-
<Badge size="lg" number={
|
|
57
|
-
</
|
|
60
|
+
<Badge size="lg" number={42} />
|
|
61
|
+
</span>
|
|
62
|
+
</Story>
|
|
63
|
+
|
|
64
|
+
<Story name="Max character count (999+)" exportName="MaxCharacterCount" asChild>
|
|
65
|
+
<span class="relative inline-flex">
|
|
66
|
+
<Icon name="mail" />
|
|
67
|
+
<Badge size="lg" number={1280} />
|
|
68
|
+
</span>
|
|
69
|
+
</Story>
|
|
70
|
+
|
|
71
|
+
<Story name="Standalone" asChild>
|
|
72
|
+
<span class="gap-spacing-100 inline-flex items-center">
|
|
73
|
+
<Badge size="sm" standalone />
|
|
74
|
+
<Badge size="lg" number={3} standalone />
|
|
75
|
+
</span>
|
|
58
76
|
</Story>
|
|
@@ -12,15 +12,22 @@ Large badges are used for specific counts.
|
|
|
12
12
|
import { badge } from './theme.js';
|
|
13
13
|
import type { BadgeProps } from './types.js';
|
|
14
14
|
|
|
15
|
-
const {
|
|
15
|
+
const {
|
|
16
|
+
number,
|
|
17
|
+
size = 'lg',
|
|
18
|
+
max = 999,
|
|
19
|
+
standalone = false,
|
|
20
|
+
class: className,
|
|
21
|
+
...restProps
|
|
22
|
+
}: BadgeProps = $props();
|
|
16
23
|
|
|
17
|
-
const styling = $derived(badge({ size }));
|
|
24
|
+
const styling = $derived(badge({ size, standalone }));
|
|
18
25
|
</script>
|
|
19
26
|
|
|
20
27
|
{#if size === 'sm' || number}
|
|
21
|
-
<
|
|
28
|
+
<span class={clsx(styling, className)} {...restProps}>
|
|
22
29
|
{#if size !== 'sm' && number}
|
|
23
|
-
{number >
|
|
30
|
+
{number > max ? `${max}+` : number}
|
|
24
31
|
{/if}
|
|
25
|
-
</
|
|
32
|
+
</span>
|
|
26
33
|
{/if}
|
|
@@ -1,16 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* M3 badge (https://m3.material.io/components/badges/specs).
|
|
3
|
+
*
|
|
4
|
+
* Anchored offsets are measured from the positioned ancestor's top-trailing corner, so that
|
|
5
|
+
* ancestor must hug the icon (24dp box), not the larger active-indicator container:
|
|
6
|
+
* - small: 6dp, its bottom-leading corner 6dp down / 6dp in from the icon's top-trailing corner,
|
|
7
|
+
* i.e. flush with that corner (`top-spacing-0 right-spacing-0`).
|
|
8
|
+
* - large: 16dp tall, bottom-leading corner 14dp down / 12dp in from the icon's top-trailing
|
|
9
|
+
* corner, i.e. top = 14 − 16 = −2dp, left = 100% − 12dp. Anchored by its leading edge so a
|
|
10
|
+
* wider count grows away from the icon.
|
|
11
|
+
*/
|
|
1
12
|
export declare const badge: import("tailwind-variants").TVReturnType<{
|
|
2
13
|
size: {
|
|
3
|
-
sm: "size-
|
|
4
|
-
lg: "h-
|
|
14
|
+
sm: "size-spacing-75";
|
|
15
|
+
lg: "h-spacing-200 min-w-spacing-200 px-spacing-50 md-sys-typescale-label-small whitespace-nowrap tabular-nums";
|
|
5
16
|
};
|
|
6
|
-
|
|
17
|
+
standalone: {
|
|
18
|
+
true: "relative";
|
|
19
|
+
false: "absolute pointer-events-none";
|
|
20
|
+
};
|
|
21
|
+
}, undefined, "bg-md-sys-color-error text-md-sys-color-on-error rounded-full inline-flex shrink-0 items-center justify-center", {
|
|
7
22
|
size: {
|
|
8
|
-
sm: "size-
|
|
9
|
-
lg: "h-
|
|
23
|
+
sm: "size-spacing-75";
|
|
24
|
+
lg: "h-spacing-200 min-w-spacing-200 px-spacing-50 md-sys-typescale-label-small whitespace-nowrap tabular-nums";
|
|
25
|
+
};
|
|
26
|
+
standalone: {
|
|
27
|
+
true: "relative";
|
|
28
|
+
false: "absolute pointer-events-none";
|
|
10
29
|
};
|
|
11
30
|
}, undefined, import("tailwind-variants").TVReturnTypeLike<{
|
|
12
31
|
size: {
|
|
13
|
-
sm: "size-
|
|
14
|
-
lg: "h-
|
|
32
|
+
sm: "size-spacing-75";
|
|
33
|
+
lg: "h-spacing-200 min-w-spacing-200 px-spacing-50 md-sys-typescale-label-small whitespace-nowrap tabular-nums";
|
|
34
|
+
};
|
|
35
|
+
standalone: {
|
|
36
|
+
true: "relative";
|
|
37
|
+
false: "absolute pointer-events-none";
|
|
15
38
|
};
|
|
16
39
|
}, undefined>>;
|
|
@@ -1,10 +1,30 @@
|
|
|
1
1
|
import { tv } from 'tailwind-variants';
|
|
2
|
+
/**
|
|
3
|
+
* M3 badge (https://m3.material.io/components/badges/specs).
|
|
4
|
+
*
|
|
5
|
+
* Anchored offsets are measured from the positioned ancestor's top-trailing corner, so that
|
|
6
|
+
* ancestor must hug the icon (24dp box), not the larger active-indicator container:
|
|
7
|
+
* - small: 6dp, its bottom-leading corner 6dp down / 6dp in from the icon's top-trailing corner,
|
|
8
|
+
* i.e. flush with that corner (`top-spacing-0 right-spacing-0`).
|
|
9
|
+
* - large: 16dp tall, bottom-leading corner 14dp down / 12dp in from the icon's top-trailing
|
|
10
|
+
* corner, i.e. top = 14 − 16 = −2dp, left = 100% − 12dp. Anchored by its leading edge so a
|
|
11
|
+
* wider count grows away from the icon.
|
|
12
|
+
*/
|
|
2
13
|
export const badge = tv({
|
|
3
|
-
base: 'bg-md-sys-color-error text-md-sys-color-on-error
|
|
14
|
+
base: 'bg-md-sys-color-error text-md-sys-color-on-error rounded-full inline-flex shrink-0 items-center justify-center',
|
|
4
15
|
variants: {
|
|
5
16
|
size: {
|
|
6
|
-
sm: 'size-
|
|
7
|
-
lg: 'h-
|
|
17
|
+
sm: 'size-spacing-75',
|
|
18
|
+
lg: 'h-spacing-200 min-w-spacing-200 px-spacing-50 md-sys-typescale-label-small whitespace-nowrap tabular-nums'
|
|
19
|
+
},
|
|
20
|
+
standalone: {
|
|
21
|
+
true: 'relative',
|
|
22
|
+
false: 'absolute pointer-events-none'
|
|
8
23
|
}
|
|
9
|
-
}
|
|
24
|
+
},
|
|
25
|
+
compoundVariants: [
|
|
26
|
+
{ standalone: false, size: 'sm', class: 'top-spacing-0 right-spacing-0' },
|
|
27
|
+
{ standalone: false, size: 'lg', class: '-top-spacing-25 left-[calc(100%-12px)]' }
|
|
28
|
+
],
|
|
29
|
+
defaultVariants: { size: 'lg', standalone: false }
|
|
10
30
|
});
|
|
@@ -2,17 +2,31 @@ import type { HTMLAttributes } from 'svelte/elements';
|
|
|
2
2
|
import type { VariantProps } from 'tailwind-variants';
|
|
3
3
|
import type { badge } from './theme.js';
|
|
4
4
|
export type BadgeVariants = VariantProps<typeof badge>;
|
|
5
|
-
export type BadgeProps = BadgeVariants & HTMLAttributes<
|
|
5
|
+
export type BadgeProps = BadgeVariants & HTMLAttributes<HTMLSpanElement> & {
|
|
6
6
|
/**
|
|
7
7
|
* The size of the badge.
|
|
8
|
-
* - 'sm': Small badge, no number displayed.
|
|
9
|
-
* - 'lg': Large badge, displays number.
|
|
8
|
+
* - 'sm': Small badge (6dp dot), no number displayed.
|
|
9
|
+
* - 'lg': Large badge (16dp tall), displays number.
|
|
10
10
|
*/
|
|
11
11
|
size?: BadgeVariants['size'];
|
|
12
12
|
/**
|
|
13
13
|
* The number to display in the badge.
|
|
14
|
-
* Values greater than
|
|
14
|
+
* Values greater than `max` are displayed as `${max}+`.
|
|
15
15
|
* If size is 'sm', the number is not displayed.
|
|
16
16
|
*/
|
|
17
17
|
number?: number;
|
|
18
|
+
/**
|
|
19
|
+
* Largest count shown before collapsing to `${max}+`. M3 caps a large badge at four
|
|
20
|
+
* characters including the "+" (16×34dp container), so the default is 999 → "999+".
|
|
21
|
+
* @default 999
|
|
22
|
+
*/
|
|
23
|
+
max?: number;
|
|
24
|
+
/**
|
|
25
|
+
* By default the badge is absolutely positioned on its nearest positioned ancestor's
|
|
26
|
+
* top-trailing corner per the M3 offsets — that ancestor should hug the icon (e.g.
|
|
27
|
+
* `<span class="relative inline-flex">` around a 24dp `Icon`). Set `standalone` to render it
|
|
28
|
+
* in normal flow instead, e.g. in a list item's trailing slot.
|
|
29
|
+
* @default false
|
|
30
|
+
*/
|
|
31
|
+
standalone?: boolean;
|
|
18
32
|
};
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { Meta, Title, Subtitle, Canvas, Controls } from '@storybook/addon-docs/blocks';
|
|
2
|
+
import * as ButtonStories from './Button.stories.svelte';
|
|
3
|
+
|
|
4
|
+
<Meta of={ButtonStories} />
|
|
5
|
+
|
|
6
|
+
<Title />
|
|
7
|
+
|
|
8
|
+
<Subtitle>Buttons prompt most actions in a UI.</Subtitle>
|
|
9
|
+
|
|
10
|
+
[M3 spec](https://m3.material.io/components/buttons/specs) ·
|
|
11
|
+
`import { Button, Toggle } from '@noxlovette/material';`
|
|
12
|
+
|
|
13
|
+
<Canvas of={ButtonStories.Playground} />
|
|
14
|
+
|
|
15
|
+
<Controls of={ButtonStories.Playground} />
|
|
16
|
+
|
|
17
|
+
## Choosing a button
|
|
18
|
+
|
|
19
|
+
One high-emphasis button per screen, for its primary action. Show the rest's importance through
|
|
20
|
+
their colour style.
|
|
21
|
+
|
|
22
|
+
| Emphasis | Use | For example |
|
|
23
|
+
| -------- | --------------------------------------------------------------------- | -------------------- |
|
|
24
|
+
| Highest | `FAB` or extended FAB, for the screen's main action | Compose, Create |
|
|
25
|
+
| High | `Button variant="filled"`: final or unblocking actions | Save, Confirm, Done |
|
|
26
|
+
| High | `SplitButton`: a key action with related options | Send + Schedule send |
|
|
27
|
+
| Medium | `variant="tonal"`: important, a step below filled | Save draft |
|
|
28
|
+
| Medium | `variant="elevated"`: only to stand apart from a patterned background | Add to cart |
|
|
29
|
+
| Medium | `variant="outlined"`: attention without being primary; leaving a flow | View all, Cancel |
|
|
30
|
+
| Low | `variant="text"`: optional actions | Learn more |
|
|
31
|
+
| Low | `ButtonIcon`: compact supplementary actions | Favourite, Print |
|
|
32
|
+
|
|
33
|
+
Put buttons side by side rather than stacked when there's room, with the higher-emphasis one
|
|
34
|
+
for the more important action.
|
|
35
|
+
|
|
36
|
+
<Canvas of={ButtonStories.ColourStyles} />
|
|
37
|
+
|
|
38
|
+
## Sizes
|
|
39
|
+
|
|
40
|
+
| `size` | Height | Padding | Icon | Label |
|
|
41
|
+
| ------ | ------ | ------- | ---- | -------------- |
|
|
42
|
+
| `xs` | 32dp | 12dp | 20dp | label large |
|
|
43
|
+
| `sm` | 40dp | 16dp | 20dp | label large |
|
|
44
|
+
| `md` | 56dp | 24dp | 24dp | title medium |
|
|
45
|
+
| `lg` | 96dp | 48dp | 32dp | headline small |
|
|
46
|
+
| `xl` | 136dp | 64dp | 40dp | headline large |
|
|
47
|
+
|
|
48
|
+
`sm` is the default. XS and S buttons keep a 48dp target area around them, so leave room
|
|
49
|
+
between them (a `ButtonGroup` does). The outline thickens to 2dp at L and 3dp at XL.
|
|
50
|
+
|
|
51
|
+
<Canvas of={ButtonStories.Sizes} />
|
|
52
|
+
|
|
53
|
+
## Shape
|
|
54
|
+
|
|
55
|
+
`round` (default) is fully rounded; `square` has 12, 12, 16, 28 and 28dp corners from XS to XL.
|
|
56
|
+
While pressed, both morph to the same tighter corner (8, 8, 12, 16, 16dp) on the fast spatial
|
|
57
|
+
spring, which carries its velocity when you let go mid-morph, so a quick tap still bounces.
|
|
58
|
+
|
|
59
|
+
<Canvas of={ButtonStories.RoundAndSquare} />
|
|
60
|
+
|
|
61
|
+
## Toggle buttons
|
|
62
|
+
|
|
63
|
+
`Toggle` is a button with a selected state (`aria-pressed`). Selecting changes its colours and
|
|
64
|
+
swaps its shape: round becomes square, square becomes round. It comes in the elevated, filled,
|
|
65
|
+
tonal and outlined styles; there is no text toggle. See **Buttons/Toggle**.
|
|
66
|
+
|
|
67
|
+
## States and accessibility
|
|
68
|
+
|
|
69
|
+
- Hover, focus and press tint the container 8%, 10% and 10% in the content colour. Keyboard
|
|
70
|
+
focus draws a 3dp ring 2dp outside the button.
|
|
71
|
+
- Disabled buttons drop to a 10% on-surface container and 38% on-surface content, and lose
|
|
72
|
+
their elevation. A disabled link gets `aria-disabled` and leaves the tab order.
|
|
73
|
+
- `loading` swaps the icon (or the label, with no icon) for a loading indicator and sets
|
|
74
|
+
`aria-busy`.
|
|
75
|
+
|
|
76
|
+
<Canvas of={ButtonStories.Disabled} />
|
|
77
|
+
|
|
78
|
+
## Where this differs from the spec
|
|
79
|
+
|
|
80
|
+
- The text button's disabled state has no container. Its token lists a 10% container, but the
|
|
81
|
+
spec's figures show none.
|
|
82
|
+
- Shape morphs use the library's fast spatial spring (stiffness 800, damping 0.6) instead of
|
|
83
|
+
the button token's 1400 / 0.9, as every motion here uses the Expressive springs.
|
|
84
|
+
- `color` (primary, secondary, tertiary, error) is gone. M3 has one colour mapping per style;
|
|
85
|
+
restyle with a class if you need another role, keeping 3:1 contrast.
|
|
@@ -2,33 +2,22 @@
|
|
|
2
2
|
import { defineMeta } from '@storybook/addon-svelte-csf';
|
|
3
3
|
import Button from './Button.svelte';
|
|
4
4
|
|
|
5
|
+
const variants = ['elevated', 'filled', 'tonal', 'outlined', 'text'] as const;
|
|
6
|
+
const sizes = ['xs', 'sm', 'md', 'lg', 'xl'] as const;
|
|
7
|
+
|
|
5
8
|
const { Story } = defineMeta({
|
|
6
9
|
title: 'Buttons/Button',
|
|
7
10
|
component: Button,
|
|
8
11
|
argTypes: {
|
|
9
|
-
variant: {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
},
|
|
13
|
-
color: {
|
|
14
|
-
control: 'select',
|
|
15
|
-
options: ['default', 'primary', 'secondary', 'tertiary', 'error']
|
|
16
|
-
},
|
|
17
|
-
size: {
|
|
18
|
-
control: 'select',
|
|
19
|
-
options: ['xs', 'sm', 'md', 'lg', 'xl']
|
|
20
|
-
},
|
|
21
|
-
shape: {
|
|
22
|
-
control: 'select',
|
|
23
|
-
options: ['round', 'square']
|
|
24
|
-
},
|
|
12
|
+
variant: { control: 'select', options: variants },
|
|
13
|
+
size: { control: 'select', options: sizes },
|
|
14
|
+
shape: { control: 'inline-radio', options: ['round', 'square'] },
|
|
25
15
|
disabled: { control: 'boolean' },
|
|
26
16
|
loading: { control: 'boolean' }
|
|
27
17
|
},
|
|
28
18
|
args: {
|
|
29
19
|
variant: 'filled',
|
|
30
|
-
|
|
31
|
-
size: 'md',
|
|
20
|
+
size: 'sm',
|
|
32
21
|
shape: 'round',
|
|
33
22
|
disabled: false,
|
|
34
23
|
loading: false
|
|
@@ -36,15 +25,61 @@
|
|
|
36
25
|
});
|
|
37
26
|
</script>
|
|
38
27
|
|
|
39
|
-
<Story name="Playground">
|
|
28
|
+
<Story name="Playground">
|
|
29
|
+
{#snippet template(args)}
|
|
30
|
+
<Button {...args}>Label</Button>
|
|
31
|
+
{/snippet}
|
|
32
|
+
</Story>
|
|
33
|
+
|
|
34
|
+
<Story name="Colour styles" asChild>
|
|
35
|
+
<div class="gap-spacing-200 p-spacing-300 flex flex-wrap items-center">
|
|
36
|
+
{#each variants as variant (variant)}
|
|
37
|
+
<Button {variant}>{variant[0].toUpperCase() + variant.slice(1)}</Button>
|
|
38
|
+
{/each}
|
|
39
|
+
</div>
|
|
40
|
+
</Story>
|
|
41
|
+
|
|
42
|
+
<Story name="With icon" asChild>
|
|
43
|
+
<div class="gap-spacing-200 p-spacing-300 flex flex-wrap items-center">
|
|
44
|
+
{#each variants as variant (variant)}
|
|
45
|
+
<Button {variant} iconProps={{ name: 'add' }}>Create</Button>
|
|
46
|
+
{/each}
|
|
47
|
+
</div>
|
|
48
|
+
</Story>
|
|
49
|
+
|
|
50
|
+
<Story name="Sizes" asChild>
|
|
51
|
+
<div class="gap-spacing-200 p-spacing-300 flex flex-col items-start">
|
|
52
|
+
{#each sizes as size (size)}
|
|
53
|
+
<div class="gap-spacing-200 flex items-center">
|
|
54
|
+
<Button {size} iconProps={{ name: 'send' }}>Send</Button>
|
|
55
|
+
<Button {size} shape="square" variant="tonal" iconProps={{ name: 'send' }}>Send</Button>
|
|
56
|
+
<Button {size} variant="outlined">Cancel</Button>
|
|
57
|
+
</div>
|
|
58
|
+
{/each}
|
|
59
|
+
</div>
|
|
60
|
+
</Story>
|
|
61
|
+
|
|
62
|
+
<Story name="Round and square" asChild>
|
|
63
|
+
<div class="gap-spacing-200 p-spacing-300 flex flex-wrap items-center">
|
|
64
|
+
<Button size="md">Round</Button>
|
|
65
|
+
<Button size="md" shape="square">Square</Button>
|
|
66
|
+
<p class="md-sys-typescale-body-medium text-md-sys-color-on-surface-variant w-full">
|
|
67
|
+
Press and hold: both morph to the same smaller corner.
|
|
68
|
+
</p>
|
|
69
|
+
</div>
|
|
70
|
+
</Story>
|
|
71
|
+
|
|
72
|
+
<Story name="Disabled" asChild>
|
|
73
|
+
<div class="gap-spacing-200 p-spacing-300 flex flex-wrap items-center">
|
|
74
|
+
{#each variants as variant (variant)}
|
|
75
|
+
<Button {variant} disabled>{variant}</Button>
|
|
76
|
+
{/each}
|
|
77
|
+
</div>
|
|
78
|
+
</Story>
|
|
40
79
|
|
|
41
|
-
<Story name="
|
|
42
|
-
<div class="
|
|
43
|
-
<Button
|
|
44
|
-
<Button
|
|
45
|
-
<Button variant="tonal" color="primary">Tonal</Button>
|
|
46
|
-
<Button variant="outlined" color="primary">Outlined</Button>
|
|
47
|
-
<Button variant="text" color="primary">Text</Button>
|
|
48
|
-
<Button variant="bare" color="primary">Bare</Button>
|
|
80
|
+
<Story name="Link" asChild>
|
|
81
|
+
<div class="gap-spacing-200 p-spacing-300 flex">
|
|
82
|
+
<Button href="#" variant="text">Learn more</Button>
|
|
83
|
+
<Button href="#" variant="outlined" disabled>Disabled link</Button>
|
|
49
84
|
</div>
|
|
50
85
|
</Story>
|