@noxlovette/material 0.5.1 → 0.6.1

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 (329) 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 +10 -6
  8. package/dist/animation/TransitionPatterns.stories.svelte +30 -20
  9. package/dist/animation/containerTransform.d.ts +4 -2
  10. package/dist/animation/containerTransform.js +4 -2
  11. package/dist/animation/enterExit.js +5 -2
  12. package/dist/animation/skeleton.d.ts +1 -1
  13. package/dist/animation/skeleton.js +1 -1
  14. package/dist/components/badge/Badge.mdx +70 -0
  15. package/dist/components/badge/Badge.stories.svelte +38 -20
  16. package/dist/components/badge/Badge.svelte +12 -5
  17. package/dist/components/badge/theme.d.ts +30 -7
  18. package/dist/components/badge/theme.js +25 -5
  19. package/dist/components/badge/types.d.ts +18 -4
  20. package/dist/components/buttons/Button.mdx +85 -0
  21. package/dist/components/buttons/Button.stories.svelte +62 -27
  22. package/dist/components/buttons/Button.svelte +29 -25
  23. package/dist/components/buttons/Button.svelte.d.ts +11 -9
  24. package/dist/components/buttons/ButtonIcon.mdx +52 -0
  25. package/dist/components/buttons/ButtonIcon.stories.svelte +72 -48
  26. package/dist/components/buttons/ButtonIcon.svelte +58 -36
  27. package/dist/components/buttons/ButtonIcon.svelte.d.ts +9 -7
  28. package/dist/components/buttons/FAB.mdx +84 -0
  29. package/dist/components/buttons/FAB.stories.svelte +103 -24
  30. package/dist/components/buttons/FAB.stories.svelte.d.ts +2 -17
  31. package/dist/components/buttons/FAB.svelte +353 -29
  32. package/dist/components/buttons/FAB.svelte.d.ts +11 -6
  33. package/dist/components/buttons/FABMenu.svelte +27 -8
  34. package/dist/components/buttons/FABMenu.svelte.d.ts +7 -3
  35. package/dist/components/buttons/FABMenuItem.svelte +20 -16
  36. package/dist/components/buttons/FABMenuItem.svelte.d.ts +3 -3
  37. package/dist/components/buttons/Toggle.stories.svelte +31 -23
  38. package/dist/components/buttons/Toggle.stories.svelte.d.ts +2 -17
  39. package/dist/components/buttons/Toggle.svelte +28 -25
  40. package/dist/components/buttons/Toggle.svelte.d.ts +5 -5
  41. package/dist/components/buttons/button-group/ButtonGroup.mdx +39 -0
  42. package/dist/components/buttons/button-group/ButtonGroup.stories.svelte +62 -43
  43. package/dist/components/buttons/button-group/ButtonGroup.stories.svelte.d.ts +2 -17
  44. package/dist/components/buttons/button-group/ButtonGroup.svelte +102 -8
  45. package/dist/components/buttons/button-group/ButtonGroup.svelte.d.ts +6 -7
  46. package/dist/components/buttons/button-group/theme.d.ts +46 -16
  47. package/dist/components/buttons/button-group/theme.js +14 -9
  48. package/dist/components/buttons/button-group/types.d.ts +13 -7
  49. package/dist/components/buttons/connected/ConnectedButtonGroup.mdx +43 -0
  50. package/dist/components/buttons/connected/ConnectedButtonGroup.stories.svelte +56 -74
  51. package/dist/components/buttons/connected/ConnectedButtonGroup.stories.svelte.d.ts +2 -17
  52. package/dist/components/buttons/connected/ConnectedButtonGroup.svelte +16 -4
  53. package/dist/components/buttons/connected/ConnectedButtonGroup.svelte.d.ts +4 -4
  54. package/dist/components/buttons/connected/ConnectedButtonGroupItem.svelte +35 -8
  55. package/dist/components/buttons/connected/ConnectedButtonGroupItem.svelte.d.ts +2 -3
  56. package/dist/components/buttons/connected/theme.d.ts +34 -19
  57. package/dist/components/buttons/connected/theme.js +33 -10
  58. package/dist/components/buttons/connected/types.d.ts +36 -9
  59. package/dist/components/buttons/shapeMorph.d.ts +26 -0
  60. package/dist/components/buttons/shapeMorph.js +142 -0
  61. package/dist/components/buttons/split-button/SplitButton.mdx +48 -0
  62. package/dist/components/buttons/split-button/SplitButton.stories.svelte +9 -14
  63. package/dist/components/buttons/split-button/SplitButton.svelte +66 -49
  64. package/dist/components/buttons/split-button/SplitButton.svelte.d.ts +6 -11
  65. package/dist/components/buttons/split-button/theme.d.ts +111 -18
  66. package/dist/components/buttons/split-button/theme.js +75 -17
  67. package/dist/components/buttons/split-button/types.d.ts +24 -18
  68. package/dist/components/buttons/theme.d.ts +423 -231
  69. package/dist/components/buttons/theme.js +287 -381
  70. package/dist/components/buttons/types.d.ts +130 -125
  71. package/dist/components/cards/Card.mdx +44 -0
  72. package/dist/components/cards/Card.stories.svelte +11 -11
  73. package/dist/components/cards/theme.js +6 -6
  74. package/dist/components/chips/Chip.mdx +68 -0
  75. package/dist/components/chips/Chip.stories.svelte +4 -4
  76. package/dist/components/chips/theme.d.ts +1 -1
  77. package/dist/components/chips/theme.js +4 -4
  78. package/dist/components/containers/action-rail/ActionRail.stories.svelte +1 -0
  79. package/dist/components/containers/action-rail/theme.d.ts +1 -1
  80. package/dist/components/containers/action-rail/theme.js +2 -2
  81. package/dist/components/containers/app/theme.d.ts +1 -1
  82. package/dist/components/containers/app/theme.js +1 -1
  83. package/dist/components/containers/bottom-sheet/BottomSheet.mdx +64 -0
  84. package/dist/components/containers/bottom-sheet/BottomSheet.stories.svelte +108 -12
  85. package/dist/components/containers/bottom-sheet/BottomSheet.svelte +179 -109
  86. package/dist/components/containers/bottom-sheet/BottomSheet.svelte.d.ts +10 -5
  87. package/dist/components/containers/bottom-sheet/index.d.ts +1 -0
  88. package/dist/components/containers/bottom-sheet/index.js +1 -0
  89. package/dist/components/containers/bottom-sheet/theme.d.ts +45 -0
  90. package/dist/components/containers/bottom-sheet/theme.js +42 -0
  91. package/dist/components/containers/bottom-sheet/types.d.ts +37 -5
  92. package/dist/components/containers/carousel/Carousel.mdx +80 -0
  93. package/dist/components/containers/carousel/Carousel.stories.svelte +131 -0
  94. package/dist/components/containers/carousel/Carousel.stories.svelte.d.ts +4 -0
  95. package/dist/components/containers/carousel/Carousel.svelte +194 -0
  96. package/dist/components/containers/carousel/Carousel.svelte.d.ts +25 -0
  97. package/dist/components/containers/carousel/index.d.ts +3 -0
  98. package/dist/components/containers/{stack → carousel}/index.js +1 -2
  99. package/dist/components/containers/carousel/keylines.d.ts +32 -0
  100. package/dist/components/containers/carousel/keylines.js +88 -0
  101. package/dist/components/containers/carousel/theme.d.ts +162 -0
  102. package/dist/components/containers/carousel/theme.js +67 -0
  103. package/dist/components/containers/carousel/types.d.ts +52 -0
  104. package/dist/components/containers/context-menu/ContextMenu.stories.svelte +1 -0
  105. package/dist/components/containers/context-menu/ContextMenu.svelte +2 -2
  106. package/dist/components/containers/context-menu/ContextMenu.svelte.d.ts +1 -1
  107. package/dist/components/containers/context-menu/theme.d.ts +1 -1
  108. package/dist/components/containers/context-menu/theme.js +11 -11
  109. package/dist/components/containers/dialogue/Dialogue.mdx +65 -0
  110. package/dist/components/containers/dialogue/Dialogue.stories.svelte +4 -4
  111. package/dist/components/containers/dialogue/Dialogue.svelte +2 -2
  112. package/dist/components/containers/dialogue/theme.d.ts +1 -1
  113. package/dist/components/containers/dialogue/theme.js +4 -4
  114. package/dist/components/containers/dialogue/types.d.ts +1 -1
  115. package/dist/components/containers/divider/Divider.stories.svelte +2 -1
  116. package/dist/components/containers/divider/Divider.svelte +2 -2
  117. package/dist/components/containers/divider/theme.d.ts +7 -7
  118. package/dist/components/containers/divider/theme.js +3 -3
  119. package/dist/components/containers/index.d.ts +1 -1
  120. package/dist/components/containers/index.js +1 -1
  121. package/dist/components/containers/link-preview/theme.d.ts +1 -1
  122. package/dist/components/containers/link-preview/theme.js +3 -3
  123. package/dist/components/containers/list/List.svelte +18 -0
  124. package/dist/components/containers/list/List.svelte.d.ts +4 -0
  125. package/dist/components/containers/list/ListItem.mdx +100 -0
  126. package/dist/components/containers/list/ListItem.stories.svelte +177 -42
  127. package/dist/components/containers/list/ListItem.stories.svelte.d.ts +2 -17
  128. package/dist/components/containers/list/ListItem.svelte +92 -37
  129. package/dist/components/containers/list/ListItem.svelte.d.ts +1 -1
  130. package/dist/components/containers/list/context.d.ts +6 -0
  131. package/dist/components/containers/list/context.js +4 -0
  132. package/dist/components/containers/list/index.d.ts +1 -0
  133. package/dist/components/containers/list/index.js +1 -0
  134. package/dist/components/containers/list/theme.d.ts +487 -12
  135. package/dist/components/containers/list/theme.js +141 -14
  136. package/dist/components/containers/list/types.d.ts +39 -5
  137. package/dist/components/containers/menu/Menu.mdx +52 -0
  138. package/dist/components/containers/menu/Menu.stories.svelte +14 -14
  139. package/dist/components/containers/menu/Menu.svelte +2 -2
  140. package/dist/components/containers/menu/MenuGroup.svelte +1 -1
  141. package/dist/components/containers/menu/MenuGroup.svelte.d.ts +1 -1
  142. package/dist/components/containers/menu/MenuSub.svelte +1 -1
  143. package/dist/components/containers/menu/menu-item/MenuItem.svelte +1 -1
  144. package/dist/components/containers/menu/theme.d.ts +1 -1
  145. package/dist/components/containers/menu/theme.js +9 -9
  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.d.ts +1 -1
  158. package/dist/components/containers/pane/theme.js +131 -47
  159. package/dist/components/containers/pane/types.d.ts +3 -2
  160. package/dist/components/containers/popover/Popover.mdx +45 -0
  161. package/dist/components/containers/popover/Popover.stories.svelte +1 -1
  162. package/dist/components/containers/popover/Popover.svelte +1 -1
  163. package/dist/components/containers/popover/theme.d.ts +1 -1
  164. package/dist/components/containers/popover/theme.js +4 -4
  165. package/dist/components/containers/scroll-area/theme.js +3 -3
  166. package/dist/components/containers/side-sheet/SideSheet.mdx +71 -0
  167. package/dist/components/containers/side-sheet/SideSheet.stories.svelte +113 -17
  168. package/dist/components/containers/side-sheet/SideSheet.svelte +113 -66
  169. package/dist/components/containers/side-sheet/SideSheet.svelte.d.ts +8 -7
  170. package/dist/components/containers/side-sheet/index.d.ts +1 -0
  171. package/dist/components/containers/side-sheet/index.js +1 -0
  172. package/dist/components/containers/side-sheet/theme.d.ts +108 -0
  173. package/dist/components/containers/side-sheet/theme.js +72 -0
  174. package/dist/components/containers/side-sheet/types.d.ts +35 -7
  175. package/dist/components/date/DateField.stories.svelte +4 -3
  176. package/dist/components/date/DateField.svelte +11 -2
  177. package/dist/components/date/DateRangeField.stories.svelte +4 -3
  178. package/dist/components/date/DateRangeField.svelte +12 -3
  179. package/dist/components/date/theme.d.ts +8 -8
  180. package/dist/components/date/theme.js +32 -32
  181. package/dist/components/forms/checkbox/Checkbox.mdx +35 -0
  182. package/dist/components/forms/checkbox/Checkbox.stories.svelte +2 -2
  183. package/dist/components/forms/checkbox/Checkbox.svelte +1 -1
  184. package/dist/components/forms/checkbox/theme.d.ts +1 -1
  185. package/dist/components/forms/checkbox/theme.js +4 -4
  186. package/dist/components/forms/command/Command.stories.svelte +1 -0
  187. package/dist/components/forms/command/theme.d.ts +1 -1
  188. package/dist/components/forms/command/theme.js +10 -10
  189. package/dist/components/forms/pin/theme.d.ts +1 -1
  190. package/dist/components/forms/pin/theme.js +5 -5
  191. package/dist/components/forms/radio-group/RadioGroup.svelte +1 -1
  192. package/dist/components/forms/radio-group/theme.d.ts +1 -1
  193. package/dist/components/forms/radio-group/theme.js +6 -6
  194. package/dist/components/forms/search/Search.mdx +38 -0
  195. package/dist/components/forms/search/Search.stories.svelte +19 -9
  196. package/dist/components/forms/search/Search.svelte +40 -17
  197. package/dist/components/forms/search/Search.svelte.d.ts +2 -2
  198. package/dist/components/forms/search/theme.d.ts +46 -13
  199. package/dist/components/forms/search/theme.js +14 -9
  200. package/dist/components/forms/search/types.d.ts +18 -12
  201. package/dist/components/forms/select/Select.mdx +53 -0
  202. package/dist/components/forms/select/Select.stories.svelte +4 -4
  203. package/dist/components/forms/select/Select.svelte +12 -4
  204. package/dist/components/forms/select/SelectItem.svelte +1 -1
  205. package/dist/components/forms/select/theme.d.ts +1 -1
  206. package/dist/components/forms/select/theme.js +14 -14
  207. package/dist/components/forms/slider/Slider.mdx +85 -0
  208. package/dist/components/forms/slider/Slider.stories.svelte +7 -7
  209. package/dist/components/forms/slider/Slider.svelte +46 -28
  210. package/dist/components/forms/slider/theme.d.ts +15 -1
  211. package/dist/components/forms/slider/theme.js +29 -18
  212. package/dist/components/forms/slider/types.d.ts +3 -2
  213. package/dist/components/forms/switch/Switch.mdx +38 -0
  214. package/dist/components/forms/switch/Switch.stories.svelte +3 -3
  215. package/dist/components/forms/switch/theme.d.ts +1 -1
  216. package/dist/components/forms/switch/theme.js +7 -7
  217. package/dist/components/forms/textfield/Textfield.mdx +53 -0
  218. package/dist/components/forms/textfield/Textfield.stories.svelte +6 -6
  219. package/dist/components/forms/textfield/Textfield.svelte +1 -0
  220. package/dist/components/forms/textfield/theme.d.ts +1 -1
  221. package/dist/components/forms/textfield/theme.js +20 -20
  222. package/dist/components/forms/toggle-group/theme.d.ts +1 -1
  223. package/dist/components/forms/toggle-group/theme.js +3 -3
  224. package/dist/components/forms/tooltip/Tooltip.stories.svelte +1 -0
  225. package/dist/components/forms/tooltip/theme.d.ts +1 -1
  226. package/dist/components/forms/tooltip/theme.js +4 -4
  227. package/dist/components/misc/Avatar.stories.svelte +5 -4
  228. package/dist/components/misc/ThemeSettings.svelte +9 -9
  229. package/dist/components/misc/ThemeSwitcher.svelte +3 -3
  230. package/dist/components/misc/theme.js +5 -5
  231. package/dist/components/nav/appbar/AppBar.mdx +71 -0
  232. package/dist/components/nav/appbar/AppBar.stories.svelte +93 -3
  233. package/dist/components/nav/appbar/AppBar.stories.svelte.d.ts +2 -17
  234. package/dist/components/nav/appbar/AppBar.svelte +90 -37
  235. package/dist/components/nav/appbar/AppBar.svelte.d.ts +9 -2
  236. package/dist/components/nav/appbar/theme.d.ts +86 -19
  237. package/dist/components/nav/appbar/theme.js +160 -24
  238. package/dist/components/nav/appbar/types.d.ts +46 -9
  239. package/dist/components/nav/breadcrumb/Breadcrumb.stories.svelte +1 -0
  240. package/dist/components/nav/breadcrumb/theme.d.ts +1 -1
  241. package/dist/components/nav/breadcrumb/theme.js +6 -6
  242. package/dist/components/nav/navbar/Navbar.mdx +38 -0
  243. package/dist/components/nav/navbar/Navbar.svelte +1 -1
  244. package/dist/components/nav/navbar/NavbarItem.svelte +12 -9
  245. package/dist/components/nav/navbar/theme.d.ts +3 -3
  246. package/dist/components/nav/navbar/theme.js +7 -7
  247. package/dist/components/nav/rail/Rail.mdx +73 -0
  248. package/dist/components/nav/rail/Rail.stories.svelte +3 -7
  249. package/dist/components/nav/rail/Rail.svelte +5 -2
  250. package/dist/components/nav/rail/RailItem.svelte +12 -9
  251. package/dist/components/nav/rail/theme.d.ts +1 -1
  252. package/dist/components/nav/rail/theme.js +14 -14
  253. package/dist/components/nav/rail/types.d.ts +8 -1
  254. package/dist/components/nav/tabs/Tabs.mdx +62 -0
  255. package/dist/components/nav/tabs/Tabs.stories.svelte +1 -1
  256. package/dist/components/nav/tabs/theme.d.ts +1 -1
  257. package/dist/components/nav/tabs/theme.js +5 -5
  258. package/dist/components/pill/Pill.mdx +32 -0
  259. package/dist/components/pill/Pill.stories.svelte +1 -1
  260. package/dist/components/pill/theme.d.ts +2 -2
  261. package/dist/components/pill/theme.js +2 -2
  262. package/dist/components/progress/LinearProgress.svelte +2 -2
  263. package/dist/components/progress/Progress.mdx +50 -0
  264. package/dist/components/progress/Progress.stories.svelte +6 -6
  265. package/dist/components/snackbar/Snackbar.mdx +52 -0
  266. package/dist/components/snackbar/Snackbar.stories.svelte +5 -5
  267. package/dist/components/snackbar/Snackbar.svelte +1 -1
  268. package/dist/components/snackbar/theme.d.ts +4 -4
  269. package/dist/components/snackbar/theme.js +5 -5
  270. package/dist/components/table/Table.stories.svelte +1 -0
  271. package/dist/components/table/TableHeader.svelte +1 -1
  272. package/dist/components/table/theme.d.ts +1 -1
  273. package/dist/components/table/theme.js +4 -4
  274. package/dist/components/time/TimeField.stories.svelte +3 -2
  275. package/dist/components/time/TimeField.svelte +2 -2
  276. package/dist/components/time/TimepickerInput.svelte +1 -1
  277. package/dist/components/time/theme.d.ts +1 -1
  278. package/dist/components/time/theme.js +6 -6
  279. package/dist/components/toolbar/Toolbar.stories.svelte +1 -0
  280. package/dist/components/toolbar/Toolbar.svelte +1 -1
  281. package/dist/components/toolbar/Toolbar.svelte.d.ts +1 -1
  282. package/dist/components/toolbar/theme.d.ts +1 -1
  283. package/dist/components/toolbar/theme.js +15 -15
  284. package/dist/components/typography/Typography.mdx +67 -0
  285. package/dist/components/typography/body/Body.stories.svelte +2 -1
  286. package/dist/components/typography/body/theme.d.ts +16 -13
  287. package/dist/components/typography/body/theme.js +20 -5
  288. package/dist/components/typography/body/types.d.ts +2 -1
  289. package/dist/components/typography/display/Display.stories.svelte +2 -1
  290. package/dist/components/typography/display/theme.d.ts +16 -13
  291. package/dist/components/typography/display/theme.js +20 -5
  292. package/dist/components/typography/display/types.d.ts +2 -1
  293. package/dist/components/typography/headline/Headline.stories.svelte +2 -1
  294. package/dist/components/typography/headline/theme.d.ts +16 -13
  295. package/dist/components/typography/headline/theme.js +20 -5
  296. package/dist/components/typography/headline/types.d.ts +2 -1
  297. package/dist/components/typography/kbd/Kbd.stories.svelte +2 -1
  298. package/dist/components/typography/kbd/theme.d.ts +5 -5
  299. package/dist/components/typography/kbd/theme.js +3 -3
  300. package/dist/components/typography/label/Label.stories.svelte +2 -1
  301. package/dist/components/typography/label/theme.d.ts +15 -12
  302. package/dist/components/typography/label/theme.js +20 -5
  303. package/dist/components/typography/label/types.d.ts +2 -1
  304. package/dist/components/typography/title/Title.stories.svelte +2 -1
  305. package/dist/components/typography/title/theme.d.ts +16 -13
  306. package/dist/components/typography/title/theme.js +20 -5
  307. package/dist/components/typography/title/types.d.ts +2 -1
  308. package/dist/index.css +2 -0
  309. package/dist/styles/component.css +78 -175
  310. package/dist/styles/elevation.css +9 -0
  311. package/dist/styles/layers.css +33 -0
  312. package/dist/styles/spacing.css +29 -0
  313. package/dist/styles/typescale.css +635 -20
  314. package/dist/utils/Layer.svelte +1 -1
  315. package/dist/utils/icon/Icon.svelte +8 -6
  316. package/dist/utils/icon/theme.d.ts +1 -1
  317. package/dist/utils/icon/theme.js +1 -1
  318. package/dist/utils/tv.d.ts +6 -0
  319. package/dist/utils/tv.js +12 -0
  320. package/package.json +19 -15
  321. package/dist/components/containers/stack/HStack.svelte +0 -23
  322. package/dist/components/containers/stack/HStack.svelte.d.ts +0 -5
  323. package/dist/components/containers/stack/VStack.svelte +0 -23
  324. package/dist/components/containers/stack/VStack.svelte.d.ts +0 -5
  325. package/dist/components/containers/stack/index.d.ts +0 -4
  326. package/dist/components/containers/stack/theme.d.ts +0 -66
  327. package/dist/components/containers/stack/theme.js +0 -26
  328. package/dist/components/containers/stack/types.d.ts +0 -12
  329. /package/dist/components/containers/{stack → carousel}/types.js +0 -0
@@ -0,0 +1,18 @@
1
+ <script lang="ts">
2
+ import clsx from 'clsx';
3
+ import { list } from './theme.js';
4
+ import { setListContext } from './context.js';
5
+ import type { ListProps } from './types.js';
6
+
7
+ let { variant = 'standard', class: className, children, ...restProps }: ListProps = $props();
8
+
9
+ setListContext({
10
+ get variant() {
11
+ return variant;
12
+ }
13
+ });
14
+ </script>
15
+
16
+ <ul class={list({ variant, class: clsx(className) })} {...restProps}>
17
+ {@render children?.()}
18
+ </ul>
@@ -0,0 +1,4 @@
1
+ import type { ListProps } from './types.js';
2
+ declare const List: import("svelte").Component<ListProps, {}, "">;
3
+ type List = ReturnType<typeof List>;
4
+ export default List;
@@ -0,0 +1,100 @@
1
+ import { Meta, Title, Subtitle, Canvas, Controls, ArgTypes } from '@storybook/addon-docs/blocks';
2
+ import * as ListStories from './ListItem.stories.svelte';
3
+ import List from './List.svelte';
4
+
5
+ <Meta of={ListStories} />
6
+
7
+ <Title />
8
+
9
+ <Subtitle>Lists are continuous, vertical indexes of text and images.</Subtitle>
10
+
11
+ [M3 spec](https://m3.material.io/components/lists/specs) ·
12
+ `import { List, ListItem, listMedia } from '@noxlovette/material';`
13
+
14
+ <Canvas of={ListStories.Playground} />
15
+
16
+ <Controls of={ListStories.Playground} />
17
+
18
+ ## `List` and `ListItem`
19
+
20
+ Put `ListItem`s in a `List`. `List` renders the `<ul>` and chooses the look for every item in it:
21
+
22
+ - **`standard`** (default): items sit on the page's `surface`.
23
+ - **`segmented`**: each item is its own segment, 2dp apart, with 16dp outer corners on the first
24
+ and last. This is a visual choice only; behaviour is the same.
25
+
26
+ A `ListItem` outside a `List` renders as a standard item.
27
+
28
+ <ArgTypes of={List} />
29
+
30
+ <Canvas of={ListStories.Segmented} />
31
+
32
+ ## What the item is
33
+
34
+ The props decide the element, so each item has one action:
35
+
36
+ | Props | Element | Use for |
37
+ | ------------------- | ------------------- | ---------------------------------------------------------------------- |
38
+ | `href` | `<a>` | Navigation. `selected` sets `aria-current="page"`. |
39
+ | `onclick` | `<button>` | An action. `selected` sets `aria-pressed`. |
40
+ | `label` | `<label>` | An item that toggles the checkbox, radio or switch in it. |
41
+ | `children` (nested) | `<button>` + region | An expandable item; see below. |
42
+ | none | `<div>` | Static content. With `role="option"`, `selected` sets `aria-selected`. |
43
+
44
+ `disabled` removes a link's `href` and disables a button.
45
+
46
+ ## Line counts
47
+
48
+ One, two or three lines give 56, 72 and 88dp minimum heights. `lines` is worked out from
49
+ `overline` and `supporting` unless you set it. At three lines, leading and trailing content align
50
+ to the top.
51
+
52
+ <Canvas of={ListStories.LineCounts} />
53
+
54
+ ## Leading media
55
+
56
+ The `leading` slot holds **one** element that is narrower than the text. Size it with the
57
+ `listMedia` helper so it matches the spec:
58
+
59
+ | Media | Size | How |
60
+ | ----------------- | ------------------------- | ------------------------------------------- |
61
+ | Icon | 20dp | `<Icon size="sm">` |
62
+ | Avatar | 40dp circle | `class={listMedia({ kind: 'avatar' })}` |
63
+ | Image | 56×56dp, 8dp corners | `class={listMedia({ kind: 'image' })}` |
64
+ | Video thumbnail | 100×56dp, 8dp corners | `class={listMedia({ kind: 'video' })}` |
65
+ | Large video | 114×64dp, 8dp corners | `class={listMedia({ kind: 'videoLarge' })}` |
66
+ | Selection control | checkbox, radio or switch | with `label` on the item |
67
+
68
+ Decorative media gets `alt=""`: the headline is the item's accessible name.
69
+
70
+ <Canvas of={ListStories.LeadingMedia} />
71
+
72
+ ## Trailing content
73
+
74
+ `trailing` takes an icon (20dp), an icon button, or a selection control. `trailingText` is for
75
+ short text such as a count, a time or a shortcut. Don't put a selection control at both ends of
76
+ the same item, and keep interactive trailing content at a 48dp target.
77
+
78
+ <Canvas of={ListStories.MultiAction} />
79
+
80
+ ## Expand
81
+
82
+ Giving a `ListItem` `children` makes it expandable. The item becomes a button with a trailing
83
+ chevron, `aria-expanded` and `aria-controls`. The nested items are `inert` while collapsed. Bind
84
+ `expanded` to control it.
85
+
86
+ <Canvas of={ListStories.Expand} />
87
+
88
+ ## States
89
+
90
+ `selected` fills the item with `secondary-container` and rounds it to 16dp. `disabled` drops the
91
+ content to 38%. Hover, focus and press tints come from the shared state layer. The keyboard focus
92
+ ring is drawn inside the item, so segments don't overlap.
93
+
94
+ <Canvas of={ListStories.Disabled} />
95
+
96
+ ## Where this differs from the tokens
97
+
98
+ - Segmented items use `surface-container`. The token says `surface`, but the spec's figures show
99
+ the segments on a tinted container.
100
+ - A selected, disabled item keeps a 12% container. The token says 38%, which reads as enabled.
@@ -1,100 +1,235 @@
1
1
  <script module lang="ts">
2
2
  import { defineMeta } from '@storybook/addon-svelte-csf';
3
3
  import ListItem from './ListItem.svelte';
4
+ import List from './List.svelte';
5
+ import { listMedia } from './theme.js';
4
6
  import Icon from '../../../utils/icon/Icon.svelte';
7
+ import Avatar from '../../misc/Avatar.svelte';
8
+ import ButtonIcon from '../../buttons/ButtonIcon.svelte';
5
9
 
6
10
  const { Story } = defineMeta({
7
- title: 'Containers/List Item',
11
+ title: 'Containers/List',
8
12
  component: ListItem,
9
13
  argTypes: {
10
14
  headline: { control: 'text' },
11
15
  overline: { control: 'text' },
12
16
  supporting: { control: 'text' },
13
- selected: { control: 'boolean' }
17
+ trailingText: { control: 'text' },
18
+ selected: { control: 'boolean' },
19
+ disabled: { control: 'boolean' }
14
20
  },
15
21
  args: {
16
22
  headline: 'Headline',
17
23
  overline: '',
18
24
  supporting: '',
19
- selected: false
25
+ trailingText: '',
26
+ selected: false,
27
+ disabled: false
20
28
  }
21
29
  });
30
+
31
+ const tracks = ['Blue in Green', 'So What', 'Freddie Freeloader', 'All Blues'];
32
+ </script>
33
+
34
+ <script lang="ts">
35
+ let single = $state(1);
36
+ let settings = $state(0);
37
+ let photosExpanded = $state(true);
22
38
  </script>
23
39
 
24
40
  <Story name="Playground">
25
41
  {#snippet template(args)}
26
- <ul class="w-80">
42
+ <List class="w-80">
27
43
  <ListItem
28
44
  headline={args.headline}
29
45
  overline={args.overline}
30
46
  supporting={args.supporting}
47
+ trailingText={args.trailingText}
31
48
  selected={args.selected}
32
- />
33
- </ul>
49
+ disabled={args.disabled}
50
+ onclick={() => {}}
51
+ >
52
+ {#snippet leading()}
53
+ <Icon name="star" size="sm" />
54
+ {/snippet}
55
+ </ListItem>
56
+ </List>
34
57
  {/snippet}
35
58
  </Story>
36
59
 
37
- <Story name="One Line" asChild>
38
- <ul class="w-80">
39
- <ListItem headline="Headline" />
40
- </ul>
60
+ <Story name="Standard" asChild>
61
+ <List class="w-80">
62
+ {#each tracks as track, i (track)}
63
+ <ListItem
64
+ headline={track}
65
+ trailingText="⌘{i + 1}"
66
+ selected={single === i}
67
+ onclick={() => (single = i)}
68
+ >
69
+ {#snippet leading()}
70
+ <Icon name="music_note" size="sm" />
71
+ {/snippet}
72
+ </ListItem>
73
+ {/each}
74
+ </List>
41
75
  </Story>
42
76
 
43
- <Story name="Two Line" asChild>
44
- <ul class="w-80">
45
- <ListItem headline="Headline" supporting="Supporting text that describes the item" />
46
- </ul>
77
+ <Story name="Segmented" asChild>
78
+ <div class="bg-md-sys-color-surface p-spacing-200 w-96">
79
+ <List variant="segmented">
80
+ {#each ['Wi-Fi', 'Bluetooth', 'Notifications', 'Display'] as label, i (label)}
81
+ <ListItem
82
+ headline={label}
83
+ supporting="Supporting text"
84
+ selected={settings === i}
85
+ onclick={() => (settings = i)}
86
+ >
87
+ {#snippet leading()}
88
+ <Icon name="settings" size="sm" />
89
+ {/snippet}
90
+ {#snippet trailing()}
91
+ <Icon name="chevron_right" size="sm" />
92
+ {/snippet}
93
+ </ListItem>
94
+ {/each}
95
+ </List>
96
+ </div>
47
97
  </Story>
48
98
 
49
- <Story name="Three Line" asChild>
50
- <ul class="w-80">
99
+ <Story name="Line counts" asChild>
100
+ <List variant="segmented" class="w-96">
101
+ <ListItem headline="One line" />
102
+ <ListItem headline="Two lines" supporting="Supporting text that describes the item" />
51
103
  <ListItem
52
104
  overline="Overline"
53
- headline="Headline"
54
- supporting="Supporting text that spans up to two lines before it gets clipped"
55
- />
56
- </ul>
105
+ headline="Three lines"
106
+ supporting="At 88dp and taller, leading and trailing content align to the top"
107
+ trailingText="100+"
108
+ >
109
+ {#snippet leading()}
110
+ <Icon name="inbox" size="sm" />
111
+ {/snippet}
112
+ </ListItem>
113
+ </List>
57
114
  </Story>
58
115
 
59
- <Story name="With Leading Icon" asChild>
60
- <ul class="w-80">
61
- <ListItem headline="Headline" supporting="Supporting text">
116
+ <Story name="Leading media" asChild>
117
+ <List variant="segmented" class="w-96">
118
+ <ListItem headline="Icon" supporting="20dp, <Icon size=&quot;sm&quot;>">
119
+ {#snippet leading()}
120
+ <Icon name="folder" size="sm" />
121
+ {/snippet}
122
+ </ListItem>
123
+ <ListItem headline="Avatar" supporting="40dp circle">
124
+ {#snippet leading()}
125
+ <Avatar seed="Ada" alt="" class={listMedia({ kind: 'avatar' })} />
126
+ {/snippet}
127
+ </ListItem>
128
+ <ListItem headline="Image" supporting="56dp, 8dp corners">
129
+ {#snippet leading()}
130
+ <div
131
+ class="{listMedia({
132
+ kind: 'image'
133
+ })} from-md-sys-color-primary to-md-sys-color-tertiary bg-linear-to-br"
134
+ aria-hidden="true"
135
+ ></div>
136
+ {/snippet}
137
+ </ListItem>
138
+ <ListItem headline="Video" supporting="100×56dp, 8dp corners">
139
+ {#snippet leading()}
140
+ <div
141
+ class="{listMedia({
142
+ kind: 'video'
143
+ })} from-md-sys-color-secondary to-md-sys-color-primary bg-linear-to-br"
144
+ aria-hidden="true"
145
+ ></div>
146
+ {/snippet}
147
+ </ListItem>
148
+ <ListItem headline="Large video" supporting="114×64dp, 8dp corners">
62
149
  {#snippet leading()}
63
- <Icon name="folder" />
150
+ <div
151
+ class="{listMedia({
152
+ kind: 'videoLarge'
153
+ })} from-md-sys-color-tertiary to-md-sys-color-secondary bg-linear-to-br"
154
+ aria-hidden="true"
155
+ ></div>
64
156
  {/snippet}
65
157
  </ListItem>
66
- </ul>
158
+ </List>
67
159
  </Story>
68
160
 
69
- <Story name="With Trailing and Badge" asChild>
70
- <ul class="w-80">
71
- <ListItem headline="Headline" supporting="Supporting text" badge={3}>
161
+ <Story name="Multi-action" asChild>
162
+ <List class="w-96">
163
+ {#each tracks as track (track)}
164
+ <li class="flex items-center">
165
+ <ListItem asChild headline={track} onclick={() => {}}>
166
+ {#snippet leading()}
167
+ <Icon name="music_note" size="sm" />
168
+ {/snippet}
169
+ </ListItem>
170
+ <ButtonIcon
171
+ variant="standard"
172
+ iconProps={{ name: 'more_vert' }}
173
+ aria-label="More for {track}"
174
+ />
175
+ </li>
176
+ {/each}
177
+ </List>
178
+ </Story>
179
+
180
+ <Story name="Expand" asChild>
181
+ <List variant="segmented" class="w-96">
182
+ <ListItem headline="Photos" supporting="3 albums" bind:expanded={photosExpanded}>
72
183
  {#snippet leading()}
73
- <Icon name="inbox" />
184
+ <Icon name="image" size="sm" />
74
185
  {/snippet}
75
- {#snippet trailing()}
76
- <Icon name="chevron_right" />
186
+ <ListItem headline="Holidays" href="#" />
187
+ <ListItem headline="Family" href="#" />
188
+ <ListItem headline="Screenshots" href="#" />
189
+ </ListItem>
190
+ <ListItem headline="Documents" supporting="2 folders">
191
+ {#snippet leading()}
192
+ <Icon name="folder" size="sm" />
77
193
  {/snippet}
194
+ <ListItem headline="Work" href="#" />
195
+ <ListItem headline="Personal" href="#" />
78
196
  </ListItem>
79
- </ul>
197
+ <ListItem headline="Downloads" href="#">
198
+ {#snippet leading()}
199
+ <Icon name="download" size="sm" />
200
+ {/snippet}
201
+ </ListItem>
202
+ </List>
80
203
  </Story>
81
204
 
82
- <Story name="Selected" asChild>
83
- <ul class="w-80">
84
- <ListItem headline="Headline" supporting="Supporting text" selected>
205
+ <Story name="Disabled" asChild>
206
+ <List variant="segmented" class="w-80">
207
+ <ListItem headline="Enabled" supporting="Supporting text" onclick={() => {}} />
208
+ <ListItem headline="Disabled" supporting="Supporting text" disabled onclick={() => {}}>
209
+ {#snippet leading()}
210
+ <Icon name="wifi" size="sm" />
211
+ {/snippet}
212
+ </ListItem>
213
+ <ListItem
214
+ headline="Disabled, selected"
215
+ supporting="Supporting text"
216
+ disabled
217
+ selected
218
+ onclick={() => {}}
219
+ >
85
220
  {#snippet leading()}
86
- <Icon name="check_circle" />
221
+ <Icon name="wifi" size="sm" />
87
222
  {/snippet}
88
223
  </ListItem>
89
- </ul>
224
+ </List>
90
225
  </Story>
91
226
 
92
- <Story name="As Link" asChild>
93
- <ul class="w-80">
94
- <ListItem headline="Headline" supporting="Navigates on click" href="#">
227
+ <Story name="Badge" asChild>
228
+ <List class="w-80">
229
+ <ListItem headline="Inbox" supporting="Supporting text" badge={3} href="#">
95
230
  {#snippet leading()}
96
- <Icon name="link" />
231
+ <Icon name="inbox" size="sm" />
97
232
  {/snippet}
98
233
  </ListItem>
99
- </ul>
234
+ </List>
100
235
  </Story>
@@ -1,19 +1,4 @@
1
1
  import ListItem from './ListItem.svelte';
2
- interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
3
- new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
4
- $$bindings?: Bindings;
5
- } & Exports;
6
- (internal: unknown, props: {
7
- $$events?: Events;
8
- $$slots?: Slots;
9
- }): Exports & {
10
- $set?: any;
11
- $on?: any;
12
- };
13
- z_$$bindings?: Bindings;
14
- }
15
- declare const ListItem: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
16
- [evt: string]: CustomEvent<any>;
17
- }, {}, {}, string>;
18
- type ListItem = InstanceType<typeof ListItem>;
2
+ declare const ListItem: import("svelte").Component<Record<string, never>, {}, "">;
3
+ type ListItem = ReturnType<typeof ListItem>;
19
4
  export default ListItem;
@@ -1,7 +1,8 @@
1
1
  <script lang="ts">
2
- import { Layer } from '../../../utils/index.js';
2
+ import { Icon, Layer } from '../../../utils/index.js';
3
3
  import clsx from 'clsx';
4
- import { listiem } from './theme.js';
4
+ import { listItem } from './theme.js';
5
+ import { getListContext } from './context.js';
5
6
  import type { ListitemProps } from './types.js';
6
7
  import Badge from '../../badge/Badge.svelte';
7
8
 
@@ -11,19 +12,78 @@
11
12
  headline = '',
12
13
  supporting = '',
13
14
  trailing,
15
+ trailingText,
14
16
  badge,
15
17
  selected,
18
+ disabled = false,
19
+ children,
20
+ expanded = $bindable(false),
16
21
  class: className,
17
22
  asChild = false,
18
23
  lines = overline && supporting ? 3 : overline || supporting ? 2 : 1,
19
24
  ...restProps
20
25
  }: ListitemProps = $props();
21
26
 
22
- const cls = $derived(listiem({ lines, selected }));
23
- const baseCls = $derived(cls.base({ class: clsx(className) }));
27
+ const uid = $props.id();
28
+ const ctx = getListContext();
29
+
30
+ const rest = $derived(restProps as Record<string, unknown>);
31
+ const expandable = $derived(!!children);
32
+ // Expandable items are always a button; otherwise the props pick the element.
33
+ const tag = $derived(
34
+ expandable || 'onclick' in rest
35
+ ? 'button'
36
+ : 'label' in rest
37
+ ? 'label'
38
+ : rest.href != null && rest.href !== ''
39
+ ? 'a'
40
+ : 'div'
41
+ );
42
+ const isOption = $derived(rest.role === 'option');
43
+ const interactive = $derived(!disabled && (tag !== 'div' || isOption));
44
+
45
+ const cls = $derived(
46
+ listItem({
47
+ lines,
48
+ selected: !!selected,
49
+ disabled,
50
+ interactive,
51
+ variant: ctx?.variant ?? 'standard',
52
+ expanded: expandable ? expanded : undefined
53
+ })
54
+ );
55
+
56
+ const attrs = $derived.by(() => {
57
+ const { label: _, href, onclick, ...extra } = rest;
58
+ const a: Record<string, unknown> = { ...extra };
59
+ if (tag === 'button') {
60
+ a.type = 'button';
61
+ a.disabled = disabled;
62
+ a.onclick = (e: MouseEvent) => {
63
+ (onclick as ((e: MouseEvent) => void) | undefined)?.(e);
64
+ if (expandable && !e.defaultPrevented) expanded = !expanded;
65
+ };
66
+ if (expandable) {
67
+ a['aria-expanded'] = expanded;
68
+ a['aria-controls'] = `${uid}-nested`;
69
+ } else if (selected !== undefined && !isOption) a['aria-pressed'] = selected;
70
+ } else if (tag === 'a') {
71
+ // A disabled link has no href, so it's not focusable or followable.
72
+ if (disabled) {
73
+ a.role = 'link';
74
+ a['aria-disabled'] = true;
75
+ } else a.href = href;
76
+ if (selected) a['aria-current'] = 'page';
77
+ } else if (disabled) a['aria-disabled'] = true;
78
+ if (isOption) a['aria-selected'] = !!selected;
79
+ return a;
80
+ });
24
81
  </script>
25
82
 
26
83
  {#snippet content()}
84
+ {#if interactive}
85
+ <Layer />
86
+ {/if}
27
87
  {#if leading}
28
88
  <div class={cls.leading()}>
29
89
  {@render leading()}
@@ -38,54 +98,49 @@
38
98
  <p class={cls.supporting()}>{supporting}</p>
39
99
  {/if}
40
100
  </div>
41
- {#if trailing || badge !== undefined}
42
- <div class={clsx(cls.trailing(), 'relative overflow-visible')}>
43
- {#if trailing}
44
- {@render trailing()}
101
+ {#if trailing || trailingText || badge !== undefined || expandable}
102
+ <div class={cls.trailing()}>
103
+ {#if trailingText}
104
+ <span class={cls.trailingText()}>{trailingText}</span>
45
105
  {/if}
106
+ {@render trailing?.()}
46
107
  {#if badge !== undefined}
47
108
  <Badge
48
109
  size={badge === true ? 'sm' : 'lg'}
49
110
  number={badge === true ? undefined : (badge as number)}
111
+ standalone
50
112
  />
51
113
  {/if}
114
+ {#if expandable}
115
+ <span class={cls.expandIcon()} aria-hidden="true">
116
+ <Icon name="keyboard_arrow_down" size="sm" />
117
+ </span>
118
+ {/if}
52
119
  </div>
53
120
  {/if}
54
121
  {/snippet}
55
122
 
56
- {#snippet action()}
57
- {#if 'label' in restProps}
58
- {@const { label: _, ...extra } = restProps}
59
- <label class={baseCls} {...extra}>
60
- <Layer />
61
- {@render content()}
62
- </label>
63
- {:else if 'onclick' in restProps}
64
- <button type="button" class={baseCls} {...restProps}>
65
- <Layer />
66
- {@render content()}
67
- </button>
68
- {:else if 'href' in restProps && restProps.href != null && restProps.href !== ''}
69
- {@const { href, ...extra } = restProps as typeof restProps & {
70
- href?: string | null;
71
- }}
72
- <a class={baseCls} {href} {...extra}>
73
- <Layer />
74
- {@render content()}
75
- </a>
76
- {:else}
77
- {@const { href: _, ...extra } = restProps as Record<string, unknown>}
78
- <div class={baseCls} {...extra}>
79
- <Layer />
80
- {@render content()}
123
+ {#snippet item()}
124
+ <svelte:element this={tag} class={cls.base({ class: clsx(className) })} {...attrs}>
125
+ {@render content()}
126
+ </svelte:element>
127
+ {#if children}
128
+ <div class={cls.region()} inert={!expanded}>
129
+ <div class={cls.regionInner()}>
130
+ <ul id="{uid}-nested" class={cls.nested()}>
131
+ {@render children()}
132
+ </ul>
133
+ </div>
81
134
  </div>
82
135
  {/if}
83
136
  {/snippet}
84
137
 
85
- {#if asChild}
86
- {@render action()}
138
+ {#if asChild && !expandable}
139
+ {@render item()}
140
+ {:else if asChild}
141
+ <div class={cls.group()}>{@render item()}</div>
87
142
  {:else}
88
- <li>
89
- {@render action()}
143
+ <li class={expandable ? cls.group() : undefined}>
144
+ {@render item()}
90
145
  </li>
91
146
  {/if}
@@ -1,4 +1,4 @@
1
1
  import type { ListitemProps } from './types.js';
2
- declare const ListItem: import("svelte").Component<ListitemProps, {}, "">;
2
+ declare const ListItem: import("svelte").Component<ListitemProps, {}, "expanded">;
3
3
  type ListItem = ReturnType<typeof ListItem>;
4
4
  export default ListItem;
@@ -0,0 +1,6 @@
1
+ type ListContext = {
2
+ readonly variant: 'standard' | 'segmented';
3
+ };
4
+ export declare const setListContext: (ctx: ListContext) => ListContext;
5
+ export declare const getListContext: () => ListContext | undefined;
6
+ export {};
@@ -0,0 +1,4 @@
1
+ import { getContext, setContext } from 'svelte';
2
+ const KEY = Symbol('list');
3
+ export const setListContext = (ctx) => setContext(KEY, ctx);
4
+ export const getListContext = () => getContext(KEY);
@@ -1,3 +1,4 @@
1
1
  export * from './theme.js';
2
2
  export * from './types.js';
3
+ export { default as List } from './List.svelte';
3
4
  export { default as ListItem } from './ListItem.svelte';
@@ -3,4 +3,5 @@
3
3
  export * from './theme.js';
4
4
  export * from './types.js';
5
5
  // default exports for components in this folder
6
+ export { default as List } from './List.svelte';
6
7
  export { default as ListItem } from './ListItem.svelte';