@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.
Files changed (316) hide show
  1. package/bin/material-claude-skill.js +31 -0
  2. package/claude-skill/material-design/SKILL.md +68 -0
  3. package/claude-skill/material-design/references/accessibility-checklist.md +29 -0
  4. package/claude-skill/material-design/references/component-patterns.md +55 -0
  5. package/claude-skill/material-design/references/motion-guide.md +163 -0
  6. package/claude-skill/material-design/references/tokens-and-styles.md +68 -0
  7. package/dist/animation/Shapes.stories.svelte +60 -0
  8. package/dist/animation/Shapes.stories.svelte.d.ts +3 -0
  9. package/dist/animation/TransitionPatterns.stories.svelte +32 -20
  10. package/dist/animation/containerTransform.d.ts +11 -0
  11. package/dist/animation/containerTransform.js +11 -0
  12. package/dist/animation/enterExit.d.ts +9 -0
  13. package/dist/animation/enterExit.js +6 -3
  14. package/dist/animation/index.d.ts +1 -0
  15. package/dist/animation/index.js +1 -0
  16. package/dist/animation/shapeMorph.svelte.d.ts +52 -0
  17. package/dist/animation/shapeMorph.svelte.js +112 -0
  18. package/dist/animation/shapesAnimatableSmall.d.ts +28 -22
  19. package/dist/animation/shapesAnimatableSmall.js +32 -23
  20. package/dist/animation/sharedAxisTransition.d.ts +22 -0
  21. package/dist/animation/sharedAxisTransition.js +25 -1
  22. package/dist/animation/skeleton.d.ts +6 -1
  23. package/dist/animation/skeleton.js +6 -1
  24. package/dist/components/badge/Badge.mdx +70 -0
  25. package/dist/components/badge/Badge.stories.svelte +38 -20
  26. package/dist/components/badge/Badge.svelte +12 -5
  27. package/dist/components/badge/theme.d.ts +30 -7
  28. package/dist/components/badge/theme.js +24 -4
  29. package/dist/components/badge/types.d.ts +18 -4
  30. package/dist/components/buttons/Button.mdx +85 -0
  31. package/dist/components/buttons/Button.stories.svelte +62 -27
  32. package/dist/components/buttons/Button.svelte +29 -25
  33. package/dist/components/buttons/Button.svelte.d.ts +11 -9
  34. package/dist/components/buttons/ButtonIcon.mdx +52 -0
  35. package/dist/components/buttons/ButtonIcon.stories.svelte +72 -48
  36. package/dist/components/buttons/ButtonIcon.svelte +58 -36
  37. package/dist/components/buttons/ButtonIcon.svelte.d.ts +9 -7
  38. package/dist/components/buttons/FAB.mdx +84 -0
  39. package/dist/components/buttons/FAB.stories.svelte +103 -24
  40. package/dist/components/buttons/FAB.stories.svelte.d.ts +2 -17
  41. package/dist/components/buttons/FAB.svelte +353 -29
  42. package/dist/components/buttons/FAB.svelte.d.ts +11 -6
  43. package/dist/components/buttons/FABMenu.svelte +27 -8
  44. package/dist/components/buttons/FABMenu.svelte.d.ts +7 -3
  45. package/dist/components/buttons/FABMenuItem.svelte +20 -16
  46. package/dist/components/buttons/FABMenuItem.svelte.d.ts +3 -3
  47. package/dist/components/buttons/Toggle.stories.svelte +31 -23
  48. package/dist/components/buttons/Toggle.stories.svelte.d.ts +2 -17
  49. package/dist/components/buttons/Toggle.svelte +28 -25
  50. package/dist/components/buttons/Toggle.svelte.d.ts +5 -5
  51. package/dist/components/buttons/button-group/ButtonGroup.mdx +39 -0
  52. package/dist/components/buttons/button-group/ButtonGroup.stories.svelte +62 -43
  53. package/dist/components/buttons/button-group/ButtonGroup.stories.svelte.d.ts +2 -17
  54. package/dist/components/buttons/button-group/ButtonGroup.svelte +102 -8
  55. package/dist/components/buttons/button-group/ButtonGroup.svelte.d.ts +6 -7
  56. package/dist/components/buttons/button-group/theme.d.ts +45 -15
  57. package/dist/components/buttons/button-group/theme.js +13 -8
  58. package/dist/components/buttons/button-group/types.d.ts +13 -7
  59. package/dist/components/buttons/connected/ConnectedButtonGroup.mdx +43 -0
  60. package/dist/components/buttons/connected/ConnectedButtonGroup.stories.svelte +56 -74
  61. package/dist/components/buttons/connected/ConnectedButtonGroup.stories.svelte.d.ts +2 -17
  62. package/dist/components/buttons/connected/ConnectedButtonGroup.svelte +16 -4
  63. package/dist/components/buttons/connected/ConnectedButtonGroup.svelte.d.ts +4 -4
  64. package/dist/components/buttons/connected/ConnectedButtonGroupItem.svelte +35 -8
  65. package/dist/components/buttons/connected/ConnectedButtonGroupItem.svelte.d.ts +2 -3
  66. package/dist/components/buttons/connected/theme.d.ts +33 -18
  67. package/dist/components/buttons/connected/theme.js +32 -9
  68. package/dist/components/buttons/connected/types.d.ts +36 -9
  69. package/dist/components/buttons/shapeMorph.d.ts +26 -0
  70. package/dist/components/buttons/shapeMorph.js +142 -0
  71. package/dist/components/buttons/split-button/SplitButton.mdx +48 -0
  72. package/dist/components/buttons/split-button/SplitButton.stories.svelte +9 -14
  73. package/dist/components/buttons/split-button/SplitButton.svelte +65 -48
  74. package/dist/components/buttons/split-button/SplitButton.svelte.d.ts +6 -11
  75. package/dist/components/buttons/split-button/theme.d.ts +110 -17
  76. package/dist/components/buttons/split-button/theme.js +74 -16
  77. package/dist/components/buttons/split-button/types.d.ts +24 -18
  78. package/dist/components/buttons/theme.d.ts +422 -230
  79. package/dist/components/buttons/theme.js +286 -380
  80. package/dist/components/buttons/types.d.ts +130 -125
  81. package/dist/components/cards/Card.mdx +44 -0
  82. package/dist/components/cards/Card.stories.svelte +11 -11
  83. package/dist/components/cards/theme.js +5 -5
  84. package/dist/components/chips/Chip.mdx +68 -0
  85. package/dist/components/chips/Chip.stories.svelte +4 -4
  86. package/dist/components/chips/theme.js +3 -3
  87. package/dist/components/containers/action-rail/ActionRail.stories.svelte +1 -0
  88. package/dist/components/containers/action-rail/theme.js +1 -1
  89. package/dist/components/containers/bottom-sheet/BottomSheet.mdx +64 -0
  90. package/dist/components/containers/bottom-sheet/BottomSheet.stories.svelte +108 -12
  91. package/dist/components/containers/bottom-sheet/BottomSheet.svelte +179 -109
  92. package/dist/components/containers/bottom-sheet/BottomSheet.svelte.d.ts +10 -5
  93. package/dist/components/containers/bottom-sheet/index.d.ts +1 -0
  94. package/dist/components/containers/bottom-sheet/index.js +1 -0
  95. package/dist/components/containers/bottom-sheet/theme.d.ts +45 -0
  96. package/dist/components/containers/bottom-sheet/theme.js +42 -0
  97. package/dist/components/containers/bottom-sheet/types.d.ts +37 -5
  98. package/dist/components/containers/carousel/Carousel.mdx +80 -0
  99. package/dist/components/containers/carousel/Carousel.stories.svelte +131 -0
  100. package/dist/components/containers/carousel/Carousel.stories.svelte.d.ts +4 -0
  101. package/dist/components/containers/carousel/Carousel.svelte +194 -0
  102. package/dist/components/containers/carousel/Carousel.svelte.d.ts +25 -0
  103. package/dist/components/containers/carousel/index.d.ts +3 -0
  104. package/dist/components/containers/{stack → carousel}/index.js +1 -2
  105. package/dist/components/containers/carousel/keylines.d.ts +32 -0
  106. package/dist/components/containers/carousel/keylines.js +88 -0
  107. package/dist/components/containers/carousel/theme.d.ts +162 -0
  108. package/dist/components/containers/carousel/theme.js +67 -0
  109. package/dist/components/containers/carousel/types.d.ts +52 -0
  110. package/dist/components/containers/context-menu/ContextMenu.stories.svelte +1 -0
  111. package/dist/components/containers/context-menu/ContextMenu.svelte +2 -2
  112. package/dist/components/containers/context-menu/ContextMenu.svelte.d.ts +1 -1
  113. package/dist/components/containers/context-menu/theme.js +10 -10
  114. package/dist/components/containers/dialogue/Dialogue.mdx +65 -0
  115. package/dist/components/containers/dialogue/Dialogue.stories.svelte +4 -4
  116. package/dist/components/containers/dialogue/Dialogue.svelte +1 -1
  117. package/dist/components/containers/dialogue/theme.js +3 -3
  118. package/dist/components/containers/divider/Divider.stories.svelte +2 -1
  119. package/dist/components/containers/divider/Divider.svelte +2 -2
  120. package/dist/components/containers/divider/theme.d.ts +6 -6
  121. package/dist/components/containers/divider/theme.js +2 -2
  122. package/dist/components/containers/index.d.ts +1 -1
  123. package/dist/components/containers/index.js +1 -1
  124. package/dist/components/containers/link-preview/theme.js +2 -2
  125. package/dist/components/containers/list/List.svelte +18 -0
  126. package/dist/components/containers/list/List.svelte.d.ts +4 -0
  127. package/dist/components/containers/list/ListItem.mdx +100 -0
  128. package/dist/components/containers/list/ListItem.stories.svelte +177 -42
  129. package/dist/components/containers/list/ListItem.stories.svelte.d.ts +2 -17
  130. package/dist/components/containers/list/ListItem.svelte +92 -37
  131. package/dist/components/containers/list/ListItem.svelte.d.ts +1 -1
  132. package/dist/components/containers/list/context.d.ts +6 -0
  133. package/dist/components/containers/list/context.js +4 -0
  134. package/dist/components/containers/list/index.d.ts +1 -0
  135. package/dist/components/containers/list/index.js +1 -0
  136. package/dist/components/containers/list/theme.d.ts +487 -12
  137. package/dist/components/containers/list/theme.js +140 -13
  138. package/dist/components/containers/list/types.d.ts +39 -5
  139. package/dist/components/containers/menu/Menu.mdx +52 -0
  140. package/dist/components/containers/menu/Menu.stories.svelte +14 -14
  141. package/dist/components/containers/menu/Menu.svelte +1 -1
  142. package/dist/components/containers/menu/MenuGroup.svelte +1 -1
  143. package/dist/components/containers/menu/MenuGroup.svelte.d.ts +1 -1
  144. package/dist/components/containers/menu/menu-item/MenuItem.svelte +1 -1
  145. package/dist/components/containers/menu/theme.js +8 -8
  146. package/dist/components/containers/pane/DraggablePane.stories.svelte +4 -3
  147. package/dist/components/containers/pane/DraggablePane.svelte +2 -2
  148. package/dist/components/containers/pane/Pane.stories.svelte +11 -10
  149. package/dist/components/containers/pane/Pane.svelte +24 -2
  150. package/dist/components/containers/pane/PaneGrid.stories.svelte +19 -18
  151. package/dist/components/containers/pane/PaneGrid.svelte +3 -2
  152. package/dist/components/containers/pane/PaneGrid.svelte.d.ts +2 -1
  153. package/dist/components/containers/pane/PaneHandle.svelte +48 -2
  154. package/dist/components/containers/pane/PaneHandle.svelte.d.ts +4 -0
  155. package/dist/components/containers/pane/resizeStore.svelte.d.ts +10 -1
  156. package/dist/components/containers/pane/resizeStore.svelte.js +13 -2
  157. package/dist/components/containers/pane/theme.js +129 -45
  158. package/dist/components/containers/pane/types.d.ts +3 -2
  159. package/dist/components/containers/popover/Popover.mdx +45 -0
  160. package/dist/components/containers/popover/Popover.stories.svelte +1 -1
  161. package/dist/components/containers/popover/Popover.svelte +1 -1
  162. package/dist/components/containers/popover/theme.js +3 -3
  163. package/dist/components/containers/scroll-area/theme.js +2 -2
  164. package/dist/components/containers/side-sheet/SideSheet.mdx +71 -0
  165. package/dist/components/containers/side-sheet/SideSheet.stories.svelte +113 -17
  166. package/dist/components/containers/side-sheet/SideSheet.svelte +113 -66
  167. package/dist/components/containers/side-sheet/SideSheet.svelte.d.ts +8 -7
  168. package/dist/components/containers/side-sheet/index.d.ts +1 -0
  169. package/dist/components/containers/side-sheet/index.js +1 -0
  170. package/dist/components/containers/side-sheet/theme.d.ts +108 -0
  171. package/dist/components/containers/side-sheet/theme.js +72 -0
  172. package/dist/components/containers/side-sheet/types.d.ts +35 -7
  173. package/dist/components/date/DateField.stories.svelte +4 -3
  174. package/dist/components/date/DateField.svelte +49 -26
  175. package/dist/components/date/DateField.svelte.d.ts +2 -0
  176. package/dist/components/date/DateRangeField.stories.svelte +4 -3
  177. package/dist/components/date/DateRangeField.svelte +54 -31
  178. package/dist/components/date/DateRangeField.svelte.d.ts +2 -0
  179. package/dist/components/date/calendarMotion.d.ts +9 -0
  180. package/dist/components/date/calendarMotion.js +23 -0
  181. package/dist/components/date/theme.d.ts +7 -7
  182. package/dist/components/date/theme.js +34 -30
  183. package/dist/components/forms/checkbox/Checkbox.mdx +35 -0
  184. package/dist/components/forms/checkbox/Checkbox.stories.svelte +2 -2
  185. package/dist/components/forms/checkbox/Checkbox.svelte +1 -1
  186. package/dist/components/forms/checkbox/theme.js +3 -3
  187. package/dist/components/forms/command/Command.stories.svelte +1 -0
  188. package/dist/components/forms/command/theme.js +9 -9
  189. package/dist/components/forms/pin/theme.js +4 -4
  190. package/dist/components/forms/radio-group/RadioGroup.svelte +1 -1
  191. package/dist/components/forms/radio-group/theme.js +5 -5
  192. package/dist/components/forms/search/Search.mdx +38 -0
  193. package/dist/components/forms/search/Search.stories.svelte +19 -9
  194. package/dist/components/forms/search/Search.svelte +40 -17
  195. package/dist/components/forms/search/Search.svelte.d.ts +2 -2
  196. package/dist/components/forms/search/theme.d.ts +45 -12
  197. package/dist/components/forms/search/theme.js +13 -8
  198. package/dist/components/forms/search/types.d.ts +18 -12
  199. package/dist/components/forms/select/Select.mdx +53 -0
  200. package/dist/components/forms/select/Select.stories.svelte +4 -4
  201. package/dist/components/forms/select/Select.svelte +10 -2
  202. package/dist/components/forms/select/SelectItem.svelte +1 -1
  203. package/dist/components/forms/select/theme.js +12 -12
  204. package/dist/components/forms/slider/Slider.mdx +85 -0
  205. package/dist/components/forms/slider/Slider.stories.svelte +7 -7
  206. package/dist/components/forms/slider/Slider.svelte +46 -28
  207. package/dist/components/forms/slider/theme.d.ts +14 -0
  208. package/dist/components/forms/slider/theme.js +28 -17
  209. package/dist/components/forms/slider/types.d.ts +3 -2
  210. package/dist/components/forms/switch/Switch.mdx +38 -0
  211. package/dist/components/forms/switch/Switch.stories.svelte +3 -3
  212. package/dist/components/forms/switch/theme.js +6 -6
  213. package/dist/components/forms/textfield/Textfield.mdx +53 -0
  214. package/dist/components/forms/textfield/Textfield.stories.svelte +6 -6
  215. package/dist/components/forms/textfield/Textfield.svelte +1 -0
  216. package/dist/components/forms/textfield/theme.d.ts +3 -0
  217. package/dist/components/forms/textfield/theme.js +22 -19
  218. package/dist/components/forms/toggle-group/theme.js +2 -2
  219. package/dist/components/forms/tooltip/Tooltip.stories.svelte +1 -0
  220. package/dist/components/forms/tooltip/theme.js +3 -3
  221. package/dist/components/misc/Avatar.stories.svelte +5 -4
  222. package/dist/components/misc/ThemeSettings.svelte +9 -9
  223. package/dist/components/misc/ThemeSwitcher.svelte +3 -3
  224. package/dist/components/misc/theme.js +4 -4
  225. package/dist/components/nav/appbar/AppBar.mdx +71 -0
  226. package/dist/components/nav/appbar/AppBar.stories.svelte +93 -3
  227. package/dist/components/nav/appbar/AppBar.stories.svelte.d.ts +2 -17
  228. package/dist/components/nav/appbar/AppBar.svelte +90 -37
  229. package/dist/components/nav/appbar/AppBar.svelte.d.ts +9 -2
  230. package/dist/components/nav/appbar/theme.d.ts +85 -18
  231. package/dist/components/nav/appbar/theme.js +159 -23
  232. package/dist/components/nav/appbar/types.d.ts +46 -9
  233. package/dist/components/nav/breadcrumb/Breadcrumb.stories.svelte +1 -0
  234. package/dist/components/nav/breadcrumb/theme.js +5 -5
  235. package/dist/components/nav/navbar/Navbar.mdx +38 -0
  236. package/dist/components/nav/navbar/Navbar.svelte +1 -1
  237. package/dist/components/nav/navbar/NavbarItem.svelte +12 -9
  238. package/dist/components/nav/navbar/theme.js +6 -6
  239. package/dist/components/nav/rail/Rail.mdx +73 -0
  240. package/dist/components/nav/rail/Rail.stories.svelte +3 -7
  241. package/dist/components/nav/rail/Rail.svelte +1 -0
  242. package/dist/components/nav/rail/RailItem.svelte +12 -9
  243. package/dist/components/nav/rail/theme.js +13 -13
  244. package/dist/components/nav/rail/types.d.ts +4 -1
  245. package/dist/components/nav/tabs/TabHolder.svelte +29 -3
  246. package/dist/components/nav/tabs/TabHolder.svelte.d.ts +3 -1
  247. package/dist/components/nav/tabs/Tabs.mdx +62 -0
  248. package/dist/components/nav/tabs/Tabs.stories.svelte +1 -1
  249. package/dist/components/nav/tabs/theme.js +4 -4
  250. package/dist/components/pill/Pill.mdx +32 -0
  251. package/dist/components/pill/Pill.stories.svelte +1 -1
  252. package/dist/components/pill/theme.d.ts +1 -1
  253. package/dist/components/pill/theme.js +1 -1
  254. package/dist/components/progress/LinearProgress.svelte +1 -1
  255. package/dist/components/progress/Progress.mdx +50 -0
  256. package/dist/components/progress/Progress.stories.svelte +6 -6
  257. package/dist/components/snackbar/Snackbar.mdx +52 -0
  258. package/dist/components/snackbar/Snackbar.stories.svelte +5 -5
  259. package/dist/components/snackbar/Snackbar.svelte +1 -1
  260. package/dist/components/snackbar/theme.d.ts +3 -3
  261. package/dist/components/snackbar/theme.js +4 -4
  262. package/dist/components/table/Table.stories.svelte +1 -0
  263. package/dist/components/table/TableHeader.svelte +1 -1
  264. package/dist/components/table/theme.js +3 -3
  265. package/dist/components/time/TimeField.stories.svelte +3 -2
  266. package/dist/components/time/TimeField.svelte +14 -8
  267. package/dist/components/time/TimeField.svelte.d.ts +6 -0
  268. package/dist/components/time/TimepickerInput.svelte +9 -5
  269. package/dist/components/time/theme.js +5 -5
  270. package/dist/components/time/types.d.ts +11 -1
  271. package/dist/components/toolbar/Toolbar.stories.svelte +1 -0
  272. package/dist/components/toolbar/Toolbar.svelte +1 -1
  273. package/dist/components/toolbar/Toolbar.svelte.d.ts +1 -1
  274. package/dist/components/toolbar/theme.js +14 -14
  275. package/dist/components/typography/Typography.mdx +67 -0
  276. package/dist/components/typography/body/Body.stories.svelte +2 -1
  277. package/dist/components/typography/body/theme.d.ts +15 -12
  278. package/dist/components/typography/body/theme.js +19 -4
  279. package/dist/components/typography/body/types.d.ts +2 -1
  280. package/dist/components/typography/display/Display.stories.svelte +2 -1
  281. package/dist/components/typography/display/theme.d.ts +15 -12
  282. package/dist/components/typography/display/theme.js +19 -4
  283. package/dist/components/typography/display/types.d.ts +2 -1
  284. package/dist/components/typography/headline/Headline.stories.svelte +2 -1
  285. package/dist/components/typography/headline/theme.d.ts +15 -12
  286. package/dist/components/typography/headline/theme.js +19 -4
  287. package/dist/components/typography/headline/types.d.ts +2 -1
  288. package/dist/components/typography/kbd/Kbd.stories.svelte +2 -1
  289. package/dist/components/typography/kbd/theme.d.ts +4 -4
  290. package/dist/components/typography/kbd/theme.js +2 -2
  291. package/dist/components/typography/label/Label.stories.svelte +2 -1
  292. package/dist/components/typography/label/theme.d.ts +15 -12
  293. package/dist/components/typography/label/theme.js +19 -4
  294. package/dist/components/typography/label/types.d.ts +2 -1
  295. package/dist/components/typography/title/Title.stories.svelte +2 -1
  296. package/dist/components/typography/title/theme.d.ts +15 -12
  297. package/dist/components/typography/title/theme.js +19 -4
  298. package/dist/components/typography/title/types.d.ts +2 -1
  299. package/dist/index.css +1 -0
  300. package/dist/styles/component.css +78 -175
  301. package/dist/styles/elevation.css +9 -0
  302. package/dist/styles/spacing.css +29 -0
  303. package/dist/styles/typescale.css +635 -20
  304. package/dist/utils/Layer.svelte +1 -1
  305. package/dist/utils/icon/Icon.svelte +8 -6
  306. package/dist/utils/icon/loadingShapes.js +11 -10
  307. package/package.json +19 -15
  308. package/dist/components/containers/stack/HStack.svelte +0 -23
  309. package/dist/components/containers/stack/HStack.svelte.d.ts +0 -5
  310. package/dist/components/containers/stack/VStack.svelte +0 -23
  311. package/dist/components/containers/stack/VStack.svelte.d.ts +0 -5
  312. package/dist/components/containers/stack/index.d.ts +0 -4
  313. package/dist/components/containers/stack/theme.d.ts +0 -66
  314. package/dist/components/containers/stack/theme.js +0 -26
  315. package/dist/components/containers/stack/types.d.ts +0 -12
  316. /package/dist/components/containers/{stack → carousel}/types.js +0 -0
