@fpkit/acss 0.5.13 → 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 (280) hide show
  1. package/libs/{chunk-PQ2K3BM6.cjs → chunk-2NRIP6RB.cjs} +3 -3
  2. package/libs/chunk-33PNJ4LO.cjs +15 -0
  3. package/libs/chunk-33PNJ4LO.cjs.map +1 -0
  4. package/libs/chunk-4BZKFPEC.cjs +17 -0
  5. package/libs/chunk-4BZKFPEC.cjs.map +1 -0
  6. package/libs/{chunk-772NRB75.js → chunk-5QD3DWFI.js} +2 -2
  7. package/libs/chunk-6SAHIYCZ.js +7 -0
  8. package/libs/chunk-6SAHIYCZ.js.map +1 -0
  9. package/libs/{chunk-3MKLDCKQ.cjs → chunk-6WTC4JXH.cjs} +3 -3
  10. package/libs/chunk-75QHTLFO.js +7 -0
  11. package/libs/chunk-75QHTLFO.js.map +1 -0
  12. package/libs/{chunk-ZANSFMTD.js → chunk-7XPFW7CB.js} +3 -3
  13. package/libs/chunk-BFK62VX5.js +5 -0
  14. package/libs/chunk-BFK62VX5.js.map +1 -0
  15. package/libs/{chunk-ROZI23GS.cjs → chunk-DKTHCQ5P.cjs} +4 -4
  16. package/libs/chunk-E2AJURUW.cjs +13 -0
  17. package/libs/chunk-E2AJURUW.cjs.map +1 -0
  18. package/libs/{chunk-L75OQKEI.cjs → chunk-ENTCUJ3A.cjs} +3 -3
  19. package/libs/chunk-ENTCUJ3A.cjs.map +1 -0
  20. package/libs/chunk-F5EYMVQM.js +10 -0
  21. package/libs/chunk-F5EYMVQM.js.map +1 -0
  22. package/libs/chunk-FVROL3V5.js +9 -0
  23. package/libs/chunk-FVROL3V5.js.map +1 -0
  24. package/libs/chunk-GT77BX4L.cjs +17 -0
  25. package/libs/chunk-GT77BX4L.cjs.map +1 -0
  26. package/libs/chunk-GUJSMQ3V.cjs +16 -0
  27. package/libs/chunk-GUJSMQ3V.cjs.map +1 -0
  28. package/libs/chunk-HHLNOC5T.js +7 -0
  29. package/libs/chunk-HHLNOC5T.js.map +1 -0
  30. package/libs/chunk-HRRHPLER.js +8 -0
  31. package/libs/chunk-HRRHPLER.js.map +1 -0
  32. package/libs/chunk-IEB64SWY.js +8 -0
  33. package/libs/chunk-IEB64SWY.js.map +1 -0
  34. package/libs/{chunk-NGTJDDFO.js → chunk-IQ76HGVP.js} +2 -2
  35. package/libs/chunk-IRLFZ3OL.js +9 -0
  36. package/libs/chunk-IRLFZ3OL.js.map +1 -0
  37. package/libs/{chunk-JJ43O4Y5.js → chunk-KK47SYZI.js} +2 -2
  38. package/libs/chunk-O3JIHC5M.cjs +15 -0
  39. package/libs/chunk-O3JIHC5M.cjs.map +1 -0
  40. package/libs/chunk-O5XAJ7BY.cjs +18 -0
  41. package/libs/chunk-O5XAJ7BY.cjs.map +1 -0
  42. package/libs/chunk-OVWLQYMK.js +10 -0
  43. package/libs/chunk-OVWLQYMK.js.map +1 -0
  44. package/libs/chunk-PNWIRCG3.cjs +7 -0
  45. package/libs/chunk-PNWIRCG3.cjs.map +1 -0
  46. package/libs/{chunk-D4YLRWAO.cjs → chunk-QVW6W76L.cjs} +6 -6
  47. package/libs/chunk-T4T6GWYQ.cjs +17 -0
  48. package/libs/chunk-T4T6GWYQ.cjs.map +1 -0
  49. package/libs/chunk-TON2YGMD.cjs +9 -0
  50. package/libs/chunk-TON2YGMD.cjs.map +1 -0
  51. package/libs/chunk-UEPAWMDF.js +8 -0
  52. package/libs/chunk-UEPAWMDF.js.map +1 -0
  53. package/libs/{chunk-LT5KZ2QW.cjs → chunk-US2I5GI7.cjs} +3 -3
  54. package/libs/{chunk-B7F5FS6D.cjs → chunk-W2UIN7EV.cjs} +3 -3
  55. package/libs/{chunk-P2DC76ZZ.cjs → chunk-W5TKWBFC.cjs} +3 -3
  56. package/libs/chunk-WXBFBWYF.cjs +16 -0
  57. package/libs/chunk-WXBFBWYF.cjs.map +1 -0
  58. package/libs/{chunk-VUH3FXGJ.js → chunk-X3JCTEPD.js} +5 -5
  59. package/libs/chunk-X5LGFCWG.js +9 -0
  60. package/libs/chunk-X5LGFCWG.js.map +1 -0
  61. package/libs/{chunk-5M57K4SW.js → chunk-Y2PFDELK.js} +2 -2
  62. package/libs/{chunk-ETFLFC2S.js → chunk-ZFJ4U45S.js} +2 -2
  63. package/libs/{component-props-a8a2f97e.d.ts → component-props-67d978a2.d.ts} +4 -4
  64. package/libs/components/alert/alert.css +1 -1
  65. package/libs/components/alert/alert.css.map +1 -1
  66. package/libs/components/alert/alert.min.css +2 -2
  67. package/libs/components/breadcrumbs/breadcrumb.cjs +6 -6
  68. package/libs/components/breadcrumbs/breadcrumb.d.cts +11 -11
  69. package/libs/components/breadcrumbs/breadcrumb.d.ts +11 -11
  70. package/libs/components/breadcrumbs/breadcrumb.js +3 -3
  71. package/libs/components/button.cjs +6 -4
  72. package/libs/components/button.d.cts +97 -4
  73. package/libs/components/button.d.ts +97 -4
  74. package/libs/components/button.js +4 -2
  75. package/libs/components/card.cjs +7 -7
  76. package/libs/components/card.d.cts +14 -14
  77. package/libs/components/card.d.ts +14 -14
  78. package/libs/components/card.js +2 -2
  79. package/libs/components/dialog/dialog.cjs +9 -7
  80. package/libs/components/dialog/dialog.d.cts +3 -3
  81. package/libs/components/dialog/dialog.d.ts +3 -3
  82. package/libs/components/dialog/dialog.js +7 -5
  83. package/libs/components/form/fields.cjs +4 -4
  84. package/libs/components/form/fields.d.cts +16 -7
  85. package/libs/components/form/fields.d.ts +16 -7
  86. package/libs/components/form/fields.js +2 -2
  87. package/libs/components/form/inputs.cjs +6 -4
  88. package/libs/components/form/inputs.d.cts +50 -2
  89. package/libs/components/form/inputs.d.ts +50 -2
  90. package/libs/components/form/inputs.js +4 -2
  91. package/libs/components/form/textarea.cjs +5 -4
  92. package/libs/components/form/textarea.d.cts +32 -23
  93. package/libs/components/form/textarea.d.ts +32 -23
  94. package/libs/components/form/textarea.js +3 -2
  95. package/libs/components/heading/heading.cjs +3 -3
  96. package/libs/components/heading/heading.d.cts +2 -2
  97. package/libs/components/heading/heading.d.ts +2 -2
  98. package/libs/components/heading/heading.js +2 -2
  99. package/libs/components/icons/icon.cjs +4 -4
  100. package/libs/components/icons/icon.d.cts +38 -38
  101. package/libs/components/icons/icon.d.ts +38 -38
  102. package/libs/components/icons/icon.js +2 -2
  103. package/libs/components/link/link.cjs +4 -4
  104. package/libs/components/link/link.css +1 -1
  105. package/libs/components/link/link.css.map +1 -1
  106. package/libs/components/link/link.d.cts +3 -19
  107. package/libs/components/link/link.d.ts +3 -19
  108. package/libs/components/link/link.js +2 -2
  109. package/libs/components/link/link.min.css +2 -2
  110. package/libs/components/list/list.cjs +5 -5
  111. package/libs/components/list/list.css +1 -0
  112. package/libs/components/list/list.css.map +1 -0
  113. package/libs/components/list/list.d.cts +120 -33
  114. package/libs/components/list/list.d.ts +120 -33
  115. package/libs/components/list/list.js +2 -2
  116. package/libs/components/list/list.min.css +3 -0
  117. package/libs/components/modal.cjs +6 -4
  118. package/libs/components/modal.d.cts +8 -8
  119. package/libs/components/modal.d.ts +8 -8
  120. package/libs/components/modal.js +5 -3
  121. package/libs/components/nav/nav.cjs +7 -7
  122. package/libs/components/nav/nav.css +1 -1
  123. package/libs/components/nav/nav.css.map +1 -1
  124. package/libs/components/nav/nav.d.cts +550 -34
  125. package/libs/components/nav/nav.d.ts +550 -34
  126. package/libs/components/nav/nav.js +3 -3
  127. package/libs/components/nav/nav.min.css +2 -2
  128. package/libs/components/popover/popover.d.cts +5 -5
  129. package/libs/components/popover/popover.d.ts +5 -5
  130. package/libs/components/tables/table.cjs +5 -5
  131. package/libs/components/tables/table.d.cts +8 -8
  132. package/libs/components/tables/table.d.ts +8 -8
  133. package/libs/components/tables/table.js +2 -2
  134. package/libs/components/tag/tag.css +1 -1
  135. package/libs/components/tag/tag.css.map +1 -1
  136. package/libs/components/tag/tag.min.css +2 -2
  137. package/libs/components/text/text.cjs +5 -5
  138. package/libs/components/text/text.d.cts +5 -5
  139. package/libs/components/text/text.d.ts +5 -5
  140. package/libs/components/text/text.js +2 -2
  141. package/libs/form.types-d25ebfac.d.ts +233 -0
  142. package/libs/{heading-3648c538.d.ts → heading-7446cb46.d.ts} +8 -8
  143. package/libs/hooks.cjs +9 -4
  144. package/libs/hooks.d.cts +137 -3
  145. package/libs/hooks.d.ts +137 -3
  146. package/libs/hooks.js +4 -3
  147. package/libs/icons.cjs +3 -3
  148. package/libs/icons.d.cts +2 -2
  149. package/libs/icons.d.ts +2 -2
  150. package/libs/icons.js +2 -2
  151. package/libs/index.cjs +53 -51
  152. package/libs/index.cjs.map +1 -1
  153. package/libs/index.css +1 -1
  154. package/libs/index.css.map +1 -1
  155. package/libs/index.d.cts +338 -49
  156. package/libs/index.d.ts +338 -49
  157. package/libs/index.js +24 -22
  158. package/libs/index.js.map +1 -1
  159. package/libs/link-5192f411.d.ts +323 -0
  160. package/libs/list.types-d26de310.d.ts +245 -0
  161. package/libs/{ui-645f95b5.d.ts → ui-d01b50d4.d.ts} +16 -12
  162. package/package.json +4 -6
  163. package/src/components/alert/alert.scss +1 -4
  164. package/src/components/breadcrumbs/breadcrumb.tsx +4 -1
  165. package/src/components/buttons/README.mdx +102 -1
  166. package/src/components/buttons/button.stories.tsx +106 -0
  167. package/src/components/buttons/button.tsx +82 -52
  168. package/src/components/dialog/dialog-a11y-review.md +653 -0
  169. package/src/components/form/README.mdx +725 -43
  170. package/src/components/form/WCAG-REVIEW.md +654 -0
  171. package/src/components/form/fields.tsx +10 -1
  172. package/src/components/form/form.stories.tsx +604 -23
  173. package/src/components/form/form.tsx +204 -63
  174. package/src/components/form/form.types.ts +378 -0
  175. package/src/components/form/input.stories.tsx +71 -3
  176. package/src/components/form/inputs.tsx +159 -67
  177. package/src/components/form/select.tsx +122 -66
  178. package/src/components/form/textarea.tsx +120 -73
  179. package/src/components/fp.tsx +86 -11
  180. package/src/components/link/README.mdx +923 -0
  181. package/src/components/link/link.scss +79 -26
  182. package/src/components/link/link.stories.tsx +383 -30
  183. package/src/components/link/link.test.tsx +677 -0
  184. package/src/components/link/link.tsx +163 -57
  185. package/src/components/link/link.types.ts +261 -0
  186. package/src/components/list/README.mdx +764 -0
  187. package/src/components/list/list.scss +285 -0
  188. package/src/components/list/list.stories.tsx +514 -27
  189. package/src/components/list/list.test.tsx +554 -0
  190. package/src/components/list/list.tsx +153 -51
  191. package/src/components/list/list.types.ts +255 -0
  192. package/src/components/nav/ACCESSIBILITY.md +649 -0
  193. package/src/components/nav/README.mdx +782 -0
  194. package/src/components/nav/nav.scss +32 -1
  195. package/src/components/nav/nav.stories.tsx +44 -6
  196. package/src/components/nav/nav.tsx +302 -51
  197. package/src/components/nav/nav.types.ts +308 -0
  198. package/src/components/tag/README.mdx +426 -0
  199. package/src/components/tag/tag.scss +101 -27
  200. package/src/components/tag/tag.stories.tsx +384 -10
  201. package/src/components/tag/tag.test.tsx +210 -0
  202. package/src/components/tag/tag.tsx +106 -9
  203. package/src/components/tag/tag.types.ts +107 -0
  204. package/src/components/ui.tsx +8 -3
  205. package/src/hooks/use-disabled-state.test.tsx +536 -0
  206. package/src/hooks/use-disabled-state.ts +246 -0
  207. package/src/hooks/useDisabledState.md +393 -0
  208. package/src/hooks.ts +6 -0
  209. package/src/index.scss +2 -0
  210. package/src/index.ts +2 -1
  211. package/src/sass/_globals.scss +2 -7
  212. package/src/styles/alert/alert.css +1 -3
  213. package/src/styles/alert/alert.css.map +1 -1
  214. package/src/styles/index.css +450 -76
  215. package/src/styles/index.css.map +1 -1
  216. package/src/styles/link/link.css +45 -28
  217. package/src/styles/link/link.css.map +1 -1
  218. package/src/styles/list/list.css +214 -0
  219. package/src/styles/list/list.css.map +1 -0
  220. package/src/styles/nav/nav.css +21 -1
  221. package/src/styles/nav/nav.css.map +1 -1
  222. package/src/styles/tag/tag.css +113 -35
  223. package/src/styles/tag/tag.css.map +1 -1
  224. package/src/styles/utilities/_disabled.scss +58 -0
  225. package/src/types/shared.ts +43 -6
  226. package/src/utils/accessibility.ts +109 -0
  227. package/libs/chunk-2LTJ7HHX.cjs +0 -18
  228. package/libs/chunk-2LTJ7HHX.cjs.map +0 -1
  229. package/libs/chunk-2Y7W75TT.js +0 -9
  230. package/libs/chunk-2Y7W75TT.js.map +0 -1
  231. package/libs/chunk-5S4ORA4C.cjs +0 -15
  232. package/libs/chunk-5S4ORA4C.cjs.map +0 -1
  233. package/libs/chunk-AHDJGCG5.cjs +0 -15
  234. package/libs/chunk-AHDJGCG5.cjs.map +0 -1
  235. package/libs/chunk-BHRQBJRY.js +0 -8
  236. package/libs/chunk-BHRQBJRY.js.map +0 -1
  237. package/libs/chunk-GZ4QFPRY.js +0 -9
  238. package/libs/chunk-GZ4QFPRY.js.map +0 -1
  239. package/libs/chunk-IYUN2EW3.cjs +0 -15
  240. package/libs/chunk-IYUN2EW3.cjs.map +0 -1
  241. package/libs/chunk-J32EZPYD.cjs +0 -15
  242. package/libs/chunk-J32EZPYD.cjs.map +0 -1
  243. package/libs/chunk-KUKIVRC2.js +0 -7
  244. package/libs/chunk-KUKIVRC2.js.map +0 -1
  245. package/libs/chunk-L75OQKEI.cjs.map +0 -1
  246. package/libs/chunk-M5RRNTVX.cjs +0 -15
  247. package/libs/chunk-M5RRNTVX.cjs.map +0 -1
  248. package/libs/chunk-OK5QEIMD.cjs +0 -17
  249. package/libs/chunk-OK5QEIMD.cjs.map +0 -1
  250. package/libs/chunk-P7TTEYCD.js +0 -7
  251. package/libs/chunk-P7TTEYCD.js.map +0 -1
  252. package/libs/chunk-QLZWHAMK.js +0 -8
  253. package/libs/chunk-QLZWHAMK.js.map +0 -1
  254. package/libs/chunk-RIVUMPOG.js +0 -8
  255. package/libs/chunk-RIVUMPOG.js.map +0 -1
  256. package/libs/chunk-S7BABR7Z.cjs +0 -13
  257. package/libs/chunk-S7BABR7Z.cjs.map +0 -1
  258. package/libs/chunk-SMYRLO3E.js +0 -8
  259. package/libs/chunk-SMYRLO3E.js.map +0 -1
  260. package/libs/chunk-TYRCEX2L.js +0 -8
  261. package/libs/chunk-TYRCEX2L.js.map +0 -1
  262. package/libs/chunk-XBA562WW.js +0 -8
  263. package/libs/chunk-XBA562WW.js.map +0 -1
  264. package/libs/chunk-XTQKWY7W.cjs +0 -32
  265. package/libs/chunk-XTQKWY7W.cjs.map +0 -1
  266. package/libs/inputs-f3a216db.d.ts +0 -45
  267. /package/libs/{chunk-PQ2K3BM6.cjs.map → chunk-2NRIP6RB.cjs.map} +0 -0
  268. /package/libs/{chunk-772NRB75.js.map → chunk-5QD3DWFI.js.map} +0 -0
  269. /package/libs/{chunk-3MKLDCKQ.cjs.map → chunk-6WTC4JXH.cjs.map} +0 -0
  270. /package/libs/{chunk-ZANSFMTD.js.map → chunk-7XPFW7CB.js.map} +0 -0
  271. /package/libs/{chunk-ROZI23GS.cjs.map → chunk-DKTHCQ5P.cjs.map} +0 -0
  272. /package/libs/{chunk-NGTJDDFO.js.map → chunk-IQ76HGVP.js.map} +0 -0
  273. /package/libs/{chunk-JJ43O4Y5.js.map → chunk-KK47SYZI.js.map} +0 -0
  274. /package/libs/{chunk-D4YLRWAO.cjs.map → chunk-QVW6W76L.cjs.map} +0 -0
  275. /package/libs/{chunk-LT5KZ2QW.cjs.map → chunk-US2I5GI7.cjs.map} +0 -0
  276. /package/libs/{chunk-B7F5FS6D.cjs.map → chunk-W2UIN7EV.cjs.map} +0 -0
  277. /package/libs/{chunk-P2DC76ZZ.cjs.map → chunk-W5TKWBFC.cjs.map} +0 -0
  278. /package/libs/{chunk-VUH3FXGJ.js.map → chunk-X3JCTEPD.js.map} +0 -0
  279. /package/libs/{chunk-5M57K4SW.js.map → chunk-Y2PFDELK.js.map} +0 -0
  280. /package/libs/{chunk-ETFLFC2S.js.map → chunk-ZFJ4U45S.js.map} +0 -0
