@fpkit/acss 0.5.12 → 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 (398) hide show
  1. package/README.md +89 -0
  2. package/libs/chunk-2NRIP6RB.cjs +17 -0
  3. package/libs/chunk-2NRIP6RB.cjs.map +1 -0
  4. package/libs/chunk-33PNJ4LO.cjs +15 -0
  5. package/libs/chunk-33PNJ4LO.cjs.map +1 -0
  6. package/libs/chunk-4BZKFPEC.cjs +17 -0
  7. package/libs/chunk-4BZKFPEC.cjs.map +1 -0
  8. package/libs/{chunk-O6QZBB6G.js → chunk-5QD3DWFI.js} +5 -5
  9. package/libs/chunk-5QD3DWFI.js.map +1 -0
  10. package/libs/chunk-6SAHIYCZ.js +7 -0
  11. package/libs/chunk-6SAHIYCZ.js.map +1 -0
  12. package/libs/{chunk-KKLTUJFB.cjs → chunk-6WTC4JXH.cjs} +5 -5
  13. package/libs/chunk-6WTC4JXH.cjs.map +1 -0
  14. package/libs/chunk-75QHTLFO.js +7 -0
  15. package/libs/chunk-75QHTLFO.js.map +1 -0
  16. package/libs/{chunk-YWOYVRFT.js → chunk-7XPFW7CB.js} +3 -3
  17. package/libs/chunk-BFK62VX5.js +5 -0
  18. package/libs/chunk-BFK62VX5.js.map +1 -0
  19. package/libs/{chunk-ICCKQ2GC.cjs → chunk-DKTHCQ5P.cjs} +4 -4
  20. package/libs/{chunk-6TE5QEVE.cjs → chunk-E2AJURUW.cjs} +3 -3
  21. package/libs/chunk-E2AJURUW.cjs.map +1 -0
  22. package/libs/chunk-ENTCUJ3A.cjs +13 -0
  23. package/libs/chunk-ENTCUJ3A.cjs.map +1 -0
  24. package/libs/chunk-F5EYMVQM.js +10 -0
  25. package/libs/chunk-F5EYMVQM.js.map +1 -0
  26. package/libs/chunk-FVROL3V5.js +9 -0
  27. package/libs/chunk-FVROL3V5.js.map +1 -0
  28. package/libs/chunk-GT77BX4L.cjs +17 -0
  29. package/libs/chunk-GT77BX4L.cjs.map +1 -0
  30. package/libs/chunk-GUJSMQ3V.cjs +16 -0
  31. package/libs/chunk-GUJSMQ3V.cjs.map +1 -0
  32. package/libs/chunk-HHLNOC5T.js +7 -0
  33. package/libs/chunk-HHLNOC5T.js.map +1 -0
  34. package/libs/chunk-HRRHPLER.js +8 -0
  35. package/libs/chunk-HRRHPLER.js.map +1 -0
  36. package/libs/chunk-IEB64SWY.js +8 -0
  37. package/libs/chunk-IEB64SWY.js.map +1 -0
  38. package/libs/{chunk-LIQJ7ZZR.js → chunk-IQ76HGVP.js} +2 -2
  39. package/libs/chunk-IRLFZ3OL.js +9 -0
  40. package/libs/chunk-IRLFZ3OL.js.map +1 -0
  41. package/libs/chunk-KK47SYZI.js +8 -0
  42. package/libs/chunk-KK47SYZI.js.map +1 -0
  43. package/libs/chunk-O3JIHC5M.cjs +15 -0
  44. package/libs/chunk-O3JIHC5M.cjs.map +1 -0
  45. package/libs/chunk-O5XAJ7BY.cjs +18 -0
  46. package/libs/chunk-O5XAJ7BY.cjs.map +1 -0
  47. package/libs/chunk-OVWLQYMK.js +10 -0
  48. package/libs/chunk-OVWLQYMK.js.map +1 -0
  49. package/libs/chunk-PNWIRCG3.cjs +7 -0
  50. package/libs/chunk-PNWIRCG3.cjs.map +1 -0
  51. package/libs/chunk-QVW6W76L.cjs +18 -0
  52. package/libs/chunk-QVW6W76L.cjs.map +1 -0
  53. package/libs/chunk-T4T6GWYQ.cjs +17 -0
  54. package/libs/chunk-T4T6GWYQ.cjs.map +1 -0
  55. package/libs/chunk-TON2YGMD.cjs +9 -0
  56. package/libs/chunk-TON2YGMD.cjs.map +1 -0
  57. package/libs/chunk-UEPAWMDF.js +8 -0
  58. package/libs/chunk-UEPAWMDF.js.map +1 -0
  59. package/libs/{chunk-LT5KZ2QW.cjs → chunk-US2I5GI7.cjs} +3 -3
  60. package/libs/{chunk-E3XP6BEX.cjs → chunk-W2UIN7EV.cjs} +3 -3
  61. package/libs/chunk-W5TKWBFC.cjs +18 -0
  62. package/libs/chunk-W5TKWBFC.cjs.map +1 -0
  63. package/libs/chunk-WXBFBWYF.cjs +16 -0
  64. package/libs/chunk-WXBFBWYF.cjs.map +1 -0
  65. package/libs/chunk-X3JCTEPD.js +11 -0
  66. package/libs/chunk-X3JCTEPD.js.map +1 -0
  67. package/libs/chunk-X5LGFCWG.js +9 -0
  68. package/libs/chunk-X5LGFCWG.js.map +1 -0
  69. package/libs/{chunk-5M57K4SW.js → chunk-Y2PFDELK.js} +2 -2
  70. package/libs/chunk-ZFJ4U45S.js +10 -0
  71. package/libs/chunk-ZFJ4U45S.js.map +1 -0
  72. package/libs/{component-props-a8a2f97e.d.ts → component-props-67d978a2.d.ts} +4 -4
  73. package/libs/components/alert/alert.css +1 -1
  74. package/libs/components/alert/alert.css.map +1 -1
  75. package/libs/components/alert/alert.min.css +2 -2
  76. package/libs/components/badge/badge.css +1 -1
  77. package/libs/components/badge/badge.css.map +1 -1
  78. package/libs/components/badge/badge.min.css +2 -2
  79. package/libs/components/breadcrumbs/breadcrumb.cjs +9 -5
  80. package/libs/components/breadcrumbs/breadcrumb.d.cts +275 -36
  81. package/libs/components/breadcrumbs/breadcrumb.d.ts +275 -36
  82. package/libs/components/breadcrumbs/breadcrumb.js +3 -3
  83. package/libs/components/button.cjs +6 -4
  84. package/libs/components/button.d.cts +97 -4
  85. package/libs/components/button.d.ts +97 -4
  86. package/libs/components/button.js +4 -2
  87. package/libs/components/buttons/button.css +1 -1
  88. package/libs/components/buttons/button.css.map +1 -1
  89. package/libs/components/buttons/button.min.css +2 -2
  90. package/libs/components/card.cjs +7 -7
  91. package/libs/components/card.d.cts +278 -34
  92. package/libs/components/card.d.ts +278 -34
  93. package/libs/components/card.js +2 -2
  94. package/libs/components/cards/card.css +1 -1
  95. package/libs/components/cards/card.css.map +1 -1
  96. package/libs/components/cards/card.min.css +2 -2
  97. package/libs/components/details/details.css +1 -1
  98. package/libs/components/details/details.css.map +1 -1
  99. package/libs/components/details/details.min.css +2 -2
  100. package/libs/components/dialog/dialog.cjs +9 -7
  101. package/libs/components/dialog/dialog.css +1 -1
  102. package/libs/components/dialog/dialog.css.map +1 -1
  103. package/libs/components/dialog/dialog.d.cts +88 -34
  104. package/libs/components/dialog/dialog.d.ts +88 -34
  105. package/libs/components/dialog/dialog.js +7 -5
  106. package/libs/components/dialog/dialog.min.css +2 -2
  107. package/libs/components/form/fields.cjs +4 -4
  108. package/libs/components/form/fields.d.cts +16 -7
  109. package/libs/components/form/fields.d.ts +16 -7
  110. package/libs/components/form/fields.js +2 -2
  111. package/libs/components/form/inputs.cjs +6 -4
  112. package/libs/components/form/inputs.d.cts +50 -2
  113. package/libs/components/form/inputs.d.ts +50 -2
  114. package/libs/components/form/inputs.js +4 -2
  115. package/libs/components/form/textarea.cjs +5 -4
  116. package/libs/components/form/textarea.d.cts +32 -23
  117. package/libs/components/form/textarea.d.ts +32 -23
  118. package/libs/components/form/textarea.js +3 -2
  119. package/libs/components/heading/heading.cjs +3 -3
  120. package/libs/components/heading/heading.d.cts +3 -14
  121. package/libs/components/heading/heading.d.ts +3 -14
  122. package/libs/components/heading/heading.js +2 -2
  123. package/libs/components/icons/icon.cjs +4 -4
  124. package/libs/components/icons/icon.d.cts +183 -39
  125. package/libs/components/icons/icon.d.ts +183 -39
  126. package/libs/components/icons/icon.js +2 -2
  127. package/libs/components/images/img.css +1 -1
  128. package/libs/components/images/img.css.map +1 -1
  129. package/libs/components/images/img.min.css +2 -2
  130. package/libs/components/link/link.cjs +4 -4
  131. package/libs/components/link/link.css +1 -1
  132. package/libs/components/link/link.css.map +1 -1
  133. package/libs/components/link/link.d.cts +3 -19
  134. package/libs/components/link/link.d.ts +3 -19
  135. package/libs/components/link/link.js +2 -2
  136. package/libs/components/link/link.min.css +2 -2
  137. package/libs/components/list/list.cjs +5 -5
  138. package/libs/components/list/list.css +1 -0
  139. package/libs/components/list/list.css.map +1 -0
  140. package/libs/components/list/list.d.cts +120 -33
  141. package/libs/components/list/list.d.ts +120 -33
  142. package/libs/components/list/list.js +2 -2
  143. package/libs/components/list/list.min.css +3 -0
  144. package/libs/components/modal.cjs +6 -4
  145. package/libs/components/modal.d.cts +8 -8
  146. package/libs/components/modal.d.ts +8 -8
  147. package/libs/components/modal.js +5 -3
  148. package/libs/components/nav/nav.cjs +7 -7
  149. package/libs/components/nav/nav.css +1 -1
  150. package/libs/components/nav/nav.css.map +1 -1
  151. package/libs/components/nav/nav.d.cts +550 -34
  152. package/libs/components/nav/nav.d.ts +550 -34
  153. package/libs/components/nav/nav.js +3 -3
  154. package/libs/components/nav/nav.min.css +2 -2
  155. package/libs/components/popover/popover.d.cts +5 -5
  156. package/libs/components/popover/popover.d.ts +5 -5
  157. package/libs/components/tables/table.cjs +5 -5
  158. package/libs/components/tables/table.d.cts +8 -8
  159. package/libs/components/tables/table.d.ts +8 -8
  160. package/libs/components/tables/table.js +2 -2
  161. package/libs/components/tag/tag.css +1 -1
  162. package/libs/components/tag/tag.css.map +1 -1
  163. package/libs/components/tag/tag.min.css +2 -2
  164. package/libs/components/text/text.cjs +5 -5
  165. package/libs/components/text/text.d.cts +5 -5
  166. package/libs/components/text/text.d.ts +5 -5
  167. package/libs/components/text/text.js +2 -2
  168. package/libs/form.types-d25ebfac.d.ts +233 -0
  169. package/libs/heading-7446cb46.d.ts +250 -0
  170. package/libs/hooks.cjs +12 -0
  171. package/libs/hooks.d.cts +140 -1
  172. package/libs/hooks.d.ts +140 -1
  173. package/libs/hooks.js +4 -0
  174. package/libs/icons.cjs +3 -3
  175. package/libs/icons.d.cts +2 -2
  176. package/libs/icons.d.ts +2 -2
  177. package/libs/icons.js +2 -2
  178. package/libs/index.cjs +117 -94
  179. package/libs/index.cjs.map +1 -1
  180. package/libs/index.css +1 -1
  181. package/libs/index.css.map +1 -1
  182. package/libs/index.d.cts +834 -61
  183. package/libs/index.d.ts +834 -61
  184. package/libs/index.js +36 -22
  185. package/libs/index.js.map +1 -1
  186. package/libs/link-5192f411.d.ts +323 -0
  187. package/libs/list.types-d26de310.d.ts +245 -0
  188. package/libs/ui-d01b50d4.d.ts +289 -0
  189. package/package.json +4 -87
  190. package/src/components/README-UI.mdx +416 -0
  191. package/src/components/alert/ACCESSIBILITY.md +319 -0
  192. package/src/components/alert/README.mdx +475 -19
  193. package/src/components/alert/alert.scss +110 -6
  194. package/src/components/alert/alert.stories.tsx +372 -0
  195. package/src/components/alert/alert.test.tsx +762 -0
  196. package/src/components/alert/alert.tsx +331 -66
  197. package/src/components/alert/views/alert-actions.tsx +13 -0
  198. package/src/components/alert/views/alert-content.tsx +17 -0
  199. package/src/components/alert/views/alert-icon.tsx +53 -0
  200. package/src/components/alert/views/alert-screen-reader-text.tsx +30 -0
  201. package/src/components/alert/views/alert-title.tsx +23 -0
  202. package/src/components/alert/views/alert-view.tsx +158 -0
  203. package/src/components/alert/views/index.ts +12 -0
  204. package/src/components/badge/badge.mdx +186 -49
  205. package/src/components/badge/badge.scss +20 -2
  206. package/src/components/badge/badge.stories.tsx +160 -14
  207. package/src/components/badge/badge.test.tsx +179 -0
  208. package/src/components/badge/badge.tsx +97 -4
  209. package/src/components/breadcrumbs/README.mdx +364 -45
  210. package/src/components/breadcrumbs/__snapshots__/breadcrumb.test.tsx.snap +152 -0
  211. package/src/components/breadcrumbs/breadcrumb.stories.tsx +7 -3
  212. package/src/components/breadcrumbs/breadcrumb.test.tsx +490 -0
  213. package/src/components/breadcrumbs/breadcrumb.tsx +430 -170
  214. package/src/components/buttons/README.mdx +102 -1
  215. package/src/components/buttons/button.scss +34 -31
  216. package/src/components/buttons/button.stories.tsx +141 -0
  217. package/src/components/buttons/button.tsx +82 -52
  218. package/src/components/cards/README.mdx +657 -0
  219. package/src/components/cards/card.scss +22 -0
  220. package/src/components/cards/card.stories.tsx +167 -5
  221. package/src/components/cards/card.test.tsx +360 -20
  222. package/src/components/cards/card.tsx +200 -79
  223. package/src/components/cards/card.types.ts +135 -0
  224. package/src/components/cards/card.utils.ts +79 -0
  225. package/src/components/details/ACCESSIBILITY-REVIEW-LIVE.md +1050 -0
  226. package/src/components/details/ACCESSIBILITY-REVIEW.md +502 -0
  227. package/src/components/details/README.mdx +437 -69
  228. package/src/components/details/details.scss +16 -7
  229. package/src/components/details/details.test.tsx +385 -0
  230. package/src/components/details/details.tsx +101 -69
  231. package/src/components/details/details.types.ts +76 -0
  232. package/src/components/dialog/README.mdx +513 -110
  233. package/src/components/dialog/dialog-a11y-review.md +653 -0
  234. package/src/components/dialog/dialog-modal.tsx +79 -56
  235. package/src/components/dialog/dialog.scss +53 -3
  236. package/src/components/dialog/dialog.stories.tsx +10 -7
  237. package/src/components/dialog/dialog.test.tsx +450 -0
  238. package/src/components/dialog/dialog.tsx +69 -59
  239. package/src/components/dialog/dialog.types.ts +133 -0
  240. package/src/components/dialog/views/dialog-footer.tsx +54 -11
  241. package/src/components/dialog/views/dialog-header.tsx +20 -15
  242. package/src/components/form/README.mdx +725 -43
  243. package/src/components/form/WCAG-REVIEW.md +654 -0
  244. package/src/components/form/fields.tsx +10 -1
  245. package/src/components/form/form.stories.tsx +604 -23
  246. package/src/components/form/form.tsx +204 -63
  247. package/src/components/form/form.types.ts +378 -0
  248. package/src/components/form/input.stories.tsx +71 -3
  249. package/src/components/form/inputs.tsx +159 -67
  250. package/src/components/form/select.tsx +122 -66
  251. package/src/components/form/textarea.tsx +120 -73
  252. package/src/components/fp.tsx +86 -11
  253. package/src/components/heading/heading.stories.tsx +44 -4
  254. package/src/components/heading/heading.tsx +89 -23
  255. package/src/components/icons/README.mdx +332 -0
  256. package/src/components/icons/icon.stories.tsx +74 -1
  257. package/src/components/icons/icon.tsx +89 -1
  258. package/src/components/icons/types.ts +47 -0
  259. package/src/components/images/README.mdx +340 -24
  260. package/src/components/images/img.scss +19 -3
  261. package/src/components/images/img.stories.tsx +424 -15
  262. package/src/components/images/img.test.tsx +354 -25
  263. package/src/components/images/img.tsx +186 -63
  264. package/src/components/images/img.types.ts +211 -0
  265. package/src/components/link/README.mdx +923 -0
  266. package/src/components/link/link.scss +79 -26
  267. package/src/components/link/link.stories.tsx +383 -30
  268. package/src/components/link/link.test.tsx +677 -0
  269. package/src/components/link/link.tsx +163 -57
  270. package/src/components/link/link.types.ts +261 -0
  271. package/src/components/list/README.mdx +764 -0
  272. package/src/components/list/list.scss +285 -0
  273. package/src/components/list/list.stories.tsx +514 -27
  274. package/src/components/list/list.test.tsx +554 -0
  275. package/src/components/list/list.tsx +153 -51
  276. package/src/components/list/list.types.ts +255 -0
  277. package/src/components/nav/ACCESSIBILITY.md +649 -0
  278. package/src/components/nav/README.mdx +782 -0
  279. package/src/components/nav/nav.scss +32 -1
  280. package/src/components/nav/nav.stories.tsx +44 -6
  281. package/src/components/nav/nav.tsx +302 -51
  282. package/src/components/nav/nav.types.ts +308 -0
  283. package/src/components/tag/README.mdx +426 -0
  284. package/src/components/tag/tag.scss +101 -27
  285. package/src/components/tag/tag.stories.tsx +384 -10
  286. package/src/components/tag/tag.test.tsx +210 -0
  287. package/src/components/tag/tag.tsx +106 -9
  288. package/src/components/tag/tag.types.ts +107 -0
  289. package/src/components/title/MIGRATION.md +199 -0
  290. package/src/components/title/README.md +326 -0
  291. package/src/components/title/README.mdx +452 -0
  292. package/src/components/title/title.stories.tsx +393 -0
  293. package/src/components/title/title.test.tsx +251 -0
  294. package/src/components/title/title.tsx +219 -0
  295. package/src/components/ui.stories.tsx +894 -0
  296. package/src/components/ui.test.tsx +559 -0
  297. package/src/components/ui.tsx +274 -18
  298. package/src/components/word-count/README.md +240 -0
  299. package/src/hooks/use-disabled-state.test.tsx +536 -0
  300. package/src/hooks/use-disabled-state.ts +246 -0
  301. package/src/hooks/useDisabledState.md +393 -0
  302. package/src/hooks.ts +7 -0
  303. package/src/index.scss +2 -0
  304. package/src/index.ts +12 -3
  305. package/src/sass/_globals.scss +2 -7
  306. package/src/sass/_properties.scss +1 -0
  307. package/src/styles/alert/alert.css +92 -4
  308. package/src/styles/alert/alert.css.map +1 -1
  309. package/src/styles/badge/badge.css +20 -2
  310. package/src/styles/badge/badge.css.map +1 -1
  311. package/src/styles/buttons/button.css +31 -31
  312. package/src/styles/buttons/button.css.map +1 -1
  313. package/src/styles/cards/card.css +16 -0
  314. package/src/styles/cards/card.css.map +1 -1
  315. package/src/styles/details/details.css +19 -8
  316. package/src/styles/details/details.css.map +1 -1
  317. package/src/styles/dialog/dialog.css +43 -2
  318. package/src/styles/dialog/dialog.css.map +1 -1
  319. package/src/styles/images/img.css +15 -3
  320. package/src/styles/images/img.css.map +1 -1
  321. package/src/styles/index.css +691 -128
  322. package/src/styles/index.css.map +1 -1
  323. package/src/styles/link/link.css +45 -28
  324. package/src/styles/link/link.css.map +1 -1
  325. package/src/styles/list/list.css +214 -0
  326. package/src/styles/list/list.css.map +1 -0
  327. package/src/styles/nav/nav.css +21 -1
  328. package/src/styles/nav/nav.css.map +1 -1
  329. package/src/styles/tag/tag.css +113 -35
  330. package/src/styles/tag/tag.css.map +1 -1
  331. package/src/styles/utilities/_disabled.scss +58 -0
  332. package/src/test/setup.d.ts +9 -0
  333. package/src/test/setup.ts +53 -1
  334. package/src/types/shared.ts +43 -6
  335. package/src/utils/accessibility.ts +109 -0
  336. package/libs/chunk-5ZM4XL44.js +0 -8
  337. package/libs/chunk-5ZM4XL44.js.map +0 -1
  338. package/libs/chunk-6BVXFW7U.cjs +0 -15
  339. package/libs/chunk-6BVXFW7U.cjs.map +0 -1
  340. package/libs/chunk-6TE5QEVE.cjs.map +0 -1
  341. package/libs/chunk-7K76RW2A.cjs +0 -18
  342. package/libs/chunk-7K76RW2A.cjs.map +0 -1
  343. package/libs/chunk-BHRQBJRY.js +0 -8
  344. package/libs/chunk-BHRQBJRY.js.map +0 -1
  345. package/libs/chunk-BIP2NY53.js +0 -8
  346. package/libs/chunk-BIP2NY53.js.map +0 -1
  347. package/libs/chunk-BSPKFLO4.js +0 -8
  348. package/libs/chunk-BSPKFLO4.js.map +0 -1
  349. package/libs/chunk-BV5CLH44.cjs +0 -18
  350. package/libs/chunk-BV5CLH44.cjs.map +0 -1
  351. package/libs/chunk-DKGJHKGW.js +0 -9
  352. package/libs/chunk-DKGJHKGW.js.map +0 -1
  353. package/libs/chunk-DV56L5YX.cjs +0 -18
  354. package/libs/chunk-DV56L5YX.cjs.map +0 -1
  355. package/libs/chunk-ECLD37WN.cjs +0 -16
  356. package/libs/chunk-ECLD37WN.cjs.map +0 -1
  357. package/libs/chunk-EQ67LF46.js +0 -9
  358. package/libs/chunk-EQ67LF46.js.map +0 -1
  359. package/libs/chunk-HYBZBN4G.js +0 -8
  360. package/libs/chunk-HYBZBN4G.js.map +0 -1
  361. package/libs/chunk-IYUN2EW3.cjs +0 -15
  362. package/libs/chunk-IYUN2EW3.cjs.map +0 -1
  363. package/libs/chunk-KKLTUJFB.cjs.map +0 -1
  364. package/libs/chunk-LHVJKDMA.cjs +0 -15
  365. package/libs/chunk-LHVJKDMA.cjs.map +0 -1
  366. package/libs/chunk-LL7HTLMS.cjs +0 -15
  367. package/libs/chunk-LL7HTLMS.cjs.map +0 -1
  368. package/libs/chunk-M5QL5TAE.cjs +0 -14
  369. package/libs/chunk-M5QL5TAE.cjs.map +0 -1
  370. package/libs/chunk-NE6YXTMC.js +0 -7
  371. package/libs/chunk-NE6YXTMC.js.map +0 -1
  372. package/libs/chunk-NHYXGV3L.js +0 -8
  373. package/libs/chunk-NHYXGV3L.js.map +0 -1
  374. package/libs/chunk-O6QZBB6G.js.map +0 -1
  375. package/libs/chunk-P7TTEYCD.js +0 -7
  376. package/libs/chunk-P7TTEYCD.js.map +0 -1
  377. package/libs/chunk-PPOOBUOS.js +0 -8
  378. package/libs/chunk-PPOOBUOS.js.map +0 -1
  379. package/libs/chunk-QCMV4VQZ.js +0 -8
  380. package/libs/chunk-QCMV4VQZ.js.map +0 -1
  381. package/libs/chunk-QVV34QEH.cjs +0 -32
  382. package/libs/chunk-QVV34QEH.cjs.map +0 -1
  383. package/libs/chunk-S7BABR7Z.cjs +0 -13
  384. package/libs/chunk-S7BABR7Z.cjs.map +0 -1
  385. package/libs/chunk-SXVZSWX6.js +0 -11
  386. package/libs/chunk-SXVZSWX6.js.map +0 -1
  387. package/libs/chunk-X3EVB7VS.cjs +0 -15
  388. package/libs/chunk-X3EVB7VS.cjs.map +0 -1
  389. package/libs/inputs-f3a216db.d.ts +0 -45
  390. package/libs/ui-9a6f9f8d.d.ts +0 -24
  391. package/src/components/cards/README.md +0 -80
  392. package/src/components/dialog/hooks/useClickOutside.ts +0 -33
  393. /package/libs/{chunk-YWOYVRFT.js.map → chunk-7XPFW7CB.js.map} +0 -0
  394. /package/libs/{chunk-ICCKQ2GC.cjs.map → chunk-DKTHCQ5P.cjs.map} +0 -0
  395. /package/libs/{chunk-LIQJ7ZZR.js.map → chunk-IQ76HGVP.js.map} +0 -0
  396. /package/libs/{chunk-LT5KZ2QW.cjs.map → chunk-US2I5GI7.cjs.map} +0 -0
  397. /package/libs/{chunk-E3XP6BEX.cjs.map → chunk-W2UIN7EV.cjs.map} +0 -0
  398. /package/libs/{chunk-5M57K4SW.js.map → chunk-Y2PFDELK.js.map} +0 -0
@@ -0,0 +1,654 @@
1
+ # Form Components - WCAG 2.1 AA Accessibility Review
2
+
3
+ **Review Date:** 2025-10-25
4
+ **Components Reviewed:** Form, Field, Input, Select, Textarea
5
+ **WCAG Version:** 2.1 Level AA
6
+ **Files Analyzed:**
7
+ - `form.tsx`
8
+ - `fields.tsx`
9
+ - `inputs.tsx`
10
+ - `select.tsx`
11
+ - `textarea.tsx`
12
+ - `form.types.ts`
13
+
14
+ ---
15
+
16
+ ## Executive Summary
17
+
18
+ The Form component and its sub-components demonstrate strong accessibility foundations with proper semantic HTML, ARIA attributes, and keyboard support. However, there are several critical issues that need attention to achieve full WCAG 2.1 AA compliance.
19
+
20
+ **Issues Found:** 4 errors, 3 warnings, 2 recommendations
21
+
22
+ ---
23
+
24
+ ## Critical Issues (Errors)
25
+
26
+ ### 1. Disabled State Implementation - WCAG 4.1.2 (Name, Role, Value)
27
+
28
+ **Severity:** Error
29
+ **Files Affected:** `inputs.tsx:142`, `select.tsx:139`, `textarea.tsx:121`
30
+ **WCAG Criteria:** 4.1.2 Name, Role, Value (Level A)
31
+
32
+ #### Problem
33
+
34
+ All three input components use `aria-disabled` instead of the native `disabled` attribute. This is a significant accessibility violation because `aria-disabled` alone doesn't prevent user interaction—keyboard users can still focus and type in these inputs.
35
+
36
+ **inputs.tsx (Line 142):**
37
+ ```tsx
38
+ // ❌ Bad - aria-disabled doesn't prevent interaction
39
+ aria-disabled={isInputDisabled}
40
+ ```
41
+
42
+ **select.tsx (Line 139):**
43
+ ```tsx
44
+ // ❌ Bad
45
+ aria-disabled={disabled}
46
+ ```
47
+
48
+ **textarea.tsx (Line 121):**
49
+ ```tsx
50
+ // ❌ Bad
51
+ aria-disabled={disabled}
52
+ ```
53
+
54
+ #### Fix
55
+
56
+ Use the native `disabled` attribute, which provides both functionality AND proper semantics:
57
+
58
+ ```tsx
59
+ // ✅ Good - Input component
60
+ <FP
61
+ as="input"
62
+ // ... other props
63
+ disabled={isInputDisabled} // Native disabled attribute
64
+ // Remove aria-disabled - it's redundant with native disabled
65
+ aria-readonly={readOnly}
66
+ aria-required={required}
67
+ aria-invalid={isInvalid}
68
+ aria-describedby={ariaDescribedBy}
69
+ {...props}
70
+ />
71
+ ```
72
+
73
+ ```tsx
74
+ // ✅ Good - Select component
75
+ <UI
76
+ as="select"
77
+ // ... other props
78
+ disabled={disabled} // Native disabled attribute
79
+ // Remove aria-disabled
80
+ required={required}
81
+ aria-required={required}
82
+ {...props}
83
+ />
84
+ ```
85
+
86
+ ```tsx
87
+ // ✅ Good - Textarea component
88
+ <UI
89
+ as="textarea"
90
+ // ... other props
91
+ disabled={disabled} // Native disabled attribute
92
+ // Remove aria-disabled
93
+ aria-required={required}
94
+ readOnly={readOnly}
95
+ {...props}
96
+ />
97
+ ```
98
+
99
+ #### Why This Matters
100
+
101
+ Screen readers announce the disabled state from the native attribute, AND the browser prevents interaction. Using only aria-disabled creates a "fake" disabled state that doesn't actually work.
102
+
103
+ ---
104
+
105
+ ### 2. Missing Validation ARIA in Select and Textarea - WCAG 3.3.1, 4.1.2
106
+
107
+ **Severity:** Error
108
+ **Files Affected:** `select.tsx`, `textarea.tsx`
109
+ **WCAG Criteria:** 3.3.1 Error Identification (Level A), 4.1.2 Name, Role, Value (Level A)
110
+
111
+ #### Problem
112
+
113
+ The TypeScript interfaces define `validationState`, `errorMessage`, and `hintText` props, but the Select and Textarea components don't implement `aria-invalid` or `aria-describedby` to expose these to assistive technologies. The Input component implements this correctly, but Select and Textarea don't.
114
+
115
+ **Current Select implementation (incomplete):**
116
+ ```tsx
117
+ // select.tsx - missing validation ARIA
118
+ export interface SelectProps {
119
+ validationState?: ValidationState // ✅ Defined in types
120
+ errorMessage?: string // ✅ Defined in types
121
+ hintText?: string // ✅ Defined in types
122
+ }
123
+
124
+ // ❌ But not implemented in component!
125
+ <UI
126
+ as="select"
127
+ // Missing: aria-invalid, aria-describedby
128
+ {...props}
129
+ />
130
+ ```
131
+
132
+ #### Fix for Select
133
+
134
+ ```tsx
135
+ // select.tsx
136
+ export const Select = React.forwardRef<HTMLSelectElement, SelectProps>(
137
+ (
138
+ {
139
+ id,
140
+ validationState = 'none',
141
+ errorMessage,
142
+ hintText,
143
+ // ... other props
144
+ },
145
+ ref
146
+ ) => {
147
+ // Determine aria-invalid based on validation state
148
+ const isInvalid = validationState === 'invalid';
149
+
150
+ // Generate describedby IDs for error and hint text
151
+ const describedByIds: string[] = [];
152
+ if (errorMessage && id) {
153
+ describedByIds.push(`${id}-error`);
154
+ }
155
+ if (hintText && id) {
156
+ describedByIds.push(`${id}-hint`);
157
+ }
158
+ const ariaDescribedBy =
159
+ describedByIds.length > 0 ? describedByIds.join(' ') : undefined;
160
+
161
+ return (
162
+ <UI
163
+ as="select"
164
+ id={id}
165
+ aria-invalid={isInvalid}
166
+ aria-describedby={ariaDescribedBy}
167
+ aria-required={required}
168
+ disabled={disabled}
169
+ // ... other props
170
+ />
171
+ );
172
+ }
173
+ );
174
+ ```
175
+
176
+ #### Fix for Textarea
177
+
178
+ Apply the same pattern as above to textarea.tsx.
179
+
180
+ #### Why This Matters
181
+
182
+ When validation errors occur, screen reader users need to be notified. Without `aria-invalid` and `aria-describedby`, they have no way to discover errors.
183
+
184
+ ---
185
+
186
+ ### 3. Redundant ARIA Role on Option - WCAG 4.1.2
187
+
188
+ **Severity:** Error
189
+ **File:** `select.tsx:27`
190
+ **WCAG Criteria:** 4.1.2 Name, Role, Value (Level A)
191
+
192
+ #### Problem
193
+
194
+ ```tsx
195
+ // ❌ Bad - role="option" is redundant on native <option>
196
+ export const Option = ({ selectValue, selectLabel }: SelectOptionsProps) => {
197
+ return (
198
+ <option role="option" value={selectValue}>
199
+ {selectLabel || selectValue}
200
+ </option>
201
+ )
202
+ }
203
+ ```
204
+
205
+ #### Fix
206
+
207
+ ```tsx
208
+ // ✅ Good - remove redundant role
209
+ export const Option = ({ selectValue, selectLabel }: SelectOptionsProps) => {
210
+ return (
211
+ <option value={selectValue}>
212
+ {selectLabel || selectValue}
213
+ </option>
214
+ )
215
+ }
216
+ ```
217
+
218
+ #### Why This Matters
219
+
220
+ Native HTML elements have implicit ARIA roles. Adding explicit roles can confuse assistive technologies and validators. The first rule of ARIA is "don't use ARIA if native HTML works."
221
+
222
+ ---
223
+
224
+ ### 4. Form Missing Accessible Name - WCAG 2.4.6, 4.1.2
225
+
226
+ **Severity:** Error (when multiple forms on page)
227
+ **File:** `form.tsx:164`
228
+ **WCAG Criteria:** 2.4.6 Headings and Labels (Level AA), 4.1.2 Name, Role, Value (Level A)
229
+
230
+ #### Problem
231
+
232
+ ```tsx
233
+ // form.tsx (Line 164)
234
+ <UI
235
+ as="form"
236
+ role="form" // ⚠️ Also redundant - native form has implicit role
237
+ aria-busy={isBusy}
238
+ // ❌ Missing: aria-label or aria-labelledby
239
+ {...props}
240
+ >
241
+ ```
242
+
243
+ The JSDoc examples show `aria-label` usage, but the component doesn't require or encourage providing an accessible name. When multiple forms exist on a page, screen reader users can't distinguish between them.
244
+
245
+ #### Fix Option 1: Encourage aria-label via TypeScript (recommended)
246
+
247
+ ```tsx
248
+ export interface FormProps extends Omit<React.ComponentProps<'form'>, 'className'> {
249
+ /**
250
+ * Accessible name for the form (required for distinguishing multiple forms)
251
+ * @example "Contact form", "Login form", "Search form"
252
+ */
253
+ 'aria-label'?: string
254
+ 'aria-labelledby'?: string
255
+ // ... other props
256
+ }
257
+ ```
258
+
259
+ #### Fix Option 2: Add runtime warning
260
+
261
+ ```tsx
262
+ const Form = React.forwardRef<HTMLFormElement, FormProps>(
263
+ ({ 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, ...props }, ref) => {
264
+ // Warn in development if no accessible name provided
265
+ if (process.env.NODE_ENV !== 'production') {
266
+ if (!ariaLabel && !ariaLabelledBy) {
267
+ console.warn(
268
+ 'Form component should have an accessible name via aria-label or aria-labelledby'
269
+ );
270
+ }
271
+ }
272
+
273
+ return (
274
+ <UI
275
+ as="form"
276
+ // Remove redundant role="form"
277
+ aria-busy={isBusy}
278
+ aria-label={ariaLabel}
279
+ aria-labelledby={ariaLabelledBy}
280
+ {...props}
281
+ />
282
+ );
283
+ }
284
+ );
285
+ ```
286
+
287
+ #### Why This Matters
288
+
289
+ Screen reader users who navigate by landmarks need to know which form is which. "Form" alone isn't descriptive enough.
290
+
291
+ ---
292
+
293
+ ## Warnings (Should Fix)
294
+
295
+ ### 1. Redundant role="form" - WCAG 4.1.2
296
+
297
+ **Severity:** Warning
298
+ **File:** `form.tsx:164`
299
+ **WCAG Criteria:** 4.1.2 Name, Role, Value (Level A)
300
+
301
+ #### Issue
302
+
303
+ ```tsx
304
+ // ⚠️ Redundant - native <form> already has role="form"
305
+ <UI
306
+ as="form"
307
+ role="form" // Remove this
308
+ aria-busy={isBusy}
309
+ {...props}
310
+ />
311
+ ```
312
+
313
+ #### Fix
314
+
315
+ Remove `role="form"` - the native `<form>` element already has an implicit role of "form".
316
+
317
+ ---
318
+
319
+ ### 2. autoFocus Support - WCAG 3.2.1 (On Focus)
320
+
321
+ **Severity:** Warning
322
+ **Files:** `inputs.tsx:78`, `inputs.tsx:134`
323
+ **WCAG Criteria:** 3.2.1 On Focus (Level A)
324
+
325
+ #### Issue
326
+
327
+ The Input component supports `autoFocus={true}`, which can cause unexpected context changes and disorient users, especially screen reader users.
328
+
329
+ ```tsx
330
+ // inputs.tsx
331
+ autoFocus={autoFocus} // ⚠️ Can violate WCAG 3.2.1
332
+ ```
333
+
334
+ #### Recommendation
335
+
336
+ Consider adding a JSDoc warning:
337
+
338
+ ```tsx
339
+ /**
340
+ * Auto-focus on mount
341
+ * ⚠️ WARNING: Use sparingly. Can violate WCAG 3.2.1 if it causes unexpected context changes.
342
+ * Only use when user clearly expects focus (e.g., search page, modal dialogs)
343
+ * @default false
344
+ * @see https://www.w3.org/WAI/WCAG21/Understanding/on-focus.html
345
+ */
346
+ autoFocus?: boolean
347
+ ```
348
+
349
+ ---
350
+
351
+ ### 3. Field Component Doesn't Validate Label Association
352
+
353
+ **Severity:** Warning
354
+ **File:** `fields.tsx:38`
355
+ **WCAG Criteria:** 3.3.2 Labels or Instructions (Level A)
356
+
357
+ #### Issue
358
+
359
+ The Field component accepts a `labelFor` prop but doesn't validate that:
360
+ 1. `labelFor` is provided
361
+ 2. A matching child input exists
362
+
363
+ This can lead to unlabeled inputs if developers forget to connect them properly.
364
+
365
+ **Current implementation:**
366
+ ```tsx
367
+ // fields.tsx
368
+ <label htmlFor={labelFor}>{label}</label> // labelFor might be undefined
369
+ {children}
370
+ ```
371
+
372
+ #### Recommendation
373
+
374
+ Add TypeScript validation or runtime warning:
375
+
376
+ ```tsx
377
+ export interface FieldProps {
378
+ /**
379
+ * ID of the associated form control (REQUIRED for accessibility)
380
+ * Must match the id of the child input/select/textarea
381
+ */
382
+ labelFor: string // Make required, not optional
383
+ // ... other props
384
+ }
385
+ ```
386
+
387
+ ---
388
+
389
+ ## Recommendations (Best Practices)
390
+
391
+ ### 1. Add Form Error Summary Pattern
392
+
393
+ **WCAG Criteria:** 3.3.1 Error Identification (Level A)
394
+
395
+ #### Benefit
396
+
397
+ Helps users with screen readers discover all validation errors at once.
398
+
399
+ #### Example
400
+
401
+ ```tsx
402
+ // Recommended pattern for form-level error summary
403
+ {errors.length > 0 && (
404
+ <div role="alert" aria-live="assertive" id="form-errors">
405
+ <h2>Please correct the following errors:</h2>
406
+ <ul>
407
+ {errors.map((error, index) => (
408
+ <li key={index}>
409
+ <a href={`#${error.fieldId}`}>{error.message}</a>
410
+ </li>
411
+ ))}
412
+ </ul>
413
+ </div>
414
+ )}
415
+ ```
416
+
417
+ ---
418
+
419
+ ### 2. Document Required Autocomplete Usage - WCAG 1.3.5
420
+
421
+ **WCAG Criteria:** 1.3.5 Identify Input Purpose (Level AA)
422
+
423
+ #### Issue
424
+
425
+ The Input component supports `autoComplete`, but WCAG 2.1 AA requires autocomplete attributes for personal data inputs.
426
+
427
+ #### Recommendation
428
+
429
+ Add JSDoc guidance:
430
+
431
+ ```tsx
432
+ /**
433
+ * Autocomplete attribute for browser autofill
434
+ * REQUIRED by WCAG 2.1 AA (1.3.5) for inputs collecting user information:
435
+ * - "email" for email addresses
436
+ * - "tel" for phone numbers
437
+ * - "given-name", "family-name" for names
438
+ * - "street-address", "address-level1", etc. for addresses
439
+ * @see https://www.w3.org/WAI/WCAG21/Understanding/identify-input-purpose.html
440
+ */
441
+ autoComplete?: string
442
+ ```
443
+
444
+ ---
445
+
446
+ ## Accessibility Strengths
447
+
448
+ The form components demonstrate several excellent accessibility practices:
449
+
450
+ ### ✅ Proper Semantic HTML
451
+ - Uses native `<form>`, `<input>`, `<select>`, `<textarea>`, and `<label>` elements
452
+ - Leverages built-in browser accessibility features
453
+
454
+ ### ✅ Keyboard Support
455
+ - All components are keyboard accessible
456
+ - `onEnter` handlers enable keyboard-only form submission
457
+ - Textarea properly handles Shift+Enter for new lines
458
+
459
+ ### ✅ Forward Refs
460
+ - All components properly forward refs using `React.forwardRef`
461
+ - Enables parent components to manage focus programmatically
462
+
463
+ ### ✅ Comprehensive TypeScript Types
464
+ - Well-defined prop interfaces with JSDoc comments
465
+ - Extends native HTML element props for maximum flexibility
466
+ - Provides type safety for accessibility attributes
467
+
468
+ ### ✅ Validation State Management (Input component)
469
+ - Input component correctly implements `aria-invalid`
470
+ - Properly associates error/hint text with `aria-describedby`
471
+ - Generates unique IDs for error messages
472
+
473
+ ### ✅ Documentation
474
+ - Excellent JSDoc comments with examples
475
+ - References to WCAG success criteria in code comments
476
+ - Multiple usage examples demonstrating accessibility patterns
477
+
478
+ ---
479
+
480
+ ## Testing Recommendations
481
+
482
+ ### Automated Testing
483
+
484
+ #### 1. Install and configure eslint-plugin-jsx-a11y
485
+
486
+ ```bash
487
+ npm install --save-dev eslint-plugin-jsx-a11y
488
+ ```
489
+
490
+ Add to `.eslintrc`:
491
+ ```json
492
+ {
493
+ "extends": ["plugin:jsx-a11y/recommended"],
494
+ "rules": {
495
+ "jsx-a11y/no-redundant-roles": "error",
496
+ "jsx-a11y/aria-props": "error",
497
+ "jsx-a11y/aria-proptypes": "error",
498
+ "jsx-a11y/label-has-associated-control": "error"
499
+ }
500
+ }
501
+ ```
502
+
503
+ #### 2. Add jest-axe for component testing
504
+
505
+ ```bash
506
+ npm install --save-dev jest-axe
507
+ ```
508
+
509
+ Example test:
510
+ ```tsx
511
+ import { axe, toHaveNoViolations } from 'jest-axe';
512
+ import { render } from '@testing-library/react';
513
+ import Form from './form';
514
+
515
+ expect.extend(toHaveNoViolations);
516
+
517
+ describe('Form Accessibility', () => {
518
+ it('should have no accessibility violations', async () => {
519
+ const { container } = render(
520
+ <Form aria-label="Contact form">
521
+ <Form.Field label="Email" labelFor="email">
522
+ <Form.Input id="email" type="email" autoComplete="email" />
523
+ </Form.Field>
524
+ <Form.Field label="Message" labelFor="message">
525
+ <Form.Textarea id="message" name="message" />
526
+ </Form.Field>
527
+ </Form>
528
+ );
529
+
530
+ const results = await axe(container);
531
+ expect(results).toHaveNoViolations();
532
+ });
533
+
534
+ it('should announce validation errors', async () => {
535
+ const { container } = render(
536
+ <Form aria-label="Contact form">
537
+ <Form.Field label="Email" labelFor="email">
538
+ <Form.Input
539
+ id="email"
540
+ type="email"
541
+ validationState="invalid"
542
+ errorMessage="Please enter a valid email"
543
+ />
544
+ <div id="email-error" role="alert">
545
+ Please enter a valid email
546
+ </div>
547
+ </Form.Field>
548
+ </Form>
549
+ );
550
+
551
+ const results = await axe(container);
552
+ expect(results).toHaveNoViolations();
553
+ });
554
+ });
555
+ ```
556
+
557
+ ### Manual Testing Checklist
558
+
559
+ #### Keyboard Navigation
560
+ - [ ] Tab through all form fields without mouse
561
+ - [ ] Verify tab order matches visual order
562
+ - [ ] Test Enter key submission
563
+ - [ ] Test Shift+Enter in textarea (creates new line)
564
+ - [ ] Verify disabled inputs cannot receive focus
565
+ - [ ] Check focus indicators are visible (3:1 contrast)
566
+
567
+ #### Screen Reader Testing
568
+ - [ ] Test with NVDA (Windows) or VoiceOver (Mac)
569
+ - [ ] Verify all labels are announced
570
+ - [ ] Check error messages are announced when inputs become invalid
571
+ - [ ] Verify disabled/required states are announced
572
+ - [ ] Test form landmark navigation
573
+ - [ ] Verify form has an accessible name
574
+
575
+ #### Validation & Error Handling
576
+ - [ ] Verify errors are announced immediately when they occur
577
+ - [ ] Check `aria-invalid` updates dynamically
578
+ - [ ] Test that error messages are associated with inputs
579
+ - [ ] Verify error color has sufficient contrast
580
+ - [ ] Check errors are indicated by more than color alone
581
+
582
+ #### Form Submission
583
+ - [ ] Test Enter key submission from text inputs
584
+ - [ ] Verify aria-busy announces during submission
585
+ - [ ] Test form submission with validation errors
586
+ - [ ] Check success/error messages are announced
587
+
588
+ ---
589
+
590
+ ## Quick Wins
591
+
592
+ These fixes provide the most significant accessibility improvements with minimal effort:
593
+
594
+ 1. **Replace `aria-disabled` with native `disabled`** in Input, Select, and Textarea
595
+ - **Time:** 5 minutes
596
+ - **Impact:** Critical - fixes keyboard trap vulnerability
597
+
598
+ 2. **Remove redundant `role="form"` and `role="option"`**
599
+ - **Time:** 2 minutes
600
+ - **Impact:** High - eliminates ARIA violations
601
+
602
+ 3. **Add validation ARIA to Select and Textarea** (copy pattern from Input)
603
+ - **Time:** 15 minutes
604
+ - **Impact:** Critical - enables error announcement for screen readers
605
+
606
+ 4. **Add `aria-label` to FormProps TypeScript interface**
607
+ - **Time:** 5 minutes
608
+ - **Impact:** Medium - improves form landmark navigation
609
+
610
+ **Total implementation time: ~30 minutes for major compliance improvements**
611
+
612
+ ---
613
+
614
+ ## Implementation Priority
615
+
616
+ ### Priority 1 (Critical - Fix Immediately)
617
+ 1. Replace `aria-disabled` with native `disabled` attribute
618
+ 2. Add validation ARIA to Select and Textarea components
619
+
620
+ ### Priority 2 (High - Fix Before Release)
621
+ 3. Remove redundant ARIA roles
622
+ 4. Add form accessible name requirement
623
+
624
+ ### Priority 3 (Medium - Next Sprint)
625
+ 5. Make `labelFor` required in Field component
626
+ 6. Add autoFocus JSDoc warning
627
+ 7. Add autocomplete JSDoc guidance
628
+
629
+ ### Priority 4 (Low - Future Enhancement)
630
+ 8. Add error summary pattern example to docs
631
+ 9. Add runtime warnings for missing accessibility attributes
632
+
633
+ ---
634
+
635
+ ## Additional Resources
636
+
637
+ - [WCAG 2.1 Quick Reference](https://www.w3.org/WAI/WCAG21/quickref/?versions=2.1&levels=aa)
638
+ - [ARIA Authoring Practices Guide - Forms](https://www.w3.org/WAI/ARIA/apg/patterns/)
639
+ - [WebAIM: Creating Accessible Forms](https://webaim.org/techniques/forms/)
640
+ - [MDN: ARIA Form Role](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/form_role)
641
+
642
+ ---
643
+
644
+ ## Review Summary
645
+
646
+ **Overall Assessment:** The form components are well-architected with strong accessibility foundations. The critical issues identified are straightforward to fix and mostly involve replacing ARIA attributes with native HTML attributes. Once these issues are addressed, the components will be fully WCAG 2.1 AA compliant.
647
+
648
+ **Reviewer Confidence:** High - All issues have clear fixes with code examples provided.
649
+
650
+ **Next Steps:**
651
+ 1. Address the 4 critical errors
652
+ 2. Run automated tests with jest-axe
653
+ 3. Perform manual keyboard and screen reader testing
654
+ 4. Update Storybook examples to demonstrate accessible usage patterns
@@ -6,12 +6,21 @@ export type FieldProps = {
6
6
  * The label content
7
7
  */
8
8
  label: React.ReactNode
9
+ /**
10
+ * ID of the associated form control (REQUIRED for accessibility)
11
+ * Must match the id of the child input/select/textarea element.
12
+ * This ensures proper label-to-input association for screen readers.
13
+ * @example "email-input"
14
+ * @see {@link https://www.w3.org/WAI/WCAG21/Understanding/labels-or-instructions.html|WCAG 3.3.2 Labels or Instructions}
15
+ */
16
+ labelFor: string
9
17
  children: React.ReactNode
10
18
  } & React.ComponentProps<'label'> &
11
19
  Partial<React.ComponentProps<typeof UI>>
12
20
  /**
13
21
  * Field component that renders a label and children wrapped in a div element.
14
- * @param labelFor Defines the for attribute of the label element
22
+ * Ensures proper accessibility by requiring the labelFor prop to associate labels with form controls.
23
+ * @param labelFor Defines the for attribute of the label element (REQUIRED)
15
24
  * @param styles Custom styles to be applied to the component
16
25
  * @param label The label content
17
26
  * @param children The children to be rendered inside the component