@noxlovette/material 0.4.7 → 0.5.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.
Files changed (134) hide show
  1. package/dist/animation/TransitionPatterns.stories.svelte +357 -0
  2. package/dist/animation/TransitionPatterns.stories.svelte.d.ts +3 -0
  3. package/dist/animation/containerTransform.d.ts +26 -12
  4. package/dist/animation/containerTransform.js +22 -138
  5. package/dist/animation/enterExit.d.ts +21 -3
  6. package/dist/animation/enterExit.js +69 -22
  7. package/dist/animation/index.d.ts +1 -1
  8. package/dist/animation/index.js +1 -1
  9. package/dist/animation/presence.svelte.d.ts +47 -0
  10. package/dist/animation/presence.svelte.js +84 -0
  11. package/dist/animation/sharedAxisTransition.d.ts +35 -37
  12. package/dist/animation/sharedAxisTransition.js +50 -22
  13. package/dist/animation/skeleton.d.ts +11 -0
  14. package/dist/animation/skeleton.js +23 -0
  15. package/dist/animation/spring.d.ts +61 -0
  16. package/dist/animation/spring.js +53 -0
  17. package/dist/animation/springValue.svelte.d.ts +22 -0
  18. package/dist/animation/springValue.svelte.js +42 -0
  19. package/dist/animation/transition.d.ts +3 -1
  20. package/dist/animation/transition.js +3 -1
  21. package/dist/attachments/clickOutside.d.ts +13 -0
  22. package/dist/attachments/clickOutside.js +18 -0
  23. package/dist/attachments/index.d.ts +1 -0
  24. package/dist/attachments/index.js +1 -0
  25. package/dist/components/buttons/FAB.svelte +23 -16
  26. package/dist/components/buttons/FABMenu.svelte +24 -29
  27. package/dist/components/buttons/FABMenu.svelte.d.ts +2 -1
  28. package/dist/components/buttons/FABMenuItem.svelte +23 -20
  29. package/dist/components/buttons/FABMenuItem.svelte.d.ts +5 -1
  30. package/dist/components/buttons/split-button/SplitButton.svelte +10 -17
  31. package/dist/components/buttons/split-button/theme.js +1 -1
  32. package/dist/components/buttons/types.d.ts +3 -3
  33. package/dist/components/cards/theme.js +1 -1
  34. package/dist/components/containers/bottom-sheet/BottomSheet.stories.svelte +8 -12
  35. package/dist/components/containers/bottom-sheet/BottomSheet.svelte +67 -55
  36. package/dist/components/containers/bottom-sheet/BottomSheet.svelte.d.ts +1 -1
  37. package/dist/components/containers/bottom-sheet/types.d.ts +8 -2
  38. package/dist/components/containers/context-menu/ContextMenu.svelte +23 -36
  39. package/dist/components/containers/context-menu/theme.js +2 -2
  40. package/dist/components/containers/dialogue/Dialogue.svelte +49 -65
  41. package/dist/components/containers/link-preview/LinkPreview.svelte +12 -23
  42. package/dist/components/containers/link-preview/theme.d.ts +3 -3
  43. package/dist/components/containers/menu/Menu.svelte +14 -21
  44. package/dist/components/containers/menu/MenuSub.svelte +10 -17
  45. package/dist/components/containers/pane/DraggablePane.svelte +90 -5
  46. package/dist/components/containers/pane/DraggablePane.svelte.d.ts +1 -1
  47. package/dist/components/containers/pane/theme.js +2 -2
  48. package/dist/components/containers/popover/Popover.svelte +31 -42
  49. package/dist/components/containers/popover/theme.d.ts +3 -3
  50. package/dist/components/containers/scroll-area/theme.js +2 -2
  51. package/dist/components/containers/side-sheet/SideSheet.stories.svelte +10 -15
  52. package/dist/components/containers/side-sheet/SideSheet.svelte +44 -44
  53. package/dist/components/containers/side-sheet/SideSheet.svelte.d.ts +4 -3
  54. package/dist/components/containers/side-sheet/types.d.ts +8 -2
  55. package/dist/components/date/DateField.svelte +85 -92
  56. package/dist/components/date/DateField.svelte.d.ts +2 -5
  57. package/dist/components/date/DateRangeField.svelte +113 -155
  58. package/dist/components/date/DateRangeField.svelte.d.ts +2 -5
  59. package/dist/components/date/theme.d.ts +95 -0
  60. package/dist/components/date/theme.js +99 -14
  61. package/dist/components/date/types.d.ts +13 -0
  62. package/dist/components/forms/checkbox/theme.js +2 -2
  63. package/dist/components/forms/command/theme.d.ts +3 -3
  64. package/dist/components/forms/command/theme.js +1 -1
  65. package/dist/components/forms/pin/theme.js +2 -2
  66. package/dist/components/forms/radio-group/theme.js +2 -2
  67. package/dist/components/forms/select/Select.svelte +42 -54
  68. package/dist/components/forms/select/theme.js +4 -4
  69. package/dist/components/forms/slider/Slider.svelte +144 -126
  70. package/dist/components/forms/slider/Slider.svelte.d.ts +3 -0
  71. package/dist/components/forms/slider/theme.d.ts +154 -48
  72. package/dist/components/forms/slider/theme.js +60 -20
  73. package/dist/components/forms/slider/types.d.ts +1 -1
  74. package/dist/components/forms/switch/theme.js +4 -4
  75. package/dist/components/forms/textfield/Textfield.svelte +1 -1
  76. package/dist/components/forms/textfield/theme.d.ts +9 -0
  77. package/dist/components/forms/textfield/theme.js +26 -9
  78. package/dist/components/forms/toggle-group/theme.js +1 -1
  79. package/dist/components/forms/tooltip/Tooltip.svelte +24 -35
  80. package/dist/components/nav/breadcrumb/theme.js +1 -1
  81. package/dist/components/nav/navbar/theme.js +2 -2
  82. package/dist/components/nav/rail/Rail.svelte +4 -5
  83. package/dist/components/nav/rail/theme.js +7 -7
  84. package/dist/components/nav/tabs/theme.js +1 -1
  85. package/dist/components/pill/theme.d.ts +1 -1
  86. package/dist/components/pill/theme.js +1 -1
  87. package/dist/components/progress/CircularProgress.svelte +78 -4
  88. package/dist/components/progress/CircularProgress.svelte.d.ts +5 -0
  89. package/dist/components/progress/LinearProgress.svelte +70 -7
  90. package/dist/components/progress/LinearProgress.svelte.d.ts +5 -0
  91. package/dist/components/progress/WavyLinearProgress.svelte +27 -3
  92. package/dist/components/progress/WavyLinearProgress.svelte.d.ts +3 -0
  93. package/dist/components/progress/_wavy.d.ts +2 -0
  94. package/dist/components/progress/_wavy.js +3 -1
  95. package/dist/components/snackbar/Snackbar.svelte +13 -17
  96. package/dist/components/table/Table.stories.svelte +24 -0
  97. package/dist/components/table/TableBody.svelte +3 -16
  98. package/dist/components/table/TableBody.svelte.d.ts +1 -5
  99. package/dist/components/table/TableHeader.svelte +1 -1
  100. package/dist/components/table/theme.js +2 -2
  101. package/dist/components/table/types.d.ts +0 -7
  102. package/dist/components/time/TimeField.stories.svelte +41 -0
  103. package/dist/components/time/TimeField.stories.svelte.d.ts +19 -0
  104. package/dist/components/time/TimeField.svelte +62 -61
  105. package/dist/components/toolbar/theme.js +2 -2
  106. package/dist/index.d.ts +1 -1
  107. package/dist/index.js +1 -1
  108. package/dist/styles/component.css +21 -22
  109. package/dist/styles/motion.css +317 -38
  110. package/dist/utils/Layer.svelte +16 -29
  111. package/dist/utils/icon/LoadingIndicator.svelte +61 -22
  112. package/dist/utils/icon/loadingShapes.d.ts +1 -0
  113. package/dist/utils/icon/loadingShapes.js +15 -0
  114. package/package.json +5 -2
  115. package/dist/actions/clickOutside.d.ts +0 -3
  116. package/dist/actions/clickOutside.js +0 -13
  117. package/dist/actions/floating.d.ts +0 -20
  118. package/dist/actions/floating.js +0 -87
  119. package/dist/actions/index.d.ts +0 -6
  120. package/dist/actions/index.js +0 -6
  121. package/dist/actions/keyboard.d.ts +0 -3
  122. package/dist/actions/keyboard.js +0 -14
  123. package/dist/actions/portal.d.ts +0 -3
  124. package/dist/actions/portal.js +0 -8
  125. package/dist/actions/positionFloating.d.ts +0 -10
  126. package/dist/actions/positionFloating.js +0 -59
  127. package/dist/actions/rovingFocusGroup.d.ts +0 -20
  128. package/dist/actions/rovingFocusGroup.js +0 -82
  129. package/dist/animation/easing.d.ts +0 -6
  130. package/dist/animation/easing.js +0 -78
  131. package/dist/animation/outroClass.d.ts +0 -3
  132. package/dist/animation/outroClass.js +0 -20
  133. package/dist/animation/transitionTypes.d.ts +0 -8
  134. package/dist/animation/transitionTypes.js +0 -1