@@ -1,60 +1,148 @@
1
- import * as React from 'react'
2
- import UI from '../ui'
1
+ import UI from "#components/ui";
2
+ import React from "react";
3
+ import type { ListProps, ListItemProps } from "./list.types";
3
4
 
4
- type ListProps = {
5
- /** Type of list to render (default: 'ul') */
6
- type?: 'ul' | 'ol' | 'dl'
7
- /** variant of list to render (default: 'none') */
8
- variant?: string
9
- } & React.ComponentProps<typeof UI>
10
-
11
- export type ListItemProps = {
12
- /** Type of list item to render (default: 'li') */
13
- type?: 'li' | 'dt' | 'dd'
14
- } & React.ComponentProps<typeof UI>
5
+ // Re-export types for external use
6
+ export type { ListProps, ListItemProps };
15
7
 
16
8
  /**
17
- * ListItem component
18
- * @param type - HTML tag type for the list item (default: 'li')
19
- * @param styles - CSS styles object
20
- * @param children - Child elements to be rendered inside the list item
21
- * @param props - Additional props to be passed to the underlying HTML element
22
- * @returns A React component that renders a list item
9
+ * ListItem - A flexible list item component for ul, ol, and dl lists.
10
+ *
11
+ * This component renders different HTML elements (li, dt, dd) based on the parent
12
+ * list type, maintaining semantic HTML and accessibility best practices.
13
+ *
14
+ * ## Key Features:
15
+ * - **Semantic HTML**: Renders appropriate element type (li, dt, dd)
16
+ * - **Type-Safe**: Full TypeScript support with comprehensive props
17
+ * - **Ref Forwarding**: Enables direct DOM access for focus management
18
+ * - **Customizable**: Supports custom styles and CSS classes
19
+ *
20
+ * ## Accessibility:
21
+ * - ✅ Uses semantic HTML elements
22
+ * - ✅ Works with screen readers out of the box
23
+ * - ✅ Supports all native HTML attributes
24
+ * - ✅ Ref forwarding for programmatic focus
25
+ *
26
+ * @example
27
+ * ```tsx
28
+ * // Standard list item
29
+ * <ListItem>Item content</ListItem>
30
+ * ```
31
+ *
32
+ * @example
33
+ * ```tsx
34
+ * // Definition term
35
+ * <ListItem type="dt">Term to define</ListItem>
36
+ * ```
37
+ *
38
+ * @example
39
+ * ```tsx
40
+ * // Definition description
41
+ * <ListItem type="dd">The definition text</ListItem>
42
+ * ```
43
+ *
44
+ * @param {ListItemProps} props - Component props
45
+ * @param {React.Ref} ref - Forwarded ref for DOM access
46
+ * @returns {React.ReactElement} A list item element
23
47
  */
