@noxlovette/material 0.6.0 → 0.7.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/claude-skill/material-design/SKILL.md +5 -2
- package/claude-skill/material-design/references/accessibility-checklist.md +5 -0
- package/claude-skill/material-design/references/component-patterns.md +24 -3
- package/claude-skill/material-design/references/motion-guide.md +53 -11
- package/claude-skill/material-design/references/tokens-and-styles.md +4 -0
- package/dist/animation/TransitionPatterns.stories.svelte +50 -0
- package/dist/animation/containerTransform.js +10 -4
- package/dist/animation/reducedMotion.d.ts +2 -0
- package/dist/animation/reducedMotion.js +2 -0
- package/dist/animation/sharedAxisTransition.d.ts +20 -3
- package/dist/animation/sharedAxisTransition.js +67 -8
- package/dist/attachments/drag.d.ts +52 -0
- package/dist/attachments/drag.js +217 -0
- package/dist/attachments/index.d.ts +1 -0
- package/dist/attachments/index.js +1 -0
- package/dist/components/badge/theme.js +1 -1
- package/dist/components/buttons/button-group/theme.d.ts +1 -1
- package/dist/components/buttons/button-group/theme.js +1 -1
- package/dist/components/buttons/connected/theme.d.ts +1 -1
- package/dist/components/buttons/connected/theme.js +1 -1
- package/dist/components/buttons/split-button/SplitButton.svelte +1 -1
- package/dist/components/buttons/split-button/theme.d.ts +1 -1
- package/dist/components/buttons/split-button/theme.js +1 -1
- package/dist/components/buttons/theme.d.ts +1 -1
- package/dist/components/buttons/theme.js +3 -3
- package/dist/components/cards/theme.js +1 -1
- package/dist/components/chips/Chip.mdx +24 -11
- package/dist/components/chips/Chip.stories.svelte +10 -0
- package/dist/components/chips/Chip.svelte +58 -18
- package/dist/components/chips/Chip.svelte.d.ts +3 -1
- package/dist/components/chips/ChipGroup.stories.svelte +73 -0
- package/dist/components/chips/ChipGroup.stories.svelte.d.ts +4 -0
- package/dist/components/chips/ChipGroup.svelte +242 -0
- package/dist/components/chips/ChipGroup.svelte.d.ts +33 -0
- package/dist/components/chips/index.d.ts +1 -0
- package/dist/components/chips/index.js +1 -0
- package/dist/components/chips/theme.d.ts +183 -22
- package/dist/components/chips/theme.js +117 -26
- package/dist/components/chips/types.d.ts +36 -2
- 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 +2 -2
- package/dist/components/containers/app/theme.js +2 -2
- package/dist/components/containers/bottom-sheet/BottomSheet.stories.svelte +1 -1
- package/dist/components/containers/bottom-sheet/theme.d.ts +1 -1
- package/dist/components/containers/bottom-sheet/theme.js +2 -2
- package/dist/components/containers/carousel/theme.d.ts +1 -1
- package/dist/components/containers/carousel/theme.js +1 -1
- package/dist/components/containers/context-menu/theme.d.ts +1 -1
- package/dist/components/containers/context-menu/theme.js +2 -2
- package/dist/components/containers/dialogue/Dialogue.svelte +1 -1
- package/dist/components/containers/dialogue/theme.d.ts +1 -1
- package/dist/components/containers/dialogue/theme.js +3 -3
- package/dist/components/containers/dialogue/types.d.ts +1 -1
- package/dist/components/containers/divider/theme.d.ts +1 -1
- package/dist/components/containers/divider/theme.js +1 -1
- package/dist/components/containers/link-preview/theme.d.ts +1 -1
- package/dist/components/containers/link-preview/theme.js +2 -2
- package/dist/components/containers/list/List.svelte +8 -2
- package/dist/components/containers/list/ListItem.mdx +6 -0
- package/dist/components/containers/list/ListItem.svelte +77 -2
- package/dist/components/containers/list/context.d.ts +14 -0
- package/dist/components/containers/list/theme.d.ts +7 -1
- package/dist/components/containers/list/theme.js +11 -3
- package/dist/components/containers/menu/Menu.svelte +1 -1
- package/dist/components/containers/menu/MenuSub.svelte +1 -1
- package/dist/components/containers/menu/theme.d.ts +1 -1
- package/dist/components/containers/menu/theme.js +1 -1
- package/dist/components/containers/pane/DraggablePane.svelte +25 -63
- package/dist/components/containers/pane/Pane.svelte +1 -1
- package/dist/components/containers/pane/theme.d.ts +1 -1
- package/dist/components/containers/pane/theme.js +35 -9
- package/dist/components/containers/popover/theme.d.ts +4 -4
- package/dist/components/containers/popover/theme.js +2 -2
- package/dist/components/containers/scroll-area/theme.js +1 -1
- package/dist/components/containers/side-sheet/theme.d.ts +1 -1
- package/dist/components/containers/side-sheet/theme.js +1 -1
- package/dist/components/date/theme.d.ts +7 -7
- package/dist/components/date/theme.js +1 -1
- package/dist/components/forms/checkbox/theme.d.ts +1 -1
- package/dist/components/forms/checkbox/theme.js +2 -2
- package/dist/components/forms/command/theme.d.ts +4 -4
- package/dist/components/forms/command/theme.js +1 -1
- package/dist/components/forms/pin/theme.d.ts +1 -1
- package/dist/components/forms/pin/theme.js +1 -1
- package/dist/components/forms/radio-group/theme.d.ts +1 -1
- package/dist/components/forms/radio-group/theme.js +1 -1
- package/dist/components/forms/search/theme.d.ts +1 -1
- package/dist/components/forms/search/theme.js +1 -1
- package/dist/components/forms/select/Select.svelte +2 -2
- package/dist/components/forms/select/theme.d.ts +1 -1
- package/dist/components/forms/select/theme.js +2 -2
- package/dist/components/forms/slider/theme.d.ts +1 -1
- package/dist/components/forms/slider/theme.js +1 -1
- package/dist/components/forms/switch/theme.d.ts +1 -1
- package/dist/components/forms/switch/theme.js +1 -1
- package/dist/components/forms/textfield/theme.d.ts +1 -1
- package/dist/components/forms/textfield/theme.js +1 -1
- package/dist/components/forms/toggle-group/theme.d.ts +1 -1
- package/dist/components/forms/toggle-group/theme.js +1 -1
- package/dist/components/forms/tooltip/theme.d.ts +1 -1
- package/dist/components/forms/tooltip/theme.js +2 -2
- package/dist/components/misc/Avatar.stories.svelte +56 -7
- package/dist/components/misc/Avatar.stories.svelte.d.ts +2 -17
- package/dist/components/misc/Avatar.svelte +82 -8
- package/dist/components/misc/Avatar.svelte.d.ts +5 -0
- package/dist/components/misc/ThemeSwitcher.svelte +1 -1
- package/dist/components/misc/theme.d.ts +6 -0
- package/dist/components/misc/theme.js +6 -4
- package/dist/components/misc/types.d.ts +17 -1
- package/dist/components/nav/appbar/theme.d.ts +1 -1
- package/dist/components/nav/appbar/theme.js +3 -2
- package/dist/components/nav/breadcrumb/theme.d.ts +1 -1
- package/dist/components/nav/breadcrumb/theme.js +1 -1
- package/dist/components/nav/currentRoute.d.ts +11 -0
- package/dist/components/nav/currentRoute.js +28 -0
- package/dist/components/nav/navbar/NavbarItem.svelte +3 -6
- package/dist/components/nav/navbar/theme.d.ts +3 -3
- package/dist/components/nav/navbar/theme.js +2 -2
- package/dist/components/nav/rail/Rail.mdx +65 -23
- package/dist/components/nav/rail/Rail.stories.svelte +24 -4
- package/dist/components/nav/rail/Rail.stories.svelte.d.ts +2 -17
- package/dist/components/nav/rail/Rail.svelte +165 -48
- package/dist/components/nav/rail/Rail.svelte.d.ts +6 -3
- package/dist/components/nav/rail/RailItem.svelte +122 -65
- package/dist/components/nav/rail/RailItem.svelte.d.ts +3 -2
- package/dist/components/nav/rail/theme.d.ts +70 -85
- package/dist/components/nav/rail/theme.js +80 -67
- package/dist/components/nav/rail/types.d.ts +4 -0
- package/dist/components/nav/tabs/Tabs.stories.svelte +2 -1
- package/dist/components/nav/tabs/theme.d.ts +1 -1
- package/dist/components/nav/tabs/theme.js +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/snackbar/theme.d.ts +1 -1
- package/dist/components/snackbar/theme.js +2 -2
- package/dist/components/table/theme.d.ts +1 -1
- package/dist/components/table/theme.js +1 -1
- package/dist/components/time/TimeField.svelte +1 -1
- package/dist/components/time/theme.d.ts +1 -1
- package/dist/components/time/theme.js +1 -1
- package/dist/components/toolbar/theme.d.ts +1 -1
- package/dist/components/toolbar/theme.js +2 -2
- package/dist/components/typography/body/theme.d.ts +1 -1
- package/dist/components/typography/body/theme.js +1 -1
- package/dist/components/typography/display/theme.d.ts +1 -1
- package/dist/components/typography/display/theme.js +1 -1
- package/dist/components/typography/headline/theme.d.ts +1 -1
- package/dist/components/typography/headline/theme.js +1 -1
- package/dist/components/typography/kbd/theme.d.ts +1 -1
- package/dist/components/typography/kbd/theme.js +1 -1
- package/dist/components/typography/label/theme.js +1 -1
- package/dist/components/typography/title/theme.d.ts +1 -1
- package/dist/components/typography/title/theme.js +1 -1
- package/dist/index.css +3 -0
- package/dist/styles/components.css +50 -0
- package/dist/styles/icon.css +13 -0
- package/dist/styles/layers.css +33 -0
- package/dist/utils/icon/Icon.stories.svelte +97 -0
- package/dist/utils/icon/Icon.stories.svelte.d.ts +4 -0
- package/dist/utils/icon/Icon.svelte +101 -12
- package/dist/utils/icon/Icon.svelte.d.ts +9 -0
- package/dist/utils/icon/MaterialSymbolsProvider.svelte +11 -4
- package/dist/utils/icon/base-icons.d.ts +1 -1
- package/dist/utils/icon/base-icons.js +1 -1
- package/dist/utils/icon/icon-names.d.ts +2 -0
- package/dist/utils/icon/icon-names.js +2 -0
- package/dist/utils/icon/swap.d.ts +6 -0
- package/dist/utils/icon/swap.js +45 -0
- package/dist/utils/icon/theme.d.ts +1 -1
- package/dist/utils/icon/theme.js +1 -1
- package/dist/utils/icon/types.d.ts +59 -7
- package/dist/utils/tv.d.ts +5 -0
- package/dist/utils/tv.js +20 -0
- package/package.json +2 -1
|
@@ -1,10 +1,35 @@
|
|
|
1
|
-
import { tv } from '
|
|
1
|
+
import { tv } from '../../../utils/tv.js';
|
|
2
|
+
/*
|
|
3
|
+
M3 Expressive navigation rail (https://m3.material.io/components/navigation-rail/specs):
|
|
4
|
+
- Container: `surface-container`, the spec's optional container role, which is this library's
|
|
5
|
+
window colour (App), so the rail reads as part of the window beside `surface` panes rather
|
|
6
|
+
than as a strip. The modal rail's token is `surface-container` too.
|
|
7
|
+
- Collapsed: 96dp wide, no elevation or shape. Destinations sit 4dp apart.
|
|
8
|
+
- Expanded: hugs its widest destination between 220 and 360dp, destinations touching. Standard
|
|
9
|
+
(lg+, pushes content) keeps the collapsed container; modal (md, over a scrim) adds
|
|
10
|
+
elevation 3 and 16dp trailing corners.
|
|
11
|
+
- 44dp above the first element; at least 40dp between the menu/FAB header and the destinations.
|
|
12
|
+
- Header elements sit in a 56dp column 20dp from the leading edge, the same column as the
|
|
13
|
+
destinations' active indicators, so nothing shifts sideways when the rail expands.
|
|
14
|
+
Expanding is one spatial spring on a progress value, 0 collapsed to 1 expanded, which
|
|
15
|
+
Rail.svelte writes to `--rail-p` (after Compose's WideNavigationRail). The width, the gap
|
|
16
|
+
between destinations, the modal corners and each destination's geometry all follow it, so
|
|
17
|
+
nothing here transitions spatially on its own.
|
|
18
|
+
*/
|
|
2
19
|
export const rail = tv({
|
|
3
20
|
slots: {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
21
|
+
// Modal corners grow with the progress (0 → 16dp); the standard rail stays square.
|
|
22
|
+
base: 'rounded-r-[calc(var(--radius-lg)_*_var(--rail-p,0))] lg:rounded-r-none hidden md:flex flex-col z-layer-rail overflow-hidden pt-(--md-comp-nav-rail-collapsed-top-space) pb-spacing-250 bg-md-sys-color-surface-container transition-[box-shadow] md-sys-motion-effects',
|
|
23
|
+
// Always start-aligned: collapsed, the content box is exactly the 56dp column, so this is
|
|
24
|
+
// centred anyway. Centring it would fling the menu and FAB to the middle of the still-wide
|
|
25
|
+
// rail the moment a collapse starts.
|
|
26
|
+
header: 'flex flex-col items-start gap-spacing-300 px-spacing-250',
|
|
27
|
+
menu: 'flex w-spacing-700 justify-center',
|
|
28
|
+
nav: 'flex min-h-spacing-0 w-full flex-1 flex-col',
|
|
29
|
+
// 4dp between destinations collapsed, 0 expanded, following the progress.
|
|
30
|
+
items: 'flex w-full flex-col overflow-x-hidden overflow-y-auto [scrollbar-width:none] gap-[calc(var(--spacing-spacing-50)_*_(1_-_var(--rail-p,0)))]',
|
|
31
|
+
ghost: 'hidden md:block shrink-0 w-(--md-comp-nav-rail-collapsed-container-width) lg:w-(--rail-width)',
|
|
32
|
+
scrim: 'hidden md:block lg:hidden inset-spacing-0 z-layer-rail bg-md-sys-color-scrim/32 transition-opacity md-sys-motion-effects'
|
|
8
33
|
},
|
|
9
34
|
variants: {
|
|
10
35
|
anchor: {
|
|
@@ -19,15 +44,19 @@ export const rail = tv({
|
|
|
19
44
|
},
|
|
20
45
|
expanded: {
|
|
21
46
|
true: {
|
|
22
|
-
base: '
|
|
23
|
-
|
|
47
|
+
base: 'w-max min-w-(--md-comp-nav-rail-expanded-container-width-minimum) max-w-(--md-comp-nav-rail-expanded-container-width-maximum) pt-(--md-comp-nav-rail-expanded-top-space) shadow-elevation-3 lg:shadow-elevation-0',
|
|
48
|
+
scrim: 'opacity-100'
|
|
24
49
|
},
|
|
25
50
|
false: {
|
|
26
|
-
base: 'w-
|
|
27
|
-
|
|
28
|
-
ghost: 'w-24'
|
|
51
|
+
base: 'w-(--md-comp-nav-rail-collapsed-container-width)',
|
|
52
|
+
scrim: 'pointer-events-none opacity-0'
|
|
29
53
|
}
|
|
30
54
|
},
|
|
55
|
+
/* Header space: only when there is a header to keep the destinations away from. */
|
|
56
|
+
header: {
|
|
57
|
+
true: { nav: 'mt-spacing-500' },
|
|
58
|
+
false: {}
|
|
59
|
+
},
|
|
31
60
|
rounded: {
|
|
32
61
|
true: {
|
|
33
62
|
base: 'rounded-xl'
|
|
@@ -36,81 +65,65 @@ export const rail = tv({
|
|
|
36
65
|
}
|
|
37
66
|
},
|
|
38
67
|
defaultVariants: {
|
|
39
|
-
anchor: 'viewport'
|
|
68
|
+
anchor: 'viewport',
|
|
69
|
+
header: false
|
|
40
70
|
}
|
|
41
71
|
});
|
|
72
|
+
/*
|
|
73
|
+
One destination. The link spans the rail's full width (M3: the target area always does); the
|
|
74
|
+
active indicator inside it hugs its contents. Collapsed, the indicator is 56×32 around the icon
|
|
75
|
+
with the label 4dp below; expanded, it's a 56dp pill around icon and label, 16dp padding, 8dp
|
|
76
|
+
between them. State layers are `on-secondary-container` at 8% hover and 10% focus/press, drawn
|
|
77
|
+
on the indicator but triggered anywhere on the link. Selecting a destination grows its fill
|
|
78
|
+
out from the centre (M3's active indicator, after Compose's NavigationRailItem).
|
|
79
|
+
|
|
80
|
+
Geometry isn't here: it interpolates on the rail's expand progress, in RailItem.svelte's
|
|
81
|
+
<style>. `layout` is which side of the halfway point that progress is on, and decides only
|
|
82
|
+
what may switch while the label is invisible: its typescale and colour.
|
|
83
|
+
*/
|
|
42
84
|
export const railElement = tv({
|
|
43
85
|
slots: {
|
|
44
|
-
base: 'group relative
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
86
|
+
base: 'group rail-item relative flex w-full px-spacing-250 outline-none',
|
|
87
|
+
// As wide as the expanded pill, so an expanded rail (w-max) hugs its widest destination.
|
|
88
|
+
sizer: 'relative h-full shrink-0 pl-spacing-600 pr-spacing-200',
|
|
89
|
+
measure: 'invisible md-sys-typescale-label-large whitespace-nowrap',
|
|
90
|
+
indicator: 'rail-indicator absolute left-spacing-0 isolate rounded-full state-layer before:rounded-full',
|
|
91
|
+
// The selected fill, under the state layer. It grows from the indicator's centre to its
|
|
92
|
+
// edges on select and shrinks back on deselect, on RailItem's --rail-sel spring.
|
|
93
|
+
fill: 'rail-fill absolute -z-10 rounded-full bg-md-sys-color-secondary-container',
|
|
94
|
+
icon: 'rail-icon absolute left-spacing-200 inline-flex',
|
|
95
|
+
label: 'rail-label absolute whitespace-nowrap transition-colors md-sys-motion-fast-effects'
|
|
49
96
|
},
|
|
50
97
|
variants: {
|
|
51
98
|
active: {
|
|
52
99
|
true: {
|
|
53
|
-
|
|
54
|
-
label: 'font-bold',
|
|
55
|
-
iconContainer: 'group-hover:text-md-sys-color-secondary bg-md-sys-color-secondary-container'
|
|
100
|
+
icon: 'text-md-sys-color-on-secondary-container'
|
|
56
101
|
},
|
|
57
102
|
false: {
|
|
58
|
-
|
|
59
|
-
|
|
103
|
+
icon: 'text-md-sys-color-on-surface-variant',
|
|
104
|
+
label: 'text-md-sys-color-on-surface-variant'
|
|
60
105
|
}
|
|
61
106
|
},
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
content: 'p-spacing-200 gap-spacing-150',
|
|
66
|
-
iconContainer: '',
|
|
67
|
-
label: 'md-sys-typescale-label-large'
|
|
68
|
-
},
|
|
69
|
-
false: {
|
|
70
|
-
base: 'text-center justify-center',
|
|
71
|
-
content: 'flex-col',
|
|
72
|
-
iconContainer: 'py-spacing-75 px-spacing-200',
|
|
73
|
-
label: 'md-sys-typescale-label-medium'
|
|
74
|
-
}
|
|
107
|
+
layout: {
|
|
108
|
+
top: { label: 'md-sys-typescale-label-medium' },
|
|
109
|
+
start: { label: 'md-sys-typescale-label-large' }
|
|
75
110
|
},
|
|
76
111
|
disabled: {
|
|
77
112
|
true: {
|
|
78
113
|
base: 'cursor-not-allowed opacity-38'
|
|
79
|
-
}
|
|
80
|
-
},
|
|
81
|
-
mobile: {
|
|
82
|
-
true: {
|
|
83
|
-
base: 'flex-1 flex-col items-center justify-center h-full min-w-spacing-0 max-w-[168px]',
|
|
84
|
-
content: 'py-spacing-0 gap-spacing-50 items-center justify-center w-full',
|
|
85
|
-
iconContainer: 'h-spacing-400 w-spacing-800 py-spacing-0 px-spacing-0',
|
|
86
|
-
icon: 'size-spacing-300',
|
|
87
|
-
label: 'truncate w-full text-center'
|
|
88
114
|
},
|
|
89
|
-
false: {
|
|
115
|
+
false: {
|
|
116
|
+
// State layer and focus ring on the indicator, triggered by the full-width link.
|
|
117
|
+
indicator: 'group-hover:before:bg-md-sys-color-on-secondary-container/8 group-focus-visible:before:bg-md-sys-color-on-secondary-container/10 group-active:before:bg-md-sys-color-on-secondary-container/10 group-focus-visible:outline-3 group-focus-visible:outline-offset-2 group-focus-visible:outline-md-sys-color-secondary'
|
|
118
|
+
}
|
|
90
119
|
}
|
|
91
120
|
},
|
|
92
121
|
compoundVariants: [
|
|
93
|
-
{
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
},
|
|
101
|
-
{
|
|
102
|
-
expanded: true,
|
|
103
|
-
active: false,
|
|
104
|
-
class: {
|
|
105
|
-
content: 'group-hover:bg-md-sys-color-surface-variant'
|
|
106
|
-
}
|
|
107
|
-
},
|
|
108
|
-
{
|
|
109
|
-
expanded: false,
|
|
110
|
-
active: false,
|
|
111
|
-
class: {
|
|
112
|
-
iconContainer: 'group-hover:bg-md-sys-color-surface-variant'
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
]
|
|
122
|
+
{ active: true, layout: 'top', class: { label: 'text-md-sys-color-secondary' } },
|
|
123
|
+
{ active: true, layout: 'start', class: { label: 'text-md-sys-color-on-secondary-container' } }
|
|
124
|
+
],
|
|
125
|
+
defaultVariants: {
|
|
126
|
+
layout: 'top',
|
|
127
|
+
disabled: false
|
|
128
|
+
}
|
|
116
129
|
});
|
|
@@ -41,6 +41,10 @@ export type RailProps = RailVariants & HTMLAttributes<HTMLDivElement> & {
|
|
|
41
41
|
anchor?: RailVariants['anchor'];
|
|
42
42
|
/** Top offset in px for viewport/parent anchor (e.g. height of a top bar). Default 0. */
|
|
43
43
|
railTop?: number;
|
|
44
|
+
/** Tooltip and accessible name of the toggle while collapsed. Default 'Expand navigation'. */
|
|
45
|
+
expandLabel?: string;
|
|
46
|
+
/** Tooltip and accessible name of the toggle while expanded. Default 'Collapse navigation'. */
|
|
47
|
+
collapseLabel?: string;
|
|
44
48
|
/**
|
|
45
49
|
* @deprecated No effect: Rail no longer renders a navigation bar below `md`. Mount a `Navbar`
|
|
46
50
|
* next to it for small windows.
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import TabHolder from './TabHolder.svelte';
|
|
4
4
|
import TabContent from './TabContent.svelte';
|
|
5
5
|
import Body from '../../typography/body/Body.svelte';
|
|
6
|
+
import type { TabProps } from './types.js';
|
|
6
7
|
|
|
7
8
|
const { Story } = defineMeta({
|
|
8
9
|
title: 'Navigation/Tabs',
|
|
@@ -27,7 +28,7 @@
|
|
|
27
28
|
{ value: 'flights', name: 'Flights', iconProps: { name: 'flight' } },
|
|
28
29
|
{ value: 'trips', name: 'Trips', iconProps: { name: 'luggage' } },
|
|
29
30
|
{ value: 'explore', name: 'Explore', iconProps: { name: 'explore' } }
|
|
30
|
-
];
|
|
31
|
+
] satisfies TabProps[];
|
|
31
32
|
</script>
|
|
32
33
|
|
|
33
34
|
<Story name="Playground">
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type VariantProps } from '
|
|
1
|
+
import { type VariantProps } from '../../../utils/tv.js';
|
|
2
2
|
export type TabVariants = VariantProps<typeof tab>;
|
|
3
3
|
export type TabHolderVariants = VariantProps<typeof tabHolder>;
|
|
4
4
|
export declare const tabHolder: import("tailwind-variants").TVReturnType<{
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { tv } from '
|
|
1
|
+
import { tv } from '../../utils/tv.js';
|
|
2
2
|
export const pill = tv({
|
|
3
3
|
base: 'relative inline-flex items-center justify-center px-spacing-200 py-spacing-75 md-sys-typescale-label-large select-none rounded-full whitespace-nowrap',
|
|
4
4
|
variants: {
|
|
@@ -11,7 +11,7 @@ The track always keeps a gap either side of the bar.
|
|
|
11
11
|
-->
|
|
12
12
|
<script lang="ts">
|
|
13
13
|
import clsx from 'clsx';
|
|
14
|
-
import { tv } from '
|
|
14
|
+
import { tv } from '../../utils/tv.js';
|
|
15
15
|
import { Progress } from 'bits-ui';
|
|
16
16
|
import { animate, type AnimationPlaybackControls } from 'motion';
|
|
17
17
|
import { springTokens, springTransition } from '../../animation/spring.js';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { tv } from '
|
|
1
|
+
import { tv } from '../../utils/tv.js';
|
|
2
2
|
export const snackbar = tv({
|
|
3
3
|
slots: {
|
|
4
|
-
base: 'rounded-xs relative min-h-spacing-600 md:max-h-17 flex z-
|
|
4
|
+
base: 'rounded-xs relative min-h-spacing-600 md:max-h-17 flex z-layer-snackbar items-center bg-md-sys-color-inverse-surface shadow-elevation-3 pr-spacing-100 pl-spacing-200 justify-between h-max py-spacing-150',
|
|
5
5
|
label: 'text-md-sys-color-inverse-primary md-sys-typescale-label-large px-spacing-150 cursor-pointer ',
|
|
6
6
|
actionWrapper: 'flex items-center z-40',
|
|
7
7
|
supportingText: 'text-md-sys-color-inverse-on-surface md-sys-typescale-body-medium max-w-[60ch] ',
|
|
@@ -92,7 +92,7 @@ It combines a Material 3 Textfield with a TimepickerInput for intuitive time sel
|
|
|
92
92
|
align="start"
|
|
93
93
|
sideOffset={12}
|
|
94
94
|
collisionPadding={8}
|
|
95
|
-
class="z-
|
|
95
|
+
class="z-layer-popup"
|
|
96
96
|
>
|
|
97
97
|
{#snippet child({ wrapperProps, props, open })}
|
|
98
98
|
<div {...wrapperProps}>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type VariantProps } from '
|
|
1
|
+
import { type VariantProps } from '../../utils/tv.js';
|
|
2
2
|
export type TimepickerVariants = VariantProps<typeof timepicker>;
|
|
3
3
|
export declare const timepicker: import("tailwind-variants").TVReturnType<{
|
|
4
4
|
[key: string]: {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type VariantProps } from '
|
|
1
|
+
import { type VariantProps } from '../../utils/tv.js';
|
|
2
2
|
export type ToolbarVariants = VariantProps<typeof toolbar>;
|
|
3
3
|
export type ToolbarButtonVariants = VariantProps<typeof toolbarButton>;
|
|
4
4
|
export type ToolbarGroupItemVariants = VariantProps<typeof toolbarGroupItem>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { tv } from '
|
|
1
|
+
import { tv } from '../../utils/tv.js';
|
|
2
2
|
export const toolbar = tv({
|
|
3
3
|
slots: {
|
|
4
4
|
// Layout/position only — no paint. Holds one implicit `segment` by default, or,
|
|
@@ -33,7 +33,7 @@ export const toolbar = tv({
|
|
|
33
33
|
},
|
|
34
34
|
variant: {
|
|
35
35
|
floating: { root: 'inline-flex', segment: 'rounded-full shadow-elevation-1' },
|
|
36
|
-
docked: { root: 'fixed left-spacing-0 z-
|
|
36
|
+
docked: { root: 'fixed left-spacing-0 z-layer-bar w-full', segment: 'w-full rounded-none' }
|
|
37
37
|
},
|
|
38
38
|
color: {
|
|
39
39
|
standard: { segment: 'bg-md-sys-color-surface-container' },
|
package/dist/index.css
CHANGED
|
@@ -3,5 +3,8 @@
|
|
|
3
3
|
@import './styles/motion.css';
|
|
4
4
|
@import './styles/rounding.css';
|
|
5
5
|
@import './styles/elevation.css';
|
|
6
|
+
@import './styles/layers.css';
|
|
7
|
+
@import './styles/components.css';
|
|
8
|
+
@import './styles/icon.css';
|
|
6
9
|
@import './styles/prose.css';
|
|
7
10
|
@import './styles/component.css';
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* M3 component dimensions that aren't on the spacing scale (issue #30). Each property is named
|
|
3
|
+
* after its token in the M3 token database, md.comp.<component>.<…> with dots as dashes, and
|
|
4
|
+
* used as `w-(--md-comp-…)`. A dimension that lands on the spacing grid uses the spacing token
|
|
5
|
+
* instead (the rail's 4dp item gap is `gap-spacing-50`, not a property here).
|
|
6
|
+
*/
|
|
7
|
+
:root {
|
|
8
|
+
/* Navigation rail: https://m3.material.io/components/navigation-rail/specs */
|
|
9
|
+
--md-comp-nav-rail-collapsed-container-width: 6rem; /* 96dp */
|
|
10
|
+
--md-comp-nav-rail-collapsed-top-space: 2.75rem; /* 44dp */
|
|
11
|
+
--md-comp-nav-rail-expanded-top-space: 2.75rem; /* 44dp */
|
|
12
|
+
--md-comp-nav-rail-expanded-container-width-minimum: 13.75rem; /* 220dp */
|
|
13
|
+
--md-comp-nav-rail-expanded-container-width-maximum: 22.5rem; /* 360dp */
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/*
|
|
17
|
+
* How far the page's content starts from the leading edge to clear a viewport-anchored Rail.
|
|
18
|
+
* The Rail writes --md-rail-width (its drawn width, every frame while it springs) on <html>;
|
|
19
|
+
* with no Rail mounted it's unset and the inset is 0. On medium windows the expanded rail is
|
|
20
|
+
* modal and overlays the content, so the inset stays at the collapsed width; from lg the
|
|
21
|
+
* standard rail pushes the content, so the inset follows its width. App's shell pads by it;
|
|
22
|
+
* fixed surfaces that span the window (AppBar) start at it. Custom layouts: `ps-(--md-rail-inset)`.
|
|
23
|
+
*/
|
|
24
|
+
:root {
|
|
25
|
+
--md-rail-inset: 0px;
|
|
26
|
+
}
|
|
27
|
+
@media (width >= 48rem) {
|
|
28
|
+
:root {
|
|
29
|
+
--md-rail-inset: var(--md-rail-rest, 0px);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
@media (width >= 64rem) {
|
|
33
|
+
:root {
|
|
34
|
+
--md-rail-inset: var(--md-rail-width, 0px);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/*
|
|
39
|
+
* A page built on App behaves as an app, not a document: scrolling stops at its edges instead of
|
|
40
|
+
* bouncing (macOS/iOS rubber-banding) or chaining into pull-to-refresh, which showed the blank
|
|
41
|
+
* canvas past App's shell. The canvas takes the window colour anyway, for the browsers that
|
|
42
|
+
* still overscroll and the safe areas around it. Scoped to pages with an App, and in the base
|
|
43
|
+
* layer, so a consumer can restore overscroll with one `html { overscroll-behavior: auto }`.
|
|
44
|
+
*/
|
|
45
|
+
@layer base {
|
|
46
|
+
:root:has(.md-app) {
|
|
47
|
+
overscroll-behavior: none;
|
|
48
|
+
background-color: var(--color-md-sys-color-surface-container);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Default grade for Icon's `grad="auto"`. Light icons on a dark background look heavier than dark
|
|
3
|
+
ones on a light background (visual bleed), so M3 drops the grade to -25 on dark UI.
|
|
4
|
+
https://m3.material.io/styles/icons/applying-icons#grade
|
|
5
|
+
*/
|
|
6
|
+
:root {
|
|
7
|
+
--md-icon-grade: 0;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.dark,
|
|
11
|
+
[data-theme^='dark'] {
|
|
12
|
+
--md-icon-grade: -25;
|
|
13
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Stacking layers for surfaces that float over the page. M3 defines no z-index tokens, so the
|
|
3
|
+
* library names its own: every fixed, sticky or portaled component takes one of these instead
|
|
4
|
+
* of a number, so their relative order is set here and nowhere else. Apply with
|
|
5
|
+
* `z-layer-<name>` (z-layer-modal); override the value on :root with `--z-layer-<name>`.
|
|
6
|
+
* Stacking inside one component (a slider thumb over its track) keeps plain z-10/z-20.
|
|
7
|
+
*
|
|
8
|
+
* Order, lowest first:
|
|
9
|
+
* bar Navbar, AppBar, ActionRail, docked Toolbar
|
|
10
|
+
* rail Rail and its tablet scrim (the expanded rail covers the bars)
|
|
11
|
+
* sheet standard (non-modal) BottomSheet
|
|
12
|
+
* fab fixed FABs such as ThemeSwitcher
|
|
13
|
+
* pane DraggablePane and its minimised pill, floating windows over app chrome
|
|
14
|
+
* modal Dialogue scrim and content, a FAB's container-transform surface
|
|
15
|
+
* snackbar stays readable while a dialog is open
|
|
16
|
+
* popup menus, selects, tooltips, popovers, date/time pickers, opened from any layer
|
|
17
|
+
* beneath, including a dialog or a pane
|
|
18
|
+
* Modal sheets are native <dialog>s in the top layer and sit above all of these.
|
|
19
|
+
*/
|
|
20
|
+
@theme static {
|
|
21
|
+
--z-layer-bar: 30;
|
|
22
|
+
--z-layer-rail: 40;
|
|
23
|
+
--z-layer-sheet: 40;
|
|
24
|
+
--z-layer-fab: 50;
|
|
25
|
+
--z-layer-pane: 60;
|
|
26
|
+
--z-layer-modal: 70;
|
|
27
|
+
--z-layer-snackbar: 80;
|
|
28
|
+
--z-layer-popup: 90;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
@utility z-layer-* {
|
|
32
|
+
z-index: --value(--z-layer-*);
|
|
33
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
<script module lang="ts">
|
|
2
|
+
import { defineMeta } from '@storybook/addon-svelte-csf';
|
|
3
|
+
import Body from '../../components/typography/body/Body.svelte';
|
|
4
|
+
import ButtonIcon from '../../components/buttons/ButtonIcon.svelte';
|
|
5
|
+
import Icon from './Icon.svelte';
|
|
6
|
+
|
|
7
|
+
const sizes = ['xs', 'sm', 'md', 'lg', 'xl'] as const;
|
|
8
|
+
const variants = ['rounded', 'outlined', 'sharp'] as const;
|
|
9
|
+
|
|
10
|
+
const { Story } = defineMeta({
|
|
11
|
+
title: 'Utils/Icon',
|
|
12
|
+
component: Icon,
|
|
13
|
+
tags: ['autodocs'],
|
|
14
|
+
argTypes: {
|
|
15
|
+
size: { control: 'select', options: ['inline', ...sizes] },
|
|
16
|
+
variant: { control: 'inline-radio', options: variants },
|
|
17
|
+
fill: { control: { type: 'range', min: 0, max: 1, step: 0.1 } },
|
|
18
|
+
wght: { control: { type: 'range', min: 100, max: 700, step: 100 } },
|
|
19
|
+
grad: { control: 'select', options: ['auto', -50, -25, 0, 100, 200] },
|
|
20
|
+
opsz: { control: { type: 'range', min: 20, max: 48, step: 1 } },
|
|
21
|
+
transition: { control: 'inline-radio', options: ['none', 'fade', 'rotate'] }
|
|
22
|
+
},
|
|
23
|
+
args: { name: 'favorite', size: 'xl', variant: 'rounded', fill: 0, wght: 400, grad: 'auto' }
|
|
24
|
+
});
|
|
25
|
+
</script>
|
|
26
|
+
|
|
27
|
+
<script lang="ts">
|
|
28
|
+
let menuOpen = $state(false);
|
|
29
|
+
let adding = $state(false);
|
|
30
|
+
let playing = $state(false);
|
|
31
|
+
</script>
|
|
32
|
+
|
|
33
|
+
<Story name="Playground" />
|
|
34
|
+
|
|
35
|
+
<!-- Toggle each button, and toggle again mid-flight: the spring reverses from where it is. -->
|
|
36
|
+
<Story name="Transitions" asChild>
|
|
37
|
+
<div class="gap-spacing-300 flex items-center">
|
|
38
|
+
<ButtonIcon
|
|
39
|
+
variant="standard"
|
|
40
|
+
tooltipContent="rotate: menu ↔ menu_open"
|
|
41
|
+
iconProps={{ name: menuOpen ? 'menu_open' : 'menu', transition: 'rotate' }}
|
|
42
|
+
onclick={() => (menuOpen = !menuOpen)}
|
|
43
|
+
/>
|
|
44
|
+
<ButtonIcon
|
|
45
|
+
variant="tonal"
|
|
46
|
+
tooltipContent="rotate: add ↔ close"
|
|
47
|
+
iconProps={{ name: adding ? 'close' : 'add', transition: 'rotate' }}
|
|
48
|
+
onclick={() => (adding = !adding)}
|
|
49
|
+
/>
|
|
50
|
+
<ButtonIcon
|
|
51
|
+
variant="filled"
|
|
52
|
+
tooltipContent="fade: play_arrow ↔ pause"
|
|
53
|
+
iconProps={{ name: playing ? 'pause' : 'play_arrow', transition: 'fade' }}
|
|
54
|
+
onclick={() => (playing = !playing)}
|
|
55
|
+
/>
|
|
56
|
+
</div>
|
|
57
|
+
</Story>
|
|
58
|
+
|
|
59
|
+
<Story name="Styles" asChild>
|
|
60
|
+
<div class="gap-spacing-300 flex">
|
|
61
|
+
{#each variants as variant (variant)}
|
|
62
|
+
<Icon name="home" size="lg" {variant} />
|
|
63
|
+
{/each}
|
|
64
|
+
</div>
|
|
65
|
+
</Story>
|
|
66
|
+
|
|
67
|
+
<Story name="Sizes" asChild>
|
|
68
|
+
<div class="gap-spacing-300 flex items-end">
|
|
69
|
+
{#each sizes as size (size)}
|
|
70
|
+
<Icon name="settings" {size} />
|
|
71
|
+
{/each}
|
|
72
|
+
</div>
|
|
73
|
+
</Story>
|
|
74
|
+
|
|
75
|
+
<Story name="Fill for state" asChild>
|
|
76
|
+
<div class="gap-spacing-300 flex">
|
|
77
|
+
<Icon name="favorite" size="lg" fill={0} />
|
|
78
|
+
<Icon name="favorite" size="lg" fill={1} />
|
|
79
|
+
</div>
|
|
80
|
+
</Story>
|
|
81
|
+
|
|
82
|
+
<Story name="Weights" asChild>
|
|
83
|
+
<div class="gap-spacing-200 flex">
|
|
84
|
+
{#each [200, 300, 400, 500, 600, 700] as wght (wght)}
|
|
85
|
+
<Icon name="search" size="lg" {wght} />
|
|
86
|
+
{/each}
|
|
87
|
+
</div>
|
|
88
|
+
</Story>
|
|
89
|
+
|
|
90
|
+
<Story name="Inline with text" asChild>
|
|
91
|
+
<Body size="large">
|
|
92
|
+
Saved to favorites <Icon name="favorite" size="inline" fill={1} />, shared <Icon
|
|
93
|
+
name="share"
|
|
94
|
+
size="inline"
|
|
95
|
+
/>
|
|
96
|
+
</Body>
|
|
97
|
+
</Story>
|