@@ -1,77 +1,183 @@
1
1
  import { type VariantProps } from 'tailwind-variants';
2
+ /**
3
+ * M3 Expressive slider: an active and an inactive track separated from a bar handle by a 6dp gap.
4
+ * Track/handle positions are set inline by `Slider.svelte` from one animated value; these slots
5
+ * only carry size, shape and color.
6
+ *
7
+ * https://m3.material.io/components/sliders/specs
8
+ */
2
9
  export declare const slider: import("tailwind-variants").TVReturnType<{
3
10
  size: {
4
- xs: "[--track-height:1rem] [--handle-height:2.75rem] [--track-radius:var(--m3-shape-small)] [--icon-size:0]";
5
- s: "[--track-height:1.5rem] [--handle-height:2.75rem] [--track-radius:var(--m3-shape-small)] [--icon-size:0]";
6
- m: "[--track-height:2.5rem] [--handle-height:3.25rem] [--track-radius:var(--m3-shape-medium)] [--icon-size:1.5rem]";
7
- l: "[--track-height:3.5rem] [--handle-height:4.25rem] [--track-radius:var(--m3-shape-large)] [--icon-size:1.5rem]";
8
- xl: "[--track-height:6rem] [--handle-height:6.75rem] [--track-radius:var(--m3-shape-extra-large)] [--icon-size:2rem]";
11
+ xs: {
12
+ root: string;
13
+ };
14
+ s: {
15
+ root: string;
16
+ };
17
+ m: {
18
+ root: string;
19
+ };
20
+ l: {
21
+ root: string;
22
+ };
23
+ xl: {
24
+ root: string;
25
+ };
9
26
  };
10
27
  vertical: {
11
- true: "[writing-mode:sideways-lr]";
28
+ false: {
29
+ root: string;
30
+ track: string;
31
+ activeTrack: string;
32
+ inactiveTrack: string;
33
+ stop: string;
34
+ icon: string;
35
+ handle: string;
36
+ value: string;
37
+ };
38
+ true: {
39
+ root: string;
40
+ track: string;
41
+ activeTrack: string;
42
+ inactiveTrack: string;
43
+ stop: string;
44
+ icon: string;
45
+ handle: string;
46
+ value: string;
47
+ };
48
+ };
49
+ active: {
50
+ true: {
51
+ value: string;
52
+ };
12
53
  };
13
54
  }, {
14
55
  root: string;
15
- input: string;
16
- leadingIcon: string;
17
- leadingIconPop: string;
18
- trailingIcon: string;
19
- trailingIconPop: string;
20
- trackFill: string;
21
- trackRest: string;
22
- stopBase: string;
23
- stopFill: string;
24
- stopRest: string;
56
+ track: string;
57
+ activeTrack: string;
58
+ inactiveTrack: string;
59
+ stop: string;
60
+ stopOnActive: string;
61
+ stopOnInactive: string;
62
+ icon: string;
63
+ iconOnActive: string;
64
+ iconOnInactive: string;
25
65
  handle: string;
26
66
  value: string;
27
67
  }, undefined, {
28
68
  size: {
29
- xs: "[--track-height:1rem] [--handle-height:2.75rem] [--track-radius:var(--m3-shape-small)] [--icon-size:0]";
30
- s: "[--track-height:1.5rem] [--handle-height:2.75rem] [--track-radius:var(--m3-shape-small)] [--icon-size:0]";
31
- m: "[--track-height:2.5rem] [--handle-height:3.25rem] [--track-radius:var(--m3-shape-medium)] [--icon-size:1.5rem]";
32
- l: "[--track-height:3.5rem] [--handle-height:4.25rem] [--track-radius:var(--m3-shape-large)] [--icon-size:1.5rem]";
33
- xl: "[--track-height:6rem] [--handle-height:6.75rem] [--track-radius:var(--m3-shape-extra-large)] [--icon-size:2rem]";
69
+ xs: {
70
+ root: string;
71
+ };
72
+ s: {
73
+ root: string;
74
+ };
75
+ m: {
76
+ root: string;
77
+ };
78
+ l: {
79
+ root: string;
80
+ };
81
+ xl: {
82
+ root: string;
83
+ };
34
84
  };
35
85
  vertical: {
36
- true: "[writing-mode:sideways-lr]";
86
+ false: {
87
+ root: string;
88
+ track: string;
89
+ activeTrack: string;
90
+ inactiveTrack: string;
91
+ stop: string;
92
+ icon: string;
93
+ handle: string;
94
+ value: string;
95
+ };
96
+ true: {
97
+ root: string;
98
+ track: string;
99
+ activeTrack: string;
100
+ inactiveTrack: string;
101
+ stop: string;
102
+ icon: string;
103
+ handle: string;
104
+ value: string;
105
+ };
106
+ };
107
+ active: {
108
+ true: {
109
+ value: string;
110
+ };
37
111
  };
38
112
  }, {
39
113
  root: string;
40
- input: string;
41
- leadingIcon: string;
42
- leadingIconPop: string;
43
- trailingIcon: string;
44
- trailingIconPop: string;
45
- trackFill: string;
46
- trackRest: string;
47
- stopBase: string;
48
- stopFill: string;
49
- stopRest: string;
114
+ track: string;
115
+ activeTrack: string;
116
+ inactiveTrack: string;
117
+ stop: string;
118
+ stopOnActive: string;
119
+ stopOnInactive: string;
120
+ icon: string;
121
+ iconOnActive: string;
122
+ iconOnInactive: string;
50
123
  handle: string;
51
124
  value: string;
52
125
  }, import("tailwind-variants").TVReturnTypeLike<{
53
126
  size: {
54
- xs: "[--track-height:1rem] [--handle-height:2.75rem] [--track-radius:var(--m3-shape-small)] [--icon-size:0]";
55
- s: "[--track-height:1.5rem] [--handle-height:2.75rem] [--track-radius:var(--m3-shape-small)] [--icon-size:0]";
56
- m: "[--track-height:2.5rem] [--handle-height:3.25rem] [--track-radius:var(--m3-shape-medium)] [--icon-size:1.5rem]";
57
- l: "[--track-height:3.5rem] [--handle-height:4.25rem] [--track-radius:var(--m3-shape-large)] [--icon-size:1.5rem]";
58
- xl: "[--track-height:6rem] [--handle-height:6.75rem] [--track-radius:var(--m3-shape-extra-large)] [--icon-size:2rem]";
127
+ xs: {
128
+ root: string;
129
+ };
130
+ s: {
131
+ root: string;
132
+ };
133
+ m: {
134
+ root: string;
135
+ };
136
+ l: {
137
+ root: string;
138
+ };
139
+ xl: {
140
+ root: string;
141
+ };
59
142
  };
60
143
  vertical: {
61
- true: "[writing-mode:sideways-lr]";
144
+ false: {
145
+ root: string;
146
+ track: string;
147
+ activeTrack: string;
148
+ inactiveTrack: string;
149
+ stop: string;
150
+ icon: string;
151
+ handle: string;
152
+ value: string;
153
+ };
154
+ true: {
155
+ root: string;
156
+ track: string;
157
+ activeTrack: string;
158
+ inactiveTrack: string;
159
+ stop: string;
160
+ icon: string;
161
+ handle: string;
162
+ value: string;
163
+ };
164
+ };
165
+ active: {
166
+ true: {
167
+ value: string;
168
+ };
62
169
  };
63
170
  }, {
64
171
  root: string;
65
- input: string;
66
- leadingIcon: string;
67
- leadingIconPop: string;
68
- trailingIcon: string;
69
- trailingIconPop: string;
70
- trackFill: string;
71
- trackRest: string;
72
- stopBase: string;
73
- stopFill: string;
74
- stopRest: string;
172
+ track: string;
173
+ activeTrack: string;
174
+ inactiveTrack: string;
175
+ stop: string;
176
+ stopOnActive: string;
177
+ stopOnInactive: string;
178
+ icon: string;
179
+ iconOnActive: string;
180
+ iconOnInactive: string;
75
181
  handle: string;
76
182
  value: string;
77
183
  }>>;