@@ -1,6 +1,8 @@
1
1
  <!--
2
2
  The six M3 transition patterns, each on its own M3 shape, driven by `src/lib/animation/`.
3
3
  https://m3.material.io/styles/motion/transitions/transition-patterns
4
+ Choosing and applying them: https://m3.material.io/styles/motion/transitions/applying-transitions
5
+ (summarized in .claude/skills/material-design/references/motion-guide.md → "Applying transitions").
4
6
 
5
7
  Every demo loops by default; "Replay" retriggers it on demand. The Overview plays the six in
6
8
  turn rather than all at once: container transform, forward/backward, lateral and top level run
@@ -201,27 +203,30 @@
201
203
  <button
202
204
  type="button"
203
205
  data-demo="ct-card"
204
- class="bg-md-sys-color-primary-container text-md-sys-color-on-primary-container absolute top-4 left-4 flex items-center gap-3 rounded-lg p-3"
206
+ class="bg-md-sys-color-primary-container text-md-sys-color-on-primary-container top-spacing-200 left-spacing-200 gap-spacing-150 p-spacing-150 absolute flex items-center rounded-lg"
205
207
  onclick={runContainer}
206
208
  >
207
- {@render shape(pathFourSidedCookie, 'size-10 text-md-sys-color-primary')}
209
+ {@render shape(pathFourSidedCookie, 'size-spacing-500 text-md-sys-color-primary')}
208
210
  <span class="md-sys-typescale-label-large">Open</span>
209
211
  </button>
210
212
  {:else}
211
213
  <div
212
214
  data-demo="ct-detail"
213
- class="bg-md-sys-color-surface-container-highest text-md-sys-color-on-surface absolute inset-3 flex flex-col items-center justify-center gap-3 rounded-xl"
215
+ class="bg-md-sys-color-surface-container-highest text-md-sys-color-on-surface inset-spacing-150 gap-spacing-150 absolute flex flex-col items-center justify-center rounded-xl"
214
216
  >
215
217
  {@render shape(pathFourSidedCookie, 'size-24 text-md-sys-color-primary')}
216
218
  <span class="md-sys-typescale-title-medium">Detail</span>
217
219
  </div>
218
220
  {/if}
219
221
  {:else if pattern.id === 'axis'}
220
- <div data-demo="axis" class="absolute inset-0 flex flex-col items-center justify-center gap-3">
222
+ <div
223
+ data-demo="axis"
224
+ class="inset-spacing-0 gap-spacing-150 absolute flex flex-col items-center justify-center"
225
+ >
221
226
  {@render shape(
222
227
  pathPentagon,
223
228
  [
224
- 'size-16 text-md-sys-color-primary',
229
+ 'size-spacing-800 text-md-sys-color-primary',
225
230
  'size-20 text-md-sys-color-secondary',
226
231
  'size-24 text-md-sys-color-tertiary'
227
232
  ][level]
@@ -231,7 +236,9 @@
231
236
  </span>
232
237
  </div>
233
238
  {:else if pattern.id === 'lateral'}
234
- <div class="absolute inset-x-0 top-0 flex justify-center gap-6 pt-3">
239
+ <div
240
+ class="inset-x-spacing-0 top-spacing-0 gap-spacing-300 pt-spacing-150 absolute flex justify-center"
241
+ >
235
242
  {#each tabs as name, i (name)}
236
243
  <span
237
244
  class={[
@@ -243,7 +250,7 @@
243
250
  </div>
244
251
  <div
245
252
  data-demo="lateral"
246
- class="bg-md-sys-color-surface-container absolute inset-x-3 top-11 bottom-3 flex items-center justify-center rounded-lg"
253
+ class="bg-md-sys-color-surface-container inset-x-spacing-150 bottom-spacing-150 absolute top-11 flex items-center justify-center rounded-lg"
247
254
  >
248
255
  {@render shape(pathFourLeafClover, 'size-24 text-md-sys-color-primary')}
249
256
  <span
@@ -255,7 +262,7 @@
255
262
  <div
256
263
  data-demo="top"
257
264
  class={[
258
- 'absolute inset-3 flex flex-col items-center justify-center gap-3 rounded-lg',
265
+ 'inset-spacing-150 gap-spacing-150 absolute flex flex-col items-center justify-center rounded-lg',
259
266
  destinations[destination].color
260
267
  ]}
261
268
  >
@@ -265,23 +272,25 @@
265
272
  {:else if pattern.id === 'enter-exit'}
266
273
  {#if pop.mounted}
267
274
  <div
268
- class="bg-md-sys-color-surface-container-high shadow-elevation-3 absolute inset-x-8 inset-y-6 flex items-center justify-center rounded-xl"
275
+ class="bg-md-sys-color-surface-container-high shadow-elevation-3 inset-x-spacing-400 inset-y-spacing-300 absolute flex items-center justify-center rounded-xl"
269
276
  {@attach pop.attach(enterExit.scale)}
270
277
  >
271
278
  {@render shape(pathSoftBurst, 'size-24 text-md-sys-color-tertiary')}
272
279
  </div>
273
280
  {/if}
274
281
  {:else if pattern.id === 'skeleton'}
275
- <div class="absolute inset-3 grid [&>*]:[grid-area:1/1]">
282
+ <div class="inset-spacing-150 absolute grid [&>*]:[grid-area:1/1]">
276
283
  {#if !loaded}
277
- <div class="flex flex-col items-center justify-center gap-3" {@attach skeleton}>
284
+ <div class="gap-spacing-150 flex flex-col items-center justify-center" {@attach skeleton}>
278
285
  <div class="bg-md-sys-color-surface-container-highest size-24 rounded-full"></div>
279
- <div class="bg-md-sys-color-surface-container-highest h-4 w-28 rounded-full"></div>
286
+ <div
287
+ class="bg-md-sys-color-surface-container-highest h-spacing-200 w-28 rounded-full"
288
+ ></div>
280
289
  </div>
281
290
  {/if}
282
291
  {#if content.mounted}
283
292
  <div
284
- class="flex flex-col items-center justify-center gap-3"
293
+ class="gap-spacing-150 flex flex-col items-center justify-center"
285
294
  {@attach content.attach(enterExit.fade)}
286
295
  >
287
296
  {@render shape(pathGem, 'size-24 text-md-sys-color-secondary')}
@@ -294,10 +303,10 @@
294
303
 
295
304
  {#snippet demo(pattern: Pattern, tall = false)}
296
305
  <section
297
- class="bg-md-sys-color-surface-container-low text-md-sys-color-on-surface flex flex-col gap-3 rounded-xl p-4"
306
+ class="bg-md-sys-color-surface-container-low text-md-sys-color-on-surface gap-spacing-150 p-spacing-200 flex flex-col rounded-xl"
298
307
  >
299
- <header class="flex items-start justify-between gap-3">
300
- <div class="flex flex-col gap-1">
308
+ <header class="gap-spacing-150 flex items-start justify-between">
309
+ <div class="gap-spacing-50 flex flex-col">
301
310
  <Title size="medium">{pattern.title}</Title>
302
311
  <Body size="small" class="text-md-sys-color-on-surface-variant">{pattern.summary}</Body>
303
312
  </div>
@@ -318,7 +327,7 @@
318
327
  {/snippet}
319
328
 
320
329
  {#snippet toolbar()}
321
- <div class="flex items-center justify-between gap-4">
330
+ <div class="gap-spacing-200 flex items-center justify-between">
322
331
  <Title size="large">M3 transition patterns</Title>
323
332
  <Button variant={looping ? 'filled' : 'outlined'} onclick={() => (looping = !looping)}>
324
333
  {looping ? 'Pause loop' : 'Loop'}
@@ -327,9 +336,12 @@
327
336
  {/snippet}
328
337
 
329
338
  <Story name="Overview" asChild>
330
- <div class="bg-md-sys-color-surface flex min-h-dvh flex-col gap-6 p-6" {@attach roundRobin}>
339
+ <div
340
+ class="bg-md-sys-color-surface gap-spacing-300 p-spacing-300 flex min-h-dvh flex-col"
341
+ {@attach roundRobin}
342
+ >
331
343
  {@render toolbar()}
332
- <div class="grid gap-4 md:grid-cols-2 xl:grid-cols-3">
344
+ <div class="gap-spacing-200 grid md:grid-cols-2 xl:grid-cols-3">
333
345
  {#each all as pattern (pattern.id)}
334
346
  {@render demo(pattern)}
335
347
  {/each}
@@ -339,7 +351,7 @@
339
351
 
340
352
  {#snippet single(pattern: Pattern)}
341
353
  <div
342
- class="bg-md-sys-color-surface flex min-h-dvh flex-col gap-6 p-6"
354
+ class="bg-md-sys-color-surface gap-spacing-300 p-spacing-300 flex min-h-dvh flex-col"
343
355
  {@attach loop(pattern.run)}
344
356
  >
345
357
  {@render toolbar()}
@@ -13,10 +13,21 @@ export interface ContainerTransformOptions {
13
13
  * the outgoing content fades out and the incoming content fades in on top.
14
14
  * https://m3.material.io/styles/motion/transitions/transition-patterns#container-transform
15
15
  *
16
+ * The most dramatic pattern (https://m3.material.io/styles/motion/transitions/applying-transitions).
17
+ * Use it for hero moments, shallow expand → collapse hierarchies and seamless element-to-element
18
+ * connections. Don't use it in deep hierarchies or utility-focused navigation, where it becomes
19
+ * excessive. Use `sharedAxis` there. Keep `spring` at `spatial`/`slowSpatial`, never the bouncy
20
+ * `fastSpatial`.
21
+ *
16
22
  * Built on Motion's `animateView()` (View Transition API), so `from` and `to` never have to be in
17
23
  * the DOM at the same time — `update` swaps one for the other. Browsers without the API just run
18
24
  * `update`. A second call while one is running is queued, not interrupted.
19
25
  *
26
+ * Not built into any component. FAB → sheet is the FAB's own morph (a clip-path on Motion, in
27
+ * `FAB.svelte`), because M3 keeps that container opaque and changes its colour, which a
28
+ * snapshot cross-fade can't. Card → detail is the app's own navigation, and `Search` is a plain
29
+ * field with no search view to expand into.
30
+ *
20
31
  * ```ts
21
32
  * containerTransform(
22
33
  * async () => { expanded = true; await tick(); },
@@ -5,10 +5,21 @@ import { springTokens, springTransition } from './spring.js';
5
5
  * the outgoing content fades out and the incoming content fades in on top.
6
6
  * https://m3.material.io/styles/motion/transitions/transition-patterns#container-transform
7
7
  *
8
+ * The most dramatic pattern (https://m3.material.io/styles/motion/transitions/applying-transitions).
9
+ * Use it for hero moments, shallow expand → collapse hierarchies and seamless element-to-element
10
+ * connections. Don't use it in deep hierarchies or utility-focused navigation, where it becomes
11
+ * excessive. Use `sharedAxis` there. Keep `spring` at `spatial`/`slowSpatial`, never the bouncy
12
+ * `fastSpatial`.
13
+ *
8
14
  * Built on Motion's `animateView()` (View Transition API), so `from` and `to` never have to be in
9
15
  * the DOM at the same time — `update` swaps one for the other. Browsers without the API just run
10
16
  * `update`. A second call while one is running is queued, not interrupted.
11
17
  *
18
+ * Not built into any component. FAB → sheet is the FAB's own morph (a clip-path on Motion, in
19
+ * `FAB.svelte`), because M3 keeps that container opaque and changes its colour, which a
20
+ * snapshot cross-fade can't. Card → detail is the app's own navigation, and `Search` is a plain
21
+ * field with no search view to expand into.
22
+ *
12
23
  * ```ts
13
24
  * containerTransform(
14
25
  * async () => { expanded = true; await tick(); },
@@ -5,6 +5,15 @@ import type { AnimationOptions, DOMKeyframesDefinition } from 'motion';
5
5
  * layer detects to delay unmounting.
6
6
  *
7
7
  * https://m3.material.io/styles/motion/transitions/transition-patterns#enter-and-exit
8
+ *
9
+ * Introduces a component in the context of the current screen, modal or not
10
+ * (https://m3.material.io/styles/motion/transitions/applying-transitions). Never use it to navigate between hierarchical screens.
11
+ * Clean fades: opacity always runs on `fastEffects` so it never lingers over the content behind.
12
+ * Edge-anchored sheets slide without fading, as M3 asks.
13
+ *
14
+ * Required for every component that mounts a surface within the current screen: dialogs, sheets,
15
+ * menus, popovers, tooltips, pickers, snackbars, the FAB menu. See the ownership table in
16
+ * `.claude/skills/material-design/references/motion-guide.md`.
8
17
  */
9
18
  export interface PresenceTransition {
10
19
  /** Where the enter animation starts. */
@@ -53,14 +53,17 @@ export const enterExit = {
53
53
  enter: enterWith(springTokens.spatial),
54
54
  exit
55
55
  },
56
- /** Side sheet anchored to the inline-end edge. */
56
+ /**
57
+ * Side sheet anchored to the inline-end edge. Slides only: no opacity (M3: don't fade sheets).
58
+ * The extra 1rem clears a detached sheet's 16dp margin, so no sliver is left at the edge.
59
+ */
57
60
  sideSheet: {
58
- hidden: { transform: 'translateX(100%)' },
61
+ hidden: { transform: 'translateX(calc(100% + 1rem))' },
59
62
  shown: { transform: 'translateX(0%)' },
60
63
  enter: springTransition(springTokens.spatial),
61
64
  exit: springTransition(springTokens.effects)
62
65
  },
63
- /** Bottom sheet anchored to the bottom edge. */
66
+ /** Bottom sheet anchored to the bottom edge. Slides only: no opacity (M3: don't fade sheets). */
64
67
  bottomSheet: {
65
68
  hidden: { transform: 'translateY(100%)' },
66
69
  shown: { transform: 'translateY(0%)' },
@@ -1,3 +1,4 @@
1
+ export * from './shapeMorph.svelte.js';
1
2
  export * from './shapes.js';
2
3
  export * from './shapesAnimatable.js';
3
4
  export * from './shapesAnimatableSmall.js';
@@ -1,3 +1,4 @@
1
+ export * from './shapeMorph.svelte.js';
1
2
  export * from './shapes.js';
2
3
  export * from './shapesAnimatable.js';
3
4
  export * from './shapesAnimatableSmall.js';
@@ -0,0 +1,52 @@
1
+ import { type AnimationPlaybackControls } from 'motion';
2
+ import type { Attachment } from 'svelte/attachments';
3
+ import { type SpringToken } from './spring.js';
4
+ /**
5
+ * The 35 shapes of the M3 Expressive shape library, in the order of the spec sheet.
6
+ * https://m3.material.io/styles/shape
7
+ */
8
+ export declare const shapeNames: readonly ["circle", "square", "slanted", "arch", "semicircle", "oval", "pill", "triangle", "arrow", "fan", "diamond", "clamshell", "pentagon", "gem", "verySunny", "sunny", "fourSidedCookie", "sixSidedCookie", "sevenSidedCookie", "nineSidedCookie", "twelveSidedCookie", "fourLeafClover", "eightLeafClover", "burst", "softBurst", "boom", "softBoom", "flower", "puffy", "puffyDiamond", "ghostish", "pixelCircle", "pixelTriangle", "bun", "heart"];
9
+ export type ShapeName = (typeof shapeNames)[number];
10
+ /**
11
+ * Every shape as a 720-point path in a 380 × 380 viewBox (`<svg viewBox="0 0 380 380">`). All
12
+ * share one command structure, start point and winding, so any two morph cleanly. Use these for
13
+ * large, hero-sized shapes; for anything icon-sized prefer {@link animatableShapesSmall}.
14
+ *
15
+ * Importing the map pulls in all 35 paths (~315 KB unminified). To ship only a few, import the
16
+ * individual `pathAnimatable*` constants instead.
17
+ */
18
+ export declare const animatableShapes: Record<"circle" | "square" | "slanted" | "arch" | "semicircle" | "oval" | "pill" | "triangle" | "arrow" | "fan" | "diamond" | "clamshell" | "pentagon" | "gem" | "verySunny" | "sunny" | "fourSidedCookie" | "sixSidedCookie" | "sevenSidedCookie" | "nineSidedCookie" | "twelveSidedCookie" | "fourLeafClover" | "eightLeafClover" | "burst" | "softBurst" | "boom" | "softBoom" | "flower" | "puffy" | "puffyDiamond" | "ghostish" | "pixelCircle" | "pixelTriangle" | "bun" | "heart", string>;
19
+ /**
20
+ * Every shape as a 120-point path in a 48 × 48 viewBox (38 × 38 shape, centred). Same guarantees
21
+ * as {@link animatableShapes} at an eighth of the size: the set for icons, avatars, indicators and
22
+ * FABs. Never mix paths from the two sets in one morph — their point counts differ.
23
+ */
24
+ export declare const animatableShapesSmall: Record<"circle" | "square" | "slanted" | "arch" | "semicircle" | "oval" | "pill" | "triangle" | "arrow" | "fan" | "diamond" | "clamshell" | "pentagon" | "gem" | "verySunny" | "sunny" | "fourSidedCookie" | "sixSidedCookie" | "sevenSidedCookie" | "nineSidedCookie" | "twelveSidedCookie" | "fourLeafClover" | "eightLeafClover" | "burst" | "softBurst" | "boom" | "softBoom" | "flower" | "puffy" | "puffyDiamond" | "ghostish" | "pixelCircle" | "pixelTriangle" | "bun" | "heart", string>;
25
+ /**
26
+ * Morphs an SVG `<path>` from its current `d` to `to` on an M3 spring (default `fastSpatial`,
27
+ * the token for shape morphs). Both paths must come from the same animatable set. Motion drives
28
+ * the progress; the spring's overshoot carries through into the shape. Under
29
+ * `prefers-reduced-motion` the shape swaps instantly (M3: turn off shape morphing).
30
+ *
31
+ * Starting a new morph mid-flight picks up from the in-between shape on screen, so stop the
32
+ * previous controls first — {@link shapeMorph} does this for you.
33
+ *
34
+ * ```ts
35
+ * morphShape(path, animatableShapesSmall.heart);
36
+ * ```
37
+ */
38
+ export declare const morphShape: (path: SVGPathElement, to: string, spring?: SpringToken) => AnimationPlaybackControls | undefined;
39
+ /**
40
+ * Attachment that keeps a `<path>` on `shape()` and morphs whenever it changes. The first shape
41
+ * renders without animating.
42
+ *
43
+ * ```svelte
44
+ * <svg viewBox="0 0 48 48">
45
+ * <path
46
+ * fill="currentColor"
47
+ * {@attach shapeMorph(() => animatableShapesSmall[selected ? 'sunny' : 'circle'])}
48
+ * />
49
+ * </svg>
50
+ * ```
51
+ */
52
+ export declare const shapeMorph: (shape: () => string, spring?: SpringToken) => Attachment<SVGPathElement>;
@@ -0,0 +1,112 @@
1
+ import { animate, mix } from 'motion';
2
+ import { untrack } from 'svelte';
3
+ import * as large from './shapesAnimatable.js';
4
+ import * as small from './shapesAnimatableSmall.js';
5
+ import { springTokens, springTransition } from './spring.js';
6
+ /**
7
+ * The 35 shapes of the M3 Expressive shape library, in the order of the spec sheet.
8
+ * https://m3.material.io/styles/shape
9
+ */
10
+ export const shapeNames = [
11
+ 'circle',
12
+ 'square',
13
+ 'slanted',
14
+ 'arch',
15
+ 'semicircle',
16
+ 'oval',
17
+ 'pill',
18
+ 'triangle',
19
+ 'arrow',
20
+ 'fan',
21
+ 'diamond',
22
+ 'clamshell',
23
+ 'pentagon',
24
+ 'gem',
25
+ 'verySunny',
26
+ 'sunny',
27
+ 'fourSidedCookie',
28
+ 'sixSidedCookie',
29
+ 'sevenSidedCookie',
30
+ 'nineSidedCookie',
31
+ 'twelveSidedCookie',
32
+ 'fourLeafClover',
33
+ 'eightLeafClover',
34
+ 'burst',
35
+ 'softBurst',
36
+ 'boom',
37
+ 'softBoom',
38
+ 'flower',
39
+ 'puffy',
40
+ 'puffyDiamond',
41
+ 'ghostish',
42
+ 'pixelCircle',
43
+ 'pixelTriangle',
44
+ 'bun',
45
+ 'heart'
46
+ ];
47
+ const byName = (paths, prefix) => Object.fromEntries(shapeNames.map((name) => [name, paths[prefix + name[0].toUpperCase() + name.slice(1)]]));
48
+ /**
49
+ * Every shape as a 720-point path in a 380 × 380 viewBox (`<svg viewBox="0 0 380 380">`). All
50
+ * share one command structure, start point and winding, so any two morph cleanly. Use these for
51
+ * large, hero-sized shapes; for anything icon-sized prefer {@link animatableShapesSmall}.
52
+ *
53
+ * Importing the map pulls in all 35 paths (~315 KB unminified). To ship only a few, import the
54
+ * individual `pathAnimatable*` constants instead.
55
+ */
56
+ export const animatableShapes = byName(large, 'pathAnimatable');
57
+ /**
58
+ * Every shape as a 120-point path in a 48 × 48 viewBox (38 × 38 shape, centred). Same guarantees
59
+ * as {@link animatableShapes} at an eighth of the size: the set for icons, avatars, indicators and
60
+ * FABs. Never mix paths from the two sets in one morph — their point counts differ.
61
+ */
62
+ export const animatableShapesSmall = byName(small, 'pathAnimatableSmall');
63
+ const prefersReducedMotion = () => typeof matchMedia === 'function' && matchMedia('(prefers-reduced-motion: reduce)').matches;
64
+ /**
65
+ * Morphs an SVG `<path>` from its current `d` to `to` on an M3 spring (default `fastSpatial`,
66
+ * the token for shape morphs). Both paths must come from the same animatable set. Motion drives
67
+ * the progress; the spring's overshoot carries through into the shape. Under
68
+ * `prefers-reduced-motion` the shape swaps instantly (M3: turn off shape morphing).
69
+ *
70
+ * Starting a new morph mid-flight picks up from the in-between shape on screen, so stop the
71
+ * previous controls first — {@link shapeMorph} does this for you.
72
+ *
73
+ * ```ts
74
+ * morphShape(path, animatableShapesSmall.heart);
75
+ * ```
76
+ */
77
+ export const morphShape = (path, to, spring = springTokens.fastSpatial) => {
78
+ const from = path.getAttribute('d');
79
+ if (!from || from === to || prefersReducedMotion()) {
80
+ path.setAttribute('d', to);
81
+ return;
82
+ }
83
+ const shape = mix(from, to);
84
+ return animate(0, 1, {
85
+ ...springTransition(spring),
86
+ onUpdate: (progress) => path.setAttribute('d', shape(progress))
87
+ });
88
+ };
89
+ /**
90
+ * Attachment that keeps a `<path>` on `shape()` and morphs whenever it changes. The first shape
91
+ * renders without animating.
92
+ *
93
+ * ```svelte
94
+ * <svg viewBox="0 0 48 48">
95
+ * <path
96
+ * fill="currentColor"
97
+ * {@attach shapeMorph(() => animatableShapesSmall[selected ? 'sunny' : 'circle'])}
98
+ * />
99
+ * </svg>
100
+ * ```
101
+ */
102
+ export const shapeMorph = (shape, spring) => (path) => {
103
+ let controls;
104
+ $effect(() => {
105
+ const to = shape();
106
+ untrack(() => {
107
+ controls?.stop();
108
+ controls = morphShape(path, to, spring);
109
+ });
110
+ });
111
+ return () => controls?.stop();
112
+ };