@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,58 +1,62 @@
1
1
  <!--
2
2
  @component
3
- Buttons help people take actions, such as sending an email, sharing a document, or liking a comment.
3
+ Buttons prompt most actions in a UI.
4
4
 
5
- - Filled: High emphasis
6
- - Tonal: Medium-high emphasis
7
- - Outlined: Medium emphasis
8
- - Text: Low emphasis
9
- - Elevated: High emphasis
5
+ - Filled: final or unblocking actions (default)
6
+ - Tonal: important actions a step below filled
7
+ - Elevated: only to stand apart from a patterned background
8
+ - Outlined: attention without being primary, or a way out of a flow
9
+ - Text: optional actions
10
10
 
11
- @see https://m3.material.io/components/all-buttons
11
+ For a two-state button use `Toggle`.
12
+
13
+ @see https://m3.material.io/components/buttons/specs
12
14
  -->
13
15
  <script lang="ts">
14
- import type { ButtonMDProps } from './types.js';
16
+ import type { ButtonProps } from './types.js';
15
17
  import { Icon, LoadingIndicator, Layer } from '../../utils/index.js';
16
- import { button } from './theme.js';
18
+ import { button, buttonColor } from './theme.js';
17
19
  import clsx from 'clsx';
20
+ import { buttonCorners, shapeMorph } from './shapeMorph.js';
18
21
  import { Button, type ButtonRootProps } from 'bits-ui';
19
22
 
20
23
  let {
21
24
  children,
22
25
  iconProps,
23
26
  variant = 'filled',
24
- color = 'default',
25
- size = 'md',
27
+ size = 'sm',
26
28
  shape = 'round',
27
29
  disabled,
28
- selected,
29
30
  formaction,
30
31
  loading,
31
32
  class: className,
32
33
  ...restProps
33
- }: ButtonMDProps = $props();
34
+ }: ButtonProps = $props();
35
+
36
+ let ref = $state<HTMLElement | null>(null);
37
+ $effect(() => (ref ? shapeMorph(ref, buttonCorners) : undefined));
34
38
 
35
- const { base, icon } = $derived(button({ variant, color, shape, size, selected }));
36
- const btnCls = $derived(base({ class: clsx(className) }));
39
+ const cls = $derived(button({ variant, size, shape }));
40
+ const btnCls = $derived(
41
+ cls.base({ class: clsx(buttonColor({ variant, state: 'default' }), className) })
42
+ );
37
43
  </script>
38
44
 
39
45
  <Button.Root
46
+ bind:ref
40
47
  {disabled}
41
48
  {formaction}
42
49
  class={btnCls}
50
+ aria-busy={loading || undefined}
43
51
  data-cy="m3-button"
44
52
  {...restProps as ButtonRootProps}
45
53
  >
46
- {#if iconProps}
47
- {#if loading}
48
- <LoadingIndicator container={variant === 'filled'} class={icon()} />
49
- {:else}
50
- <Icon class={icon()} {...iconProps} />
51
- {@render children?.()}
52
- {/if}
53
- {:else if loading}
54
- <LoadingIndicator container={variant === 'filled'} />
55
- {:else}
54
+ {#if loading}
55
+ <LoadingIndicator center={false} class={cls.icon({ class: 'text-current' })} />
56
+ {:else if iconProps}
57
+ <Icon {...iconProps} class={cls.icon({ class: clsx(iconProps.class) })} />
58
+ {/if}
59
+ {#if !loading || iconProps}
56
60
  {@render children?.()}
57
61
  {/if}
58
62
  <Layer />
@@ -1,16 +1,18 @@
1
- import type { ButtonMDProps } from './types.js';
1
+ import type { ButtonProps } from './types.js';
2
2
  import { Button } from 'bits-ui';
3
3
  /**
4
- * Buttons help people take actions, such as sending an email, sharing a document, or liking a comment.
4
+ * Buttons prompt most actions in a UI.
5
5
  *
6
- * - Filled: High emphasis
7
- * - Tonal: Medium-high emphasis
8
- * - Outlined: Medium emphasis
9
- * - Text: Low emphasis
10
- * - Elevated: High emphasis
6
+ * - Filled: final or unblocking actions (default)
7
+ * - Tonal: important actions a step below filled
8
+ * - Elevated: only to stand apart from a patterned background
9
+ * - Outlined: attention without being primary, or a way out of a flow
10
+ * - Text: optional actions
11
11
  *
12
- * @see https://m3.material.io/components/all-buttons
12
+ * For a two-state button use `Toggle`.
13
+ *
14
+ * @see https://m3.material.io/components/buttons/specs
13
15
  */
14
- declare const Button: import("svelte").Component<ButtonMDProps, {}, "">;
16
+ declare const Button: import("svelte").Component<ButtonProps, {}, "">;
15
17
  type Button = ReturnType<typeof Button>;
16
18
  export default Button;
@@ -0,0 +1,52 @@
1
+ import { Meta, Title, Subtitle, Canvas, Controls } from '@storybook/addon-docs/blocks';
2
+ import * as IconStories from './ButtonIcon.stories.svelte';
3
+
4
+ <Meta of={IconStories} />
5
+
6
+ <Title />
7
+
8
+ <Subtitle>Icon buttons help people take minor actions with one tap.</Subtitle>
9
+
10
+ [M3 spec](https://m3.material.io/components/icon-buttons/specs) ·
11
+ `import { ButtonIcon } from '@noxlovette/material';`
12
+
13
+ <Canvas of={IconStories.Playground} />
14
+
15
+ <Controls of={IconStories.Playground} />
16
+
17
+ ## Colour styles
18
+
19
+ `filled` (default), `tonal`, `outlined` and `standard`. `standard` has no container until it is
20
+ hovered, focused or pressed; use it in app bars, text fields, sheets and other dense places.
21
+
22
+ With `variation="toggle"`, the button has a selected state (`aria-pressed`, bindable `pressed`).
23
+ Unselected, a filled toggle uses surface container; selected, each style takes its strong colour
24
+ (primary, secondary, inverse surface, or a primary icon for standard). The icon fills while
25
+ selected, and the resting shape swaps (round ↔ square).
26
+
27
+ <Canvas of={IconStories.ColourStyles} />
28
+
29
+ ## Sizes and widths
30
+
31
+ | `size` | Height | Icon | Narrow | Default | Wide |
32
+ | ------ | ------ | ---- | ------ | ------- | ----- |
33
+ | `xs` | 32dp | 20dp | 28dp | 32dp | 40dp |
34
+ | `sm` | 40dp | 24dp | 32dp | 40dp | 52dp |
35
+ | `md` | 56dp | 24dp | 48dp | 56dp | 72dp |
36
+ | `lg` | 96dp | 32dp | 64dp | 96dp | 128dp |
37
+ | `xl` | 136dp | 40dp | 104dp | 136dp | 184dp |
38
+
39
+ `sm` is the default. XS and S keep a 48dp target area. Square corners are 12, 12, 16, 28 and
40
+ 28dp; pressed, both shapes tighten to 8, 8, 12, 16 and 16dp.
41
+
42
+ <Canvas of={IconStories.SizesAndWidths} />
43
+
44
+ ## Accessibility
45
+
46
+ An icon has no text, so give every icon button a name: `aria-label`, or `tooltipContent`, which
47
+ shows on hover and focus and becomes the name when there is no `aria-label`.
48
+
49
+ ## Migrating
50
+
51
+ `variant="text"` is now `variant="standard"`, the spec's name, and the default is now `filled`
52
+ (it was `text`). `elevated`, `bare` and `color` are gone.
@@ -2,73 +2,97 @@
2
2
  import { defineMeta } from '@storybook/addon-svelte-csf';
3
3
  import ButtonIcon from './ButtonIcon.svelte';
4
4
 
5
+ const variants = ['filled', 'tonal', 'outlined', 'standard'] as const;
6
+ const sizes = ['xs', 'sm', 'md', 'lg', 'xl'] as const;
7
+ const widths = ['narrow', 'default', 'wide'] as const;
8
+
5
9
  const { Story } = defineMeta({
6
10
  title: 'Buttons/Button Icon',
7
11
  component: ButtonIcon,
8
12
  argTypes: {
9
- variant: {
10
- control: 'select',
11
- options: ['elevated', 'filled', 'tonal', 'outlined', 'text', 'bare']
12
- },
13
- color: {
14
- control: 'select',
15
- options: ['default', 'primary', 'secondary', 'tertiary', 'error']
16
- },
17
- size: {
18
- control: 'select',
19
- options: ['xs', 'sm', 'md', 'lg', 'xl']
20
- },
21
- width: {
22
- control: 'select',
23
- options: ['default', 'narrow', 'wide']
24
- },
25
- shape: {
26
- control: 'select',
27
- options: ['round', 'square']
28
- },
29
- variation: {
30
- control: 'select',
31
- options: ['default', 'toggle']
32
- },
13
+ variant: { control: 'select', options: variants },
14
+ size: { control: 'select', options: sizes },
15
+ width: { control: 'inline-radio', options: widths },
16
+ shape: { control: 'inline-radio', options: ['round', 'square'] },
17
+ variation: { control: 'inline-radio', options: ['default', 'toggle'] },
33
18
  disabled: { control: 'boolean' },
34
- loading: { control: 'boolean' },
35
- tooltipContent: { control: 'text' }
19
+ loading: { control: 'boolean' }
36
20
  },
37
21
  args: {
38
- variant: 'text',
39
- color: 'primary',
40
- size: 'md',
22
+ variant: 'filled',
23
+ size: 'sm',
41
24
  width: 'default',
42
25
  shape: 'round',
43
26
  variation: 'default',
44
27
  disabled: false,
45
28
  loading: false,
46
- iconProps: { name: 'favorite' },
47
- tooltipContent: 'Favorite'
29
+ tooltipContent: 'Favourite',
30
+ iconProps: { name: 'favorite' }
48
31
  }
49
32
  });
50
33
  </script>
51
34
 
52
- <Story name="Playground" />
35
+ <Story name="Playground">
36
+ {#snippet template(args)}
37
+ <ButtonIcon {...args} iconProps={{ name: 'favorite' }} />
38
+ {/snippet}
39
+ </Story>
40
+
41
+ <Story name="Colour styles" asChild>
42
+ <div
43
+ class="gap-spacing-200 p-spacing-300 grid grid-cols-[repeat(3,auto)] items-center justify-start"
44
+ >
45
+ {#each variants as variant (variant)}
46
+ <ButtonIcon {variant} tooltipContent={variant} iconProps={{ name: 'settings' }} />
47
+ <ButtonIcon
48
+ {variant}
49
+ variation="toggle"
50
+ tooltipContent="{variant} toggle, unselected"
51
+ iconProps={{ name: 'bookmark' }}
52
+ />
53
+ <ButtonIcon
54
+ {variant}
55
+ variation="toggle"
56
+ pressed
57
+ tooltipContent="{variant} toggle, selected"
58
+ iconProps={{ name: 'bookmark' }}
59
+ />
60
+ {/each}
61
+ </div>
62
+ </Story>
53
63
 
54
- <Story name="Variants" asChild>
55
- <div class="flex flex-wrap items-center gap-4 p-6">
56
- <ButtonIcon variant="elevated" color="primary" iconProps={{ name: 'favorite' }} />
57
- <ButtonIcon variant="filled" color="primary" iconProps={{ name: 'favorite' }} />
58
- <ButtonIcon variant="tonal" color="primary" iconProps={{ name: 'favorite' }} />
59
- <ButtonIcon variant="outlined" color="primary" iconProps={{ name: 'favorite' }} />
60
- <ButtonIcon variant="text" color="primary" iconProps={{ name: 'favorite' }} />
61
- <ButtonIcon variant="bare" color="primary" iconProps={{ name: 'favorite' }} />
64
+ <Story name="Sizes and widths" asChild>
65
+ <div class="gap-spacing-200 p-spacing-300 flex flex-col items-start">
66
+ <p class="md-sys-typescale-body-medium text-md-sys-color-on-surface-variant max-w-lg">
67
+ Per size: narrow, default and wide round buttons (fully round on their short side, so narrow
68
+ is a vertical pill and wide a horizontal one), then a filled square button.
69
+ </p>
70
+ {#each sizes as size (size)}
71
+ <div class="gap-spacing-200 flex items-center">
72
+ {#each widths as width (width)}
73
+ <ButtonIcon
74
+ {size}
75
+ {width}
76
+ variant="tonal"
77
+ tooltipContent="{size} {width}"
78
+ iconProps={{ name: 'edit' }}
79
+ />
80
+ {/each}
81
+ <ButtonIcon
82
+ {size}
83
+ shape="square"
84
+ tooltipContent="{size} square"
85
+ iconProps={{ name: 'edit' }}
86
+ />
87
+ </div>
88
+ {/each}
62
89
  </div>
63
90
  </Story>
64
91
 
65
- <Story name="Toggle" asChild>
66
- <div class="flex flex-wrap items-center gap-4 p-6">
67
- <ButtonIcon
68
- variation="toggle"
69
- variant="tonal"
70
- iconProps={{ name: 'star' }}
71
- tooltipContent="Star"
72
- />
92
+ <Story name="Disabled" asChild>
93
+ <div class="gap-spacing-200 p-spacing-300 flex">
94
+ {#each variants as variant (variant)}
95
+ <ButtonIcon {variant} disabled aria-label={variant} iconProps={{ name: 'delete' }} />
96
+ {/each}
73
97
  </div>
74
98
  </Story>
@@ -1,29 +1,31 @@
1
1
  <!--
2
2
  @component
3
- Icon buttons help people take minor actions and are often used in app bars.
3
+ Icon buttons help people take minor actions with one tap.
4
4
 
5
- - Standard: Low emphasis
6
- - Filled: High emphasis
7
- - Filled Tonal: Medium-high emphasis
8
- - Outlined: Medium emphasis
5
+ - Filled: high emphasis (default)
6
+ - Tonal: medium-high emphasis
7
+ - Outlined: medium emphasis
8
+ - Standard: low emphasis, no container at rest; for app bars, fields and dense layouts
9
9
 
10
- @see https://m3.material.io/components/icon-buttons/overview
10
+ `variation="toggle"` makes a two-state icon button.
11
+
12
+ @see https://m3.material.io/components/icon-buttons/specs
11
13
  -->
12
14
  <script lang="ts">
13
15
  import type { ButtonIconProps } from './types.js';
14
16
  import { Icon, LoadingIndicator, Layer } from '../../utils/index.js';
15
- import { buttonIcon } from './theme.js';
17
+ import { buttonColor, buttonIcon } from './theme.js';
16
18
  import clsx from 'clsx';
19
+ import { buttonCorners, shapeMorph } from './shapeMorph.js';
17
20
  import Tooltip from '../forms/tooltip/Tooltip.svelte';
18
- import { Button, Toggle, type ButtonRootProps } from 'bits-ui';
19
- import type { ToggleRootProps } from 'bits-ui';
21
+ import { Button, Toggle, type ButtonRootProps, type ToggleRootProps } from 'bits-ui';
20
22
 
21
23
  let {
22
24
  iconProps,
23
- variant = 'text',
24
- color = 'default',
25
- size = 'md',
25
+ variant = 'filled',
26
+ size = 'sm',
26
27
  shape = 'round',
28
+ width = 'default',
27
29
  variation = 'default',
28
30
  triggerClass = '',
29
31
  triggerSide = 'top',
@@ -32,61 +34,81 @@ Icon buttons help people take minor actions and are often used in app bars.
32
34
  formaction,
33
35
  tooltipContent,
34
36
  loading,
35
- width = 'default',
36
- pressed = false,
37
+ pressed = $bindable(false),
37
38
  onPressedChange,
38
39
  class: className,
39
40
  ...restProps
40
41
  }: ButtonIconProps = $props();
41
42
 
42
- const selected = $derived(variation === 'toggle' ? pressed : undefined);
43
+ let ref = $state<HTMLElement | null>(null);
44
+ $effect(() => (ref ? shapeMorph(ref, buttonCorners) : undefined));
43
45
 
44
- const { base, icon } = $derived(
45
- buttonIcon({ variant, color, shape, variation, size, width, selected })
46
+ const toggle = $derived(variation === 'toggle');
47
+ const cls = $derived(buttonIcon({ variant, size, width, shape, selected: toggle && pressed }));
48
+ const colorCls = $derived(
49
+ buttonColor({
50
+ variant,
51
+ state: toggle ? (pressed ? 'selected' : 'unselected') : 'default'
52
+ })
46
53
  );
47
-
48
- const btnCls = $derived(base({ class: clsx(className) }));
54
+ const label = $derived(restProps['aria-label'] ?? tooltipContent);
49
55
  </script>
50
56
 
51
- <Tooltip {triggerClass} variant="snack" supportingText={tooltipContent}>
57
+ {#snippet content()}
58
+ {#if loading}
59
+ <LoadingIndicator center={false} class={cls.icon({ class: 'text-current' })} />
60
+ {:else}
61
+ <Icon
62
+ fill={toggle && pressed ? 1 : 0}
63
+ {...iconProps}
64
+ class={cls.icon({ class: clsx(iconProps.class) })}
65
+ />
66
+ {/if}
67
+ <Layer />
68
+ {/snippet}
69
+
70
+ <Tooltip
71
+ {triggerClass}
72
+ supportingText={tooltipContent}
73
+ contentProps={{ side: triggerSide, align: triggerAlign }}
74
+ >
52
75
  {#snippet trigger({
53
- class: triggerClass_,
76
+ class: tooltipTriggerClass,
54
77
  type: _tooltipType,
55
78
  onclick: _tooltipOnclick,
56
79
  ...triggerAttrs
57
80
  })}
58
- {#if variation === 'toggle'}
81
+ {@const btnCls = cls.base({
82
+ class: clsx(colorCls, className, tooltipTriggerClass as string)
83
+ })}
84
+ {#if toggle}
59
85
  <Toggle.Root
86
+ bind:ref
60
87
  bind:pressed
61
88
  {onPressedChange}
62
89
  {disabled}
63
- class={clsx(btnCls, triggerClass_ as string)}
90
+ class={btnCls}
91
+ aria-busy={loading || undefined}
64
92
  data-cy="m3-button-icon"
65
93
  {...restProps as ToggleRootProps}
66
94
  {...triggerAttrs}
95
+ aria-label={label}
67
96
  >
68
- {#if loading}
69
- <LoadingIndicator />
70
- {:else}
71
- <Icon class={icon()} {...iconProps} />
72
- <Layer />
73
- {/if}
97
+ {@render content()}
74
98
  </Toggle.Root>
75
99
  {:else}
76
100
  <Button.Root
101
+ bind:ref
77
102
  {disabled}
78
103
  {formaction}
79
- class={clsx(btnCls, triggerClass_ as string)}
104
+ class={btnCls}
105
+ aria-busy={loading || undefined}
80
106
  data-cy="m3-button-icon"
81
107
  {...restProps as ButtonRootProps}
82
108
  {...triggerAttrs}
109
+ aria-label={label}
83
110
  >
84
- {#if loading}
85
- <LoadingIndicator />
86
- {:else}
87
- <Icon class={icon()} {...iconProps} />
88
- <Layer />
89
- {/if}
111
+ {@render content()}
90
112
  </Button.Root>
91
113
  {/if}
92
114
  {/snippet}
@@ -1,14 +1,16 @@
1
1
  import type { ButtonIconProps } from './types.js';
2
2
  /**
3
- * Icon buttons help people take minor actions and are often used in app bars.
3
+ * Icon buttons help people take minor actions with one tap.
4
4
  *
5
- * - Standard: Low emphasis
6
- * - Filled: High emphasis
7
- * - Filled Tonal: Medium-high emphasis
8
- * - Outlined: Medium emphasis
5
+ * - Filled: high emphasis (default)
6
+ * - Tonal: medium-high emphasis
7
+ * - Outlined: medium emphasis
8
+ * - Standard: low emphasis, no container at rest; for app bars, fields and dense layouts
9
9
  *
10
- * @see https://m3.material.io/components/icon-buttons/overview
10
+ * `variation="toggle"` makes a two-state icon button.
11
+ *
12
+ * @see https://m3.material.io/components/icon-buttons/specs
11
13
  */
12
- declare const ButtonIcon: import("svelte").Component<ButtonIconProps, {}, "">;
14
+ declare const ButtonIcon: import("svelte").Component<ButtonIconProps, {}, "pressed">;
13
15
  type ButtonIcon = ReturnType<typeof ButtonIcon>;
14
16
  export default ButtonIcon;
@@ -0,0 +1,84 @@
1
+ import { Meta, Title, Subtitle, Canvas, Controls } from '@storybook/addon-docs/blocks';
2
+ import * as FABStories from './FAB.stories.svelte';
3
+
4
+ <Meta of={FABStories} />
5
+
6
+ <Title />
7
+
8
+ <Subtitle>FABs help people take the primary action on a screen.</Subtitle>
9
+
10
+ [FAB spec](https://m3.material.io/components/floating-action-button/specs) ·
11
+ [Extended FAB spec](https://m3.material.io/components/extended-fab/specs) ·
12
+ [FAB menu spec](https://m3.material.io/components/fab-menu/specs) ·
13
+ `import { FAB, FABMenuItem } from '@noxlovette/material';`
14
+
15
+ <Canvas of={FABStories.Playground} />
16
+
17
+ <Controls of={FABStories.Playground} />
18
+
19
+ ## Sizes
20
+
21
+ | `size` | FAB | Icon | Corners | Extended: label, padding, gap |
22
+ | --------- | ---- | ---- | ------- | ----------------------------- |
23
+ | `regular` | 56dp | 24dp | 16dp | title medium, 16dp, 8dp |
24
+ | `medium` | 80dp | 28dp | 20dp | title large, 26dp, 12dp |
25
+ | `large` | 96dp | 36dp | 28dp | headline small, 28dp, 16dp |
26
+ | `small` | 40dp | 24dp | 12dp | none |
27
+
28
+ `small` is the baseline small FAB, which M3 no longer recommends. FABs sit at elevation 3 and
29
+ rise to 4 on hover. Keep 16dp from the window edges.
30
+
31
+ <Canvas of={FABStories.Sizes} />
32
+
33
+ ## Colour
34
+
35
+ `primary-container` (default), `secondary-container` and `tertiary-container`, or the stronger
36
+ `primary`, `secondary` and `tertiary`. The state layer always takes the icon's colour.
37
+
38
+ <Canvas of={FABStories.Colours} />
39
+
40
+ ## FAB and extended FAB
41
+
42
+ Give the FAB a `label` and it becomes an extended FAB where there's room. The two transform
43
+ into each other with the space available, so `expanded` is responsive:
44
+
45
+ - **Default:** a FAB on compact windows, an extended FAB from medium windows up
46
+ (`{ small: false, medium: true }`).
47
+ - **In a `Rail`:** a FAB while the rail is collapsed, an extended FAB while it's expanded.
48
+ - **Your own:** pass `true`, `false`, or per-window values; toggle it to collapse the label
49
+ while the page scrolls.
50
+
51
+ The label slides open and shut on the spatial spring. It also names the FAB for assistive
52
+ technology when collapsed; a FAB without a label needs an `aria-label`.
53
+
54
+ <Canvas of={FABStories.Extended} />
55
+
56
+ <Canvas of={FABStories.Responsive} />
57
+
58
+ ## FAB menu
59
+
60
+ `withMenu` opens up to six `FABMenuItem`s above the FAB, which springs into a 56dp round close
61
+ button in the same top trailing corner. The close button is 56dp whatever the FAB's size, as
62
+ M3 specifies, so a medium or large FAB shrinks into it. The items grow out of it one after
63
+ another, nearest first. Items are 56dp pills 4dp apart, 8dp above the close
64
+ button, in the FAB's colour set: a primary, secondary or tertiary close button with items in the
65
+ matching container colour. The menu takes arrow keys, Escape and outside clicks.
66
+
67
+ <Canvas of={FABStories.FabMenu} />
68
+
69
+ ## Container transform
70
+
71
+ Pass a `surface` snippet and the FAB opens into it: the FAB's container grows from its corner
72
+ into the surface and turns from the FAB's colour into the surface's, and the content fades in
73
+ once it has room (M3's container transform, with a persistent container). It shrinks back on
74
+ Escape, an outside click, or the snippet's `close()`, and focus returns to the FAB. Keep the
75
+ FAB's icon in the surface, as on the "Compose new" row below, so the icon persists too.
76
+
77
+ <Canvas of={FABStories.ContainerTransform} />
78
+
79
+ ## Migrating
80
+
81
+ `config` is now `color`, with the Expressive names: the old `primary` is now `primary-container`
82
+ (the default). `size` gains `medium`. `FABMenuItem` loses `variant`; items follow the FAB's
83
+ colour. `expanded` now defaults to responsive instead of `false`, so a labelled FAB extends on
84
+ wider windows; pass `expanded={false}` to keep the old behaviour.