@@ -1,33 +1,73 @@
1
1
  import { tv } from 'tailwind-variants';
2
+ /**
3
+ * M3 Expressive slider: an active and an inactive track separated from a bar handle by a 6dp gap.
4
+ * Track/handle positions are set inline by `Slider.svelte` from one animated value; these slots
5
+ * only carry size, shape and color.
6
+ *
7
+ * https://m3.material.io/components/sliders/specs
8
+ */
2
9
  export const slider = tv({
3
10
  slots: {
4
- root: 'slider-root group relative block min-w-40 [block-size:var(--handle-height)] [print-color-adjust:exact] [--m3-slider-track-out-shape:0.5rem] [--m3-slider-track-in-shape:0.125rem] [--m3-slider-handle-shape:var(--m3-shape-full)] [--functional-width:calc(100%-2*(0.25rem+0.125rem))] [--handle-left:calc(50%+var(--functional-width)*var(--handle)-0.125rem-0.375rem)] [--handle-center:calc(50%+var(--functional-width)*var(--handle))] [--handle-right:calc(50%+var(--functional-width)*var(--handle)+0.125rem+0.375rem)] cursor-pointer data-[disabled]:cursor-not-allowed',
5
- input: 'peer absolute left-1/2 [inline-size:calc(var(--functional-width)+1rem)] [block-size:100%] -translate-x-1/2 appearance-none opacity-0 m-0 enabled:cursor-pointer',
6
- leadingIcon: 'absolute top-1/2 left-1 h-[var(--icon-size)] w-[var(--icon-size)] -translate-y-1/2 text-[var(--m3c-secondary-container)] pointer-events-none',
7
- leadingIconPop: 'left-[var(--handle-right)] text-[var(--m3c-primary)]',
8
- trailingIcon: 'absolute top-1/2 right-1 h-[var(--icon-size)] w-[var(--icon-size)] -translate-y-1/2 text-[var(--m3c-primary)] pointer-events-none',
9
- trailingIconPop: 'right-[calc(100%-var(--handle-left))] text-[var(--m3c-secondary-container)]',
10
- trackFill: 'absolute inset-x-0 [inset-block:calc((var(--handle-height)-var(--track-height))/2)] pointer-events-none bg-[var(--m3c-primary)] [clip-path:inset(0_calc(100%-var(--handle-left))_0_0_round_var(--track-radius)_var(--m3-slider-track-in-shape)_var(--m3-slider-track-in-shape)_var(--track-radius))] group-data-[disabled]:bg-[--translucent(var(--m3c-on-surface),0.38)] [@media(forced-colors:active)]:bg-[selecteditem] group-data-[disabled]:[@media(forced-colors:active)]:bg-[canvastext]',
11
- trackRest: 'absolute inset-x-0 [inset-block:calc((var(--handle-height)-var(--track-height))/2)] pointer-events-none bg-[var(--m3c-secondary-container)] [clip-path:inset(0_0_0_var(--handle-right)_round_var(--m3-slider-track-in-shape)_var(--track-radius)_var(--track-radius)_var(--m3-slider-track-in-shape))] group-data-[disabled]:bg-[--translucent(var(--m3c-on-surface),0.12)] [@media(forced-colors:active)]:bg-[canvastext] group-data-[disabled]:[@media(forced-colors:active)]:bg-[graytext]',
12
- stopBase: 'absolute top-1/2 h-1 w-1 rounded-full [inset-inline-start:calc(50%+(100%-0.5rem-0.25rem)*var(--x))] pointer-events-none',
13
- stopFill: 'bg-[var(--m3c-on-primary)] group-data-[disabled]:bg-[var(--m3c-inverse-on-surface)]',
14
- stopRest: 'bg-[var(--m3c-primary)] group-data-[disabled]:bg-[--translucent(var(--m3c-on-surface),0.38)]',
15
- handle: 'absolute inset-y-0 left-[var(--handle-center)] w-1 rounded-[1.25rem] bg-[var(--m3c-primary)] pointer-events-none group-focus-within:outline group-focus-within:outline-[4px] group-focus-within:outline-[var(--m3c-on-secondary-container)] group-focus-within:outline-offset-[5px] group-focus-within:z-[2] group-focus-within:w-0.5 group-active:w-0.5 group-data-[disabled]:bg-[--translucent(var(--m3c-on-surface),0.38)] [@media(forced-colors:active)]:bg-[selecteditem] group-data-[disabled]:[@media(forced-colors:active)]:bg-[graytext]',
16
- value: 'absolute flex min-w-12 items-center justify-center rounded-[var(--m3-slider-handle-shape)] bg-[var(--m3c-inverse-surface)] px-4 py-3 text-[var(--m3c-inverse-on-surface)] md-sys-typescale-label-large [inset-inline-start:var(--handle-center)] [inset-block-end:calc(var(--handle-height)+4px)] opacity-0 pointer-events-none select-none z-[1] group-hover:opacity-100 group-focus-within:opacity-100 group-active:opacity-100 [@media(forced-colors:active)]:border-2 [@media(forced-colors:active)]:border-[selecteditem] [@media(forced-colors:active)]:overflow-hidden'
11
+ root: 'group relative flex shrink-0 cursor-pointer touch-none select-none data-[disabled]:cursor-not-allowed',
12
+ track: 'pointer-events-none absolute',
13
+ activeTrack: 'bg-md-sys-color-primary group-data-[disabled]:bg-md-sys-color-on-surface/38',
14
+ inactiveTrack: 'bg-md-sys-color-secondary-container group-data-[disabled]:bg-md-sys-color-on-surface/12',
15
+ stop: 'pointer-events-none absolute size-1 rounded-full',
16
+ stopOnActive: 'bg-md-sys-color-on-primary group-data-[disabled]:bg-md-sys-color-inverse-on-surface',
17
+ stopOnInactive: 'bg-md-sys-color-on-secondary-container group-data-[disabled]:bg-md-sys-color-on-surface/38',
18
+ icon: 'pointer-events-none absolute',
19
+ iconOnActive: 'text-md-sys-color-on-primary',
20
+ iconOnInactive: 'text-md-sys-color-on-secondary-container',
21
+ handle: `
22
+ absolute rounded-full bg-md-sys-color-primary outline-none
23
+ transition-[width,height] md-sys-motion-fast-spatial
24
+ focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-md-sys-color-secondary
25
+ group-data-[disabled]:bg-md-sys-color-on-surface/38
26
+ `,
27
+ value: `
28
+ pointer-events-none absolute z-10 flex min-w-12 items-center justify-center rounded-full
29
+ bg-md-sys-color-inverse-surface px-4 py-3
30
+ md-sys-typescale-label-large text-md-sys-color-inverse-on-surface
31
+ opacity-0 transition-opacity md-sys-motion-effects
32
+ group-has-[[data-slider-thumb]:focus-visible]:opacity-100
33
+ `
17
34
  },
18
35
  variants: {
19
36
  size: {
20
- xs: '[--track-height:1rem] [--handle-height:2.75rem] [--track-radius:var(--m3-shape-small)] [--icon-size:0]',
21
- s: '[--track-height:1.5rem] [--handle-height:2.75rem] [--track-radius:var(--m3-shape-small)] [--icon-size:0]',
22
- m: '[--track-height:2.5rem] [--handle-height:3.25rem] [--track-radius:var(--m3-shape-medium)] [--icon-size:1.5rem]',
23
- l: '[--track-height:3.5rem] [--handle-height:4.25rem] [--track-radius:var(--m3-shape-large)] [--icon-size:1.5rem]',
24
- xl: '[--track-height:6rem] [--handle-height:6.75rem] [--track-radius:var(--m3-shape-extra-large)] [--icon-size:2rem]'
37
+ xs: { root: '[--track:1rem] [--handle:2.75rem] [--outer:var(--radius-sm)]' },
38
+ s: { root: '[--track:1.5rem] [--handle:2.75rem] [--outer:var(--radius-sm)]' },
39
+ m: { root: '[--track:2.5rem] [--handle:3.25rem] [--outer:var(--radius-md)]' },
40
+ l: { root: '[--track:3.5rem] [--handle:4.25rem] [--outer:var(--radius-lg)]' },
41
+ xl: { root: '[--track:6rem] [--handle:6.75rem] [--outer:var(--radius-xl)]' }
25
42
  },
26
43
  vertical: {
27
- true: '[writing-mode:sideways-lr]'
44
+ false: {
45
+ root: 'h-[var(--handle)] w-full min-w-40',
46
+ track: 'top-1/2 h-[var(--track)] -translate-y-1/2',
47
+ activeTrack: 'left-0 rounded-l-[var(--outer)] rounded-r-[2px]',
48
+ inactiveTrack: 'right-0 rounded-l-[2px] rounded-r-[var(--outer)]',
49
+ stop: 'top-1/2 -translate-x-1/2 -translate-y-1/2',
50
+ icon: 'top-1/2 -translate-y-1/2',
51
+ handle: 'top-0 h-full w-1 -translate-x-1/2 data-[active]:w-0.5',
52
+ value: 'bottom-[calc(100%+4px)] -translate-x-1/2'
53
+ },
54
+ true: {
55
+ root: 'h-full min-h-40 w-[var(--handle)]',
56
+ track: 'left-1/2 w-[var(--track)] -translate-x-1/2',
57
+ activeTrack: 'bottom-0 rounded-t-[2px] rounded-b-[var(--outer)]',
58
+ inactiveTrack: 'top-0 rounded-t-[var(--outer)] rounded-b-[2px]',
59
+ stop: 'left-1/2 -translate-x-1/2 translate-y-1/2',
60
+ icon: 'left-1/2 -translate-x-1/2',
61
+ handle: 'left-0 h-1 w-full translate-y-1/2 data-[active]:h-0.5',
62
+ value: 'left-[calc(100%+4px)] translate-y-1/2'
63
+ }
64
+ },
65
+ active: {
66
+ true: { value: 'opacity-100' }
28
67
  }
29
68
  },
30
69
  defaultVariants: {
31
- size: 'xs'
70
+ size: 'xs',
71
+ vertical: false
32
72
  }
33
73
  });
@@ -4,7 +4,7 @@ import type { SliderVariants } from './theme.js';
4
4
  /**
5
5
  * Props for the Slider component.
6
6
  */
7
- export type SliderProps = SliderVariants & Omit<HTMLAttributes<HTMLSpanElement>, 'size' | 'value'> & {
7
+ export type SliderProps = Omit<SliderVariants, 'active'> & Omit<HTMLAttributes<HTMLSpanElement>, 'size' | 'value'> & {
8
8
  /**
9
9
  * The current value of the slider.
10
10
  */
@@ -14,14 +14,14 @@ export const toggle = tv({
14
14
  'group-data-[disabled]:cursor-not-allowed',
15
15
  'group-data-[disabled]:border-md-sys-color-on-surface/12 group-data-[disabled]:bg-md-sys-color-surface-container-highest',
16
16
  'group-data-[state=checked]:group-data-[disabled]:border-transparent group-data-[state=checked]:group-data-[disabled]:bg-md-sys-color-on-surface/12',
17
- 'transition-colors duration-200'
17
+ 'transition-colors md-sys-motion-effects'
18
18
  ].join(' '),
19
19
  // Thumb — absolute over track
20
20
  handle: [
21
21
  'pointer-events-none absolute left-2 top-1/2 flex h-4 w-4 -translate-y-1/2',
22
22
  'items-center justify-center rounded-full relative',
23
23
  'bg-md-sys-color-outline',
24
- 'transition-[left,transform,background-color] duration-200 ease-in-out',
24
+ 'transition-[left,transform,background-color] md-sys-motion-fast-spatial',
25
25
  // checked: move right + scale up + on-primary color
26
26
  'group-data-[state=checked]:left-[1.75rem] group-data-[state=checked]:scale-[1.5] group-data-[state=checked]:bg-md-sys-color-on-primary',
27
27
  // disabled
@@ -38,7 +38,7 @@ export const toggle = tv({
38
38
  hover: [
39
39
  'pointer-events-none absolute left-4 top-1/2 h-12 w-12',
40
40
  '-translate-x-1/2 -translate-y-1/2 rounded-full',
41
- 'transition-[left,background-color] duration-200',
41
+ 'transition-[left,background-color] md-sys-motion-fast-spatial',
42
42
  'group-data-[state=checked]:left-9',
43
43
  'group-data-[disabled]:hidden',
44
44
  'group-hover:bg-md-sys-color-on-surface/8',
@@ -47,7 +47,7 @@ export const toggle = tv({
47
47
  // Icon inside thumb - shared base (sized via size="xs" prop on Icon, not here)
48
48
  icon: [
49
49
  'absolute inset-0 m-auto pointer-events-none flex items-center justify-center',
50
- 'opacity-0 transition-opacity duration-150 shrink-0'
50
+ 'opacity-0 transition-opacity md-sys-motion-fast-effects shrink-0'
51
51
  ].join(' '),
52
52
  // Specific icon states - colour matches M3 spec for each thumb background
53
53
  iconChecked: [
@@ -34,7 +34,7 @@ Text fields allow users to enter and edit text.
34
34
  ...restProps
35
35
  }: TextfieldProps = $props();
36
36
 
37
- const cls = $derived(textfield({ disabled, error, variant }));
37
+ const cls = $derived(textfield({ disabled, error, variant, leadingIcon: !!leadingIconProps }));
38
38
 
39
39
  const inputProps = $derived({
40
40
  id,
@@ -20,6 +20,9 @@ export declare const textfield: import("tailwind-variants").TVReturnType<{
20
20
  fieldset: string;
21
21
  };
22
22
  };
23
+ leadingIcon: {
24
+ true: {};
25
+ };
23
26
  disabled: {
24
27
  true: {
25
28
  base: string;
@@ -58,6 +61,9 @@ export declare const textfield: import("tailwind-variants").TVReturnType<{
58
61
  fieldset: string;
59
62
  };
60
63
  };
64
+ leadingIcon: {
65
+ true: {};
66
+ };
61
67
  disabled: {
62
68
  true: {
63
69
  base: string;
@@ -96,6 +102,9 @@ export declare const textfield: import("tailwind-variants").TVReturnType<{
96
102
  fieldset: string;
97
103
  };
98
104
  };
105
+ leadingIcon: {
106
+ true: {};
107
+ };
99
108
  disabled: {
100
109
  true: {
101
110
  base: string;
@@ -4,8 +4,10 @@ export const textfield = tv({
4
4
  base: `
5
5
  group relative w-full h-14 flex items-center
6
6
  `,
7
+ /* Stretches to the full field height so the label floats relative to the field's top edge,
8
+ not the input's. */
7
9
  inputWrapper: `
8
- relative flex-1 px-4
10
+ relative flex-1 self-stretch flex items-center px-4
9
11
  `,
10
12
  input: `
11
13
  peer w-full pt-4 bg-transparent outline-none
@@ -17,7 +19,7 @@ export const textfield = tv({
17
19
  md-sys-typescale-body-large
18
20
  text-md-sys-color-on-surface-variant
19
21
  pointer-events-none
20
- transition-[top,font-size,line-height,color,transform] duration-200 ease-in-out
22
+ transition-[top,left,font-size,line-height,color,transform] md-sys-motion-fast-spatial
21
23
 
22
24
  peer-focus:text-md-sys-color-primary
23
25
  `,
@@ -25,7 +27,7 @@ export const textfield = tv({
25
27
  ml-0.5
26
28
  text-md-sys-color-error
27
29
  group-focus-within:text-md-sys-color-primary
28
- transition-colors duration-200
30
+ transition-colors md-sys-motion-effects
29
31
  `,
30
32
  leadingIcon: `
31
33
  text-md-sys-color-on-surface-variant size-6
@@ -43,9 +45,9 @@ export const textfield = tv({
43
45
  text-md-sys-color-on-surface-variant
44
46
  `,
45
47
  fieldset: `
46
- absolute -top-[5px] left-0 right-0 bottom-0 m-0 px-2
48
+ absolute -top-2 left-0 right-0 bottom-0 m-0 px-3
47
49
  pointer-events-none rounded-xs border border-md-sys-color-outline
48
- transition-colors duration-150
50
+ transition-colors md-sys-motion-fast-effects
49
51
 
50
52
  group-hover:border-md-sys-color-on-surface
51
53
  group-focus-within:border-2 group-focus-within:border-md-sys-color-primary
@@ -53,7 +55,7 @@ export const textfield = tv({
53
55
  legend: `
54
56
  invisible float-none block h-auto max-w-[0.01px] overflow-hidden
55
57
  whitespace-nowrap md-sys-typescale-body-small
56
- transition-[max-width] duration-150 ease-in-out
58
+ transition-[max-width] md-sys-motion-fast-spatial
57
59
 
58
60
  group-focus-within:max-w-full
59
61
  group-has-[input:not(:placeholder-shown)]:max-w-full
@@ -69,7 +71,7 @@ export const textfield = tv({
69
71
  px-0 bg-md-sys-color-surface-container-highest
70
72
  rounded-t-xs state-layer before:rounded-xs hover:before:bg-md-sys-color-on-surface/8
71
73
  after:absolute after:bottom-0 after:left-0 after:right-0 after:h-px after:bg-md-sys-color-on-surface-variant
72
- after:transition-[height,background-color] after:duration-200
74
+ after:transition-[height,background-color] after:md-sys-motion-fast-spatial
73
75
  hover:after:bg-md-sys-color-on-surface
74
76
  focus-within:after:bg-md-sys-color-primary
75
77
  focus-within:after:h-[2px]
@@ -77,8 +79,8 @@ export const textfield = tv({
77
79
  disabled:after:bg-md-sys-color-on-surface/12
78
80
  `,
79
81
  label: `
80
- peer-focus:top-1.5 peer-focus:md-sys-typescale-body-small peer-focus:-translate-y-1
81
- peer-not-placeholder-shown:top-1.5 peer-not-placeholder-shown:md-sys-typescale-body-small peer-not-placeholder-shown:-translate-y-1
82
+ peer-focus:top-2 peer-focus:md-sys-typescale-body-small peer-focus:translate-y-0
83
+ peer-not-placeholder-shown:top-2 peer-not-placeholder-shown:md-sys-typescale-body-small peer-not-placeholder-shown:translate-y-0
82
84
  `
83
85
  },
84
86
  outlined: {
@@ -102,6 +104,9 @@ export const textfield = tv({
102
104
  `
103
105
  }
104
106
  },
107
+ leadingIcon: {
108
+ true: {}
109
+ },
105
110
  disabled: {
106
111
  true: {
107
112
  base: 'cursor-not-allowed opacity-60',
@@ -109,6 +114,18 @@ export const textfield = tv({
109
114
  }
110
115
  }
111
116
  },
117
+ compoundVariants: [
118
+ {
119
+ /* M3: an outlined label floats back to the field's start edge, over the leading icon, into
120
+ the notch. The wrapper starts after the icon (ml-3 + size-6 = 36px), so -20px puts the
121
+ label at 16px from the field's edge. */
122
+ variant: 'outlined',
123
+ leadingIcon: true,
124
+ class: {
125
+ label: 'peer-focus:-left-5 peer-not-placeholder-shown:-left-5'
126
+ }
127
+ }
128
+ ],
112
129
  defaultVariants: {
113
130
  variant: 'outlined'
114
131
  }
@@ -13,7 +13,7 @@ export const toggleGroup = tv({
13
13
  });
14
14
  export const toggleGroupItem = tv({
15
15
  slots: {
16
- base: 'layer-container state-layer relative inline-flex min-w-12 flex-1 items-center justify-center gap-2 px-4 md-sys-typescale-label-large text-md-sys-color-on-surface outline-none transition-colors disabled:cursor-not-allowed disabled:opacity-38 [&:not(:last-child)]:border-r [&:not(:last-child)]:border-md-sys-color-outline data-[state=on]:bg-md-sys-color-secondary-container data-[state=on]:text-md-sys-color-on-secondary-container',
16
+ base: 'layer-container state-layer relative inline-flex min-w-12 flex-1 items-center justify-center gap-2 px-4 md-sys-typescale-label-large text-md-sys-color-on-surface outline-none transition-colors md-sys-motion-fast-effects disabled:cursor-not-allowed disabled:opacity-38 [&:not(:last-child)]:border-r [&:not(:last-child)]:border-md-sys-color-outline data-[state=on]:bg-md-sys-color-secondary-container data-[state=on]:text-md-sys-color-on-secondary-container',
17
17
  checkIcon: 'size-[18px] text-[18px]',
18
18
  icon: 'size-[18px] text-[18px]'
19
19
  }
@@ -13,7 +13,7 @@ Plain tooltips are used for simple labels, while rich tooltips can contain forma
13
13
  import { tooltip } from './theme.js';
14
14
  import type { TooltipProps } from './types.js';
15
15
  import { Tooltip } from 'bits-ui';
16
- import { enterExit, easeEmphasizedDecel, easeEmphasizedAccel } from '../../../animation/index.js';
16
+ import { enterExit, presence } from '../../../animation/index.js';
17
17
 
18
18
  let {
19
19
  subhead,
@@ -66,43 +66,32 @@ Plain tooltips are used for simple labels, while rich tooltips can contain forma
66
66
  {/if}
67
67
 
68
68
  {#if hasTooltipContent}
69
- <Tooltip.Content {...contentProps} forceMount>
69
+ <Tooltip.Content {...contentProps}>
70
70
  {#snippet child({ wrapperProps, props, open })}
71
- {#if open}
72
- <div {...wrapperProps} class={wrapperProps.class as any}>
73
- <div
74
- {...props}
75
- class={clsx(baseCls, props.class as any)}
76
- in:enterExit={{
77
- duration: variant === 'rich' ? 200 : 150,
78
- easing: easeEmphasizedDecel,
79
- mode: 'scale'
80
- }}
81
- out:enterExit={{
82
- duration: variant === 'rich' ? 150 : 75,
83
- easing: easeEmphasizedAccel,
84
- mode: 'scale'
85
- }}
86
- >
87
- {#if variant === 'rich'}
88
- <Layer />
89
- {#if subhead}
90
- <Title size="small" class={subheadCls()}>
91
- {subhead}
92
- </Title>
93
- {/if}
94
- <Body class={supportingTextCls()}>
95
- {supportingText}
96
- </Body>
97
- {@render children?.()}
98
- {:else if supportingText}
99
- <Body class={supportingTextCls()}>
100
- {supportingText}
101
- </Body>
71
+ <div {...wrapperProps} class={wrapperProps.class as any}>
72
+ <div
73
+ {...props}
74
+ class={clsx(baseCls, props.class as any)}
75
+ {@attach presence(() => open, enterExit.scale)}
76
+ >
77
+ {#if variant === 'rich'}
78
+ <Layer />
79
+ {#if subhead}
80
+ <Title size="small" class={subheadCls()}>
81
+ {subhead}
82
+ </Title>
102
83
  {/if}
103
- </div>
84
+ <Body class={supportingTextCls()}>
85
+ {supportingText}
86
+ </Body>
87
+ {@render children?.()}
88
+ {:else if supportingText}
89
+ <Body class={supportingTextCls()}>
90
+ {supportingText}
91
+ </Body>
92
+ {/if}
104
93
  </div>
105
- {/if}
94
+ </div>
106
95
  {/snippet}
107
96
  </Tooltip.Content>
108
97
  {/if}
@@ -4,7 +4,7 @@ export const breadcrumb = tv({
4
4
  base: 'flex',
5
5
  list: 'flex flex-wrap items-center gap-1',
6
6
  item: 'flex items-center gap-1',
7
- link: 'md-sys-typescale-label-large text-md-sys-color-on-surface-variant md-sys-state-focus-indicator relative inline-flex min-h-12 items-center rounded-full px-3 transition-colors',
7
+ link: 'md-sys-typescale-label-large text-md-sys-color-on-surface-variant md-sys-state-focus-indicator relative inline-flex min-h-12 items-center rounded-full px-3 transition-colors md-sys-motion-fast-effects',
8
8
  text: 'md-sys-typescale-label-large text-md-sys-color-on-surface-variant px-1 py-0.5',
9
9
  current: 'md-sys-typescale-label-large font-bold px-1 py-0.5',
10
10
  separator: 'text-md-sys-color-on-surface-variant inline-flex shrink-0'
@@ -9,9 +9,9 @@ export const navbar = tv({
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',
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
13
  content: 'flex flex-col items-center justify-center gap-1 w-full',
14
- iconContainer: 'relative flex items-center justify-center h-8 w-16 rounded-full transition-colors duration-200 ease-in-out',
14
+ iconContainer: 'relative flex items-center justify-center h-8 w-16 rounded-full transition-colors md-sys-motion-effects',
15
15
  icon: 'text-[24px] size-6',
16
16
  label: 'md-sys-typescale-label-medium truncate w-full text-center'
17
17
  },
@@ -8,7 +8,7 @@ On mobile (< md) it automatically renders as a bottom navigation bar.
8
8
  @see https://m3.material.io/components/navigation-rail/overview
9
9
  -->
10
10
  <script lang="ts">
11
- import { clickOutside } from '../../../actions/index.js';
11
+ import { clickOutside } from '../../../attachments/index.js';
12
12
  import clsx from 'clsx';
13
13
  import { setContext, untrack } from 'svelte';
14
14
  import type { RailProps } from './types';
@@ -62,9 +62,7 @@ On mobile (< md) it automatically renders as a bottom navigation bar.
62
62
  class={railBaseClass}
63
63
  style={cssVars}
64
64
  data-expanded={expanded}
65
- use:clickOutside={() => {
66
- if (expanded) collapsed = true;
67
- }}
65
+ {@attach expanded && clickOutside(() => (collapsed = true))}
68
66
  >
69
67
  {#if expandable}
70
68
  <ButtonIcon
@@ -91,7 +89,8 @@ On mobile (< md) it automatically renders as a bottom navigation bar.
91
89
  pointer-events: none;
92
90
  background-color: transparent;
93
91
  z-index: -1;
94
- transition: opacity 200ms ease;
92
+ transition: opacity var(--md-sys-motion-duration-effects-spring)
93
+ var(--md-sys-motion-timing-function-effects-spring);
95
94
  }
96
95
 
97
96
  .rail-scrim[data-expanded='true'] {