24
- export const ListItem = ({
25
- type = 'li',
26
- id,
27
- styles,
28
- children,
29
- classes,
30
- ...props
31
- }: ListItemProps) => {
48
+ export const ListItem = React.forwardRef<
49
+ HTMLLIElement | HTMLElement,
50
+ ListItemProps
51
+ >(({ type = "li", id, styles, children, classes, ...props }, ref) => {
32
52
  return (
33
- <UI id={id} as={type} className={classes} {...props} style={styles}>
53
+ <UI
54
+ id={id}
55
+ as={type}
56
+ className={classes}
57
+ style={styles}
58
+ ref={ref}
59
+ {...props}
60
+ >
34
61
  {children}
35
62
  </UI>
36
- )
37
- }
63
+ );
64
+ });
65
+
66
+ ListItem.displayName = "ListItem";
38
67
 
39
68
  /**
40
- * List component renders a list element with provided props
41
- * @param children - Child elements to render inside the list
42
- * @param classes - CSS classes to apply
43
- * @param type - Type of list element (default: 'ul')
44
- * @param variant - Variant for styling purposes
45
- * @param styles - Inline styles object
46
- * @param role - ARIA role
47
- * @param props - Additional props to pass to underlying element
69
+ * List - A flexible, accessible list component for creating ul, ol, and dl lists.
70
+ *
71
+ * This component provides a type-safe, accessible way to create different types of lists
72
+ * with built-in support for custom styling, variants, and WCAG 2.1 AA compliance.
73
+ *
74
+ * ## Key Features:
75
+ * - **Multiple List Types**: Supports ul (unordered), ol (ordered), and dl (definition) lists
76
+ * - **Semantic HTML**: Uses native HTML list elements for proper accessibility
77
+ * - **Customizable Styling**: CSS custom properties and variant support
78
+ * - **Type-Safe**: Comprehensive TypeScript types with JSDoc
79
+ * - **Ref Forwarding**: Direct DOM access for scroll positioning and focus management
80
+ * - **WCAG 2.1 AA**: Meets accessibility standards with proper semantic structure
81
+ *
82
+ * ## Accessibility:
83
+ * - ✅ WCAG 2.1 AA compliant using semantic HTML
84
+ * - ✅ Screen reader compatible (announced as "list" with item count)
85
+ * - ✅ Supports role="list" override for styled lists (Safari/VoiceOver compatibility)
86
+ * - ✅ Keyboard navigation works naturally with focusable children
87
+ * - ✅ Ref forwarding for programmatic focus management
88
+ *
89
+ * ## Common Use Cases:
90
+ * - **Navigation menus** - Use ul with variant="inline" or "none"
91
+ * - **Sequential steps** - Use ol for numbered instructions
92
+ * - **Glossaries** - Use dl for term-definition pairs
93
+ * - **Feature lists** - Use ul for product features
94
+ *
95
+ * @example
96
+ * ```tsx
97
+ * // Basic unordered list
98
+ * <List>
99
+ * <List.ListItem>First item</List.ListItem>
100
+ * <List.ListItem>Second item</List.ListItem>
101
+ * </List>
102
+ * ```
103
+ *
104
+ * @example
105
+ * ```tsx
106
+ * // Ordered list with custom styling
107
+ * <List
108
+ * type="ol"
109
+ * variant="numbered"
110
+ * styles={{ '--list-marker-color': '#0066cc' }}
111
+ * >
112
+ * <List.ListItem>Step one</List.ListItem>
113
+ * <List.ListItem>Step two</List.ListItem>
114
+ * </List>
115
+ * ```
116
+ *
117
+ * @example
118
+ * ```tsx
119
+ * // Unstyled list with role restoration for accessibility
120
+ * // IMPORTANT: Use role="list" when removing list styling
121
+ * <List variant="none" role="list">
122
+ * <List.ListItem>Navigation link</List.ListItem>
123
+ * <List.ListItem>Another link</List.ListItem>
124
+ * </List>
125
+ * ```
126
+ *
127
+ * @example
128
+ * ```tsx
129
+ * // Definition list
130
+ * <List type="dl">
131
+ * <List.ListItem type="dt">React</List.ListItem>
132
+ * <List.ListItem type="dd">A JavaScript library for building UIs</List.ListItem>
133
+ * <List.ListItem type="dt">TypeScript</List.ListItem>
134
+ * <List.ListItem type="dd">JavaScript with syntax for types</List.ListItem>
135
+ * </List>
136
+ * ```
137
+ *
138
+ * @param {ListProps} props - Component props
139
+ * @param {React.Ref} ref - Forwarded ref for DOM access
140
+ * @returns {React.ReactElement} A list element (ul, ol, or dl)
48
141
  */
49
- export const List = ({
50
- children,
51
- classes,
52
- type = 'ul',
53
- variant,
54
- styles,
55
- role,
56
- ...props
57
- }: ListProps) => {
142
+ export const List = React.forwardRef<
143
+ HTMLUListElement | HTMLOListElement | HTMLDListElement,
144
+ ListProps
145
+ >(({ children, classes, type = "ul", variant, styles, role, ...props }, ref) => {
58
146
  return (
59
147
  <UI
60
148
  as={type}
@@ -62,13 +150,27 @@ export const List = ({
62
150
  className={classes}
63
151
  style={styles}
64
152
  role={role}
153
+ ref={ref}
65
154
  {...props}
66
155
  >
67
156
  {children}
68
157
  </UI>
69
- )
158
+ );
159
+ });
160
+
161
+ List.displayName = "List";
162
+
163
+ // Compound component pattern - attach ListItem to List with proper typing
164
+ export interface ListComponent
165
+ extends React.ForwardRefExoticComponent<
166
+ ListProps & React.RefAttributes<HTMLUListElement | HTMLOListElement | HTMLDListElement>
167
+ > {
168
+ ListItem: typeof ListItem;
70
169
  }
71
170
 
72
- export default List
73
- List.displayName = 'List'
74
- List.ListItem = ListItem
171
+ // Attach ListItem to List using Object.assign for better type inference
172
+ const ListWithItem = Object.assign(List, {
173
+ ListItem,
174
+ });
175
+
176
+ export default ListWithItem as ListComponent;
@@ -0,0 +1,255 @@
1
+ import React from "react";
2
+ import UI from "#components/ui";
3
+
4
+ /**
5
+ * Props for the List component.
6
+ *
7
+ * Combines native HTML list element props with custom styling and accessibility features.
8
+ * The List component provides a flexible, type-safe way to create ordered, unordered,
9
+ * and definition lists with built-in accessibility support and customizable styling.
10
+ *
11
+ * @example
12
+ * ```tsx
13
+ * // Unordered list (default)
14
+ * <List>
15
+ * <List.ListItem>Item 1</List.ListItem>
16
+ * <List.ListItem>Item 2</List.ListItem>
17
+ * </List>
18
+ * ```
19
+ *
20
+ * @example
21
+ * ```tsx
22
+ * // Ordered list with custom styling
23
+ * <List
24
+ * type="ol"
25
+ * variant="numbered"
26
+ * styles={{ '--list-marker-color': 'blue' }}
27
+ * >
28
+ * <List.ListItem>First step</List.ListItem>
29
+ * <List.ListItem>Second step</List.ListItem>
30
+ * </List>
31
+ * ```
32
+ *
33
+ * @example
34
+ * ```tsx
35
+ * // Definition list
36
+ * <List type="dl">
37
+ * <List.ListItem type="dt">Term</List.ListItem>
38
+ * <List.ListItem type="dd">Definition</List.ListItem>
39
+ * </List>
40
+ * ```
41
+ */
42
+ export type ListProps = {
43
+ /**
44
+ * Type of list element to render.
45
+ *
46
+ * - `'ul'` - Unordered list (default) - Use for items where order doesn't matter
47
+ * - `'ol'` - Ordered list - Use for sequential steps or ranked items
48
+ * - `'dl'` - Definition list - Use for term-definition pairs
49
+ *
50
+ * @default 'ul'
51
+ * @example
52
+ * ```tsx
53
+ * type="ol" // Renders an ordered list with numbers
54
+ * type="dl" // Renders a definition list
55
+ * ```
56
+ */
57
+ type?: "ul" | "ol" | "dl";
58
+
59
+ /**
60
+ * Variant for custom styling through CSS.
61
+ * Applied as `data-variant` attribute for CSS targeting.
62
+ *
63
+ * Common variants might include:
64
+ * - `'inline'` - Display items horizontally
65
+ * - `'none'` - Remove list markers
66
+ * - `'custom'` - Custom marker styling
67
+ *
68
+ * @optional
69
+ * @example
70
+ * ```tsx
71
+ * variant="inline" // Horizontal list for navigation
72
+ * variant="none" // Clean list without bullets
73
+ * ```
74
+ */
75
+ variant?: string;
76
+
77
+ /**
78
+ * ARIA role override.
79
+ *
80
+ * Note: Only override the default role when necessary for accessibility.
81
+ * Native list elements have semantic meaning that should be preserved.
82
+ *
83
+ * Use `role="list"` when CSS `list-style: none` is applied, as some screen
84
+ * readers remove list semantics when list styling is removed.
85
+ *
86
+ * @optional
87
+ * @see {@link https://www.scottohara.me/blog/2019/01/12/lists-and-safari.html}
88
+ * @example
89
+ * ```tsx
90
+ * // Restore list semantics when using list-style: none
91
+ * <List variant="none" role="list">
92
+ * <List.ListItem>Navigation item</List.ListItem>
93
+ * </List>
94
+ * ```
95
+ */
96
+ role?: string;
97
+
98
+ /**
99
+ * Inline CSS styles to apply to the list element.
100
+ * Can include CSS custom properties for theming.
101
+ *
102
+ * @optional
103
+ * @example
104
+ * ```tsx
105
+ * styles={{
106
+ * '--list-gap': '1rem',
107
+ * '--list-marker-color': '#0066cc'
108
+ * }}
109
+ * ```
110
+ */
111
+ styles?: React.CSSProperties;
112
+
113
+ /**
114
+ * CSS class names to apply to the list element.
115
+ *
116
+ * @optional
117
+ * @example
118
+ * ```tsx
119
+ * classes="navigation-list"
120
+ * ```
121
+ */
122
+ classes?: string;
123
+
124
+ /**
125
+ * HTML id attribute for the list element.
126
+ *
127
+ * @optional
128
+ * @example
129
+ * ```tsx
130
+ * id="main-navigation"
131
+ * ```
132
+ */
133
+ id?: string;
134
+
135
+ /**
136
+ * Accessible label for screen readers.
137
+ *
138
+ * Use when the list's purpose isn't clear from context or when
139
+ * multiple lists exist on the page.
140
+ *
141
+ * @optional
142
+ * @example
143
+ * ```tsx
144
+ * aria-label="Product features"
145
+ * aria-labelledby="features-heading"
146
+ * ```
147
+ */
148
+ "aria-label"?: string;
149
+ "aria-labelledby"?: string;
150
+
151
+ /**
152
+ * Child elements (typically ListItem components).
153
+ *
154
+ * @required
155
+ * @example
156
+ * ```tsx
157
+ * <List>
158
+ * <List.ListItem>Item 1</List.ListItem>
159
+ * <List.ListItem>Item 2</List.ListItem>
160
+ * </List>
161
+ * ```
162
+ */
163
+ children: React.ReactNode;
164
+ } & Partial<React.ComponentProps<typeof UI>>;
165
+
166
+ /**
167
+ * Props for the ListItem component.
168
+ *
169
+ * Provides a flexible list item that can render as different HTML elements
170
+ * depending on the parent list type (li, dt, dd).
171
+ *
172
+ * @example
173
+ * ```tsx
174
+ * // Standard list item (li) - default
175
+ * <ListItem>Regular item</ListItem>
176
+ * ```
177
+ *
178
+ * @example
179
+ * ```tsx
180
+ * // Definition term (dt)
181
+ * <ListItem type="dt">Term to define</ListItem>
182
+ * ```
183
+ *
184
+ * @example
185
+ * ```tsx
186
+ * // Definition description (dd)
187
+ * <ListItem type="dd">The definition</ListItem>
188
+ * ```
189
+ */
190
+ export type ListItemProps = {
191
+ /**
192
+ * Type of list item element to render.
193
+ *
194
+ * - `'li'` - Standard list item (default) - For ul and ol
195
+ * - `'dt'` - Definition term - For dl (term being defined)
196
+ * - `'dd'` - Definition description - For dl (the definition itself)
197
+ *
198
+ * @default 'li'
199
+ * @example
200
+ * ```tsx
201
+ * // In a definition list
202
+ * <List type="dl">
203
+ * <ListItem type="dt">React</ListItem>
204
+ * <ListItem type="dd">A JavaScript library for building user interfaces</ListItem>
205
+ * </List>
206
+ * ```
207
+ */
208
+ type?: "li" | "dt" | "dd";
209
+
210
+ /**
211
+ * HTML id attribute for the list item.
212
+ *
213
+ * @optional
214
+ * @example
215
+ * ```tsx
216
+ * id="feature-1"
217
+ * ```
218
+ */
219
+ id?: string;
220
+
221
+ /**
222
+ * Inline CSS styles to apply to the list item.
223
+ *
224
+ * @optional
225
+ * @example
226
+ * ```tsx
227
+ * styles={{ paddingLeft: '1rem' }}
228
+ * ```
229
+ */
230
+ styles?: React.CSSProperties;
231
+
232
+ /**
233
+ * CSS class names to apply to the list item.
234
+ *
235
+ * @optional
236
+ * @example
237
+ * ```tsx
238
+ * classes="list-item-active"
239
+ * ```
240
+ */
241
+ classes?: string;
242
+
243
+ /**
244
+ * Child elements to render inside the list item.
245
+ *
246
+ * @required
247
+ * @example
248
+ * ```tsx
249
+ * <ListItem>
250
+ * <strong>Bold text</strong> and regular text
251
+ * </ListItem>
252
+ * ```
253
+ */
254
+ children: React.ReactNode;
255
+ } & Partial<React.ComponentProps<typeof UI>>;