@boostdev/design-system-components 2.7.1 → 2.11.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 (535) hide show
  1. package/AGENTS.md +54 -46
  2. package/README.md +34 -20
  3. package/dist/client.cjs +1317 -779
  4. package/dist/client.css +1029 -812
  5. package/dist/client.d.cts +88 -26
  6. package/dist/client.d.ts +88 -26
  7. package/dist/client.js +1278 -732
  8. package/dist/index.cjs +1317 -779
  9. package/dist/index.css +1029 -812
  10. package/dist/index.d.cts +88 -26
  11. package/dist/index.d.ts +88 -26
  12. package/dist/index.js +1278 -732
  13. package/dist/web-components/chunk-2OLVQUBU.js +193 -0
  14. package/dist/web-components/chunk-3AY2YKCM.js +223 -0
  15. package/dist/web-components/chunk-3WAV6MDN.js +212 -0
  16. package/dist/web-components/{chunk-CZBIVR4V.js → chunk-47AT5KZD.js} +88 -16
  17. package/dist/web-components/chunk-4A2YYTYN.js +93 -0
  18. package/dist/web-components/{chunk-Q4T5BJT6.js → chunk-62NK3ZSC.js} +18 -3
  19. package/dist/web-components/chunk-66M6ETWD.js +77 -0
  20. package/dist/web-components/{chunk-NCPQ7AF3.js → chunk-6G22I2CK.js} +18 -3
  21. package/dist/web-components/{chunk-QDST57JC.js → chunk-7ZOJ7N4E.js} +14 -4
  22. package/dist/web-components/{chunk-5R6IFELV.js → chunk-AIBOHNDU.js} +11 -1
  23. package/dist/web-components/{chunk-ITHLKR7Q.js → chunk-AP4RDUL2.js} +16 -5
  24. package/dist/web-components/{chunk-QWPACK5L.js → chunk-BPYKZVDK.js} +11 -1
  25. package/dist/web-components/{chunk-YLVTEY23.js → chunk-BTCMJQKB.js} +53 -21
  26. package/dist/web-components/chunk-CUKQ2L5B.js +245 -0
  27. package/dist/web-components/chunk-DIZDCL7Z.js +14 -0
  28. package/dist/web-components/{chunk-PC3IOQAH.js → chunk-DV5T43ZC.js} +27 -7
  29. package/dist/web-components/{chunk-2QA62WCQ.js → chunk-EF7IVYTY.js} +10 -0
  30. package/dist/web-components/{chunk-L3XHOMN6.js → chunk-F3ZDNHZZ.js} +26 -1
  31. package/dist/web-components/chunk-FEDABOR5.js +248 -0
  32. package/dist/web-components/{chunk-6I2DBFQ7.js → chunk-HGFCJXOQ.js} +36 -5
  33. package/dist/web-components/{chunk-SOQQ7RVJ.js → chunk-IPGHUCJT.js} +23 -8
  34. package/dist/web-components/chunk-ITD2MV5K.js +392 -0
  35. package/dist/web-components/{chunk-CM3KYZ6Z.js → chunk-JH6LQKLK.js} +78 -6
  36. package/dist/web-components/chunk-JMCXAAFK.js +120 -0
  37. package/dist/web-components/{chunk-KUI55GFB.js → chunk-JUPCZVVW.js} +50 -18
  38. package/dist/web-components/chunk-JV5QT2OU.js +146 -0
  39. package/dist/web-components/{chunk-3GFWLSLS.js → chunk-KA3VPKMY.js} +29 -6
  40. package/dist/web-components/{chunk-CR5PGUHV.js → chunk-KJGRFDFI.js} +26 -11
  41. package/dist/web-components/{chunk-PY62FTRW.js → chunk-KZPRFY5P.js} +68 -33
  42. package/dist/web-components/{chunk-X46KL5BK.js → chunk-LDIPCTRN.js} +18 -1
  43. package/dist/web-components/chunk-M3ECULRH.js +174 -0
  44. package/dist/web-components/chunk-NBN2ENWJ.js +90 -0
  45. package/dist/web-components/chunk-NIN3JO6Q.js +189 -0
  46. package/dist/web-components/{chunk-2FGATTGT.js → chunk-NTQ4TCUT.js} +76 -55
  47. package/dist/web-components/chunk-OY74D4X6.js +302 -0
  48. package/dist/web-components/{chunk-3S42DZ7W.js → chunk-P24JYC5V.js} +7 -0
  49. package/dist/web-components/{chunk-BKIHQYJR.js → chunk-PXPPKCLT.js} +17 -2
  50. package/dist/web-components/{chunk-TQ7IQ4GZ.js → chunk-QEF2IRID.js} +71 -29
  51. package/dist/web-components/chunk-QZAIRJ75.js +111 -0
  52. package/dist/web-components/{chunk-6I3CFC26.js → chunk-RSZ3BWBK.js} +20 -5
  53. package/dist/web-components/chunk-RVF7W653.js +101 -0
  54. package/dist/web-components/chunk-SEO2F5KJ.js +234 -0
  55. package/dist/web-components/{chunk-VMMVWLXL.js → chunk-SFZ6Q4BP.js} +10 -0
  56. package/dist/web-components/{chunk-LY62SAVN.js → chunk-SYNLFKD3.js} +12 -2
  57. package/dist/web-components/chunk-TMWXRHGF.js +192 -0
  58. package/dist/web-components/{chunk-65JXQOBA.js → chunk-U3YZE6R6.js} +51 -7
  59. package/dist/web-components/chunk-UO7ROSHD.js +424 -0
  60. package/dist/web-components/chunk-VANAKB6D.js +152 -0
  61. package/dist/web-components/{chunk-PXZWYO6Z.js → chunk-VED2DFJ6.js} +108 -29
  62. package/dist/web-components/chunk-W6H5ID2U.js +161 -0
  63. package/dist/web-components/{chunk-57TRNCWQ.js → chunk-WFVKU4GX.js} +22 -11
  64. package/dist/web-components/{chunk-OQTRTMAB.js → chunk-WIBAN7KP.js} +10 -0
  65. package/dist/web-components/chunk-XI7KRAH7.js +54 -0
  66. package/dist/web-components/{chunk-F5E3IT7G.js → chunk-XIZWAWMJ.js} +50 -11
  67. package/dist/web-components/{chunk-FXURM6D5.js → chunk-YFAXGRPR.js} +10 -0
  68. package/dist/web-components/globals.js +1 -1
  69. package/dist/web-components/index.d.ts +77 -707
  70. package/dist/web-components/index.js +339 -2066
  71. package/dist/web-components/interaction/bds-accordion-item.js +1 -1
  72. package/dist/web-components/interaction/bds-accordion.js +1 -1
  73. package/dist/web-components/interaction/bds-button.d.ts +10 -2
  74. package/dist/web-components/interaction/bds-button.js +1 -1
  75. package/dist/web-components/interaction/bds-collapsible.d.ts +7 -2
  76. package/dist/web-components/interaction/bds-collapsible.js +1 -1
  77. package/dist/web-components/interaction/bds-dialog.d.ts +11 -3
  78. package/dist/web-components/interaction/bds-dialog.js +1 -1
  79. package/dist/web-components/interaction/bds-drawer.d.ts +7 -1
  80. package/dist/web-components/interaction/bds-drawer.js +1 -1
  81. package/dist/web-components/interaction/bds-dropdown-menu-item.d.ts +51 -0
  82. package/dist/web-components/interaction/bds-dropdown-menu-item.js +7 -0
  83. package/dist/web-components/interaction/bds-dropdown-menu.d.ts +70 -0
  84. package/dist/web-components/interaction/bds-dropdown-menu.js +7 -0
  85. package/dist/web-components/interaction/bds-popover.d.ts +14 -3
  86. package/dist/web-components/interaction/bds-popover.js +1 -1
  87. package/dist/web-components/interaction/bds-skip-link.js +1 -1
  88. package/dist/web-components/interaction/bds-tab-panel.js +1 -1
  89. package/dist/web-components/interaction/bds-tab.js +1 -1
  90. package/dist/web-components/interaction/bds-tabs.d.ts +1 -0
  91. package/dist/web-components/interaction/bds-tabs.js +1 -1
  92. package/dist/web-components/interaction/bds-toast-provider.js +1 -1
  93. package/dist/web-components/interaction/bds-tooltip.d.ts +19 -3
  94. package/dist/web-components/interaction/bds-tooltip.js +1 -1
  95. package/dist/web-components/interaction/form/bds-checkbox-group.d.ts +83 -0
  96. package/dist/web-components/interaction/form/bds-checkbox-group.js +7 -0
  97. package/dist/web-components/interaction/form/bds-checkbox.d.ts +6 -0
  98. package/dist/web-components/interaction/form/bds-checkbox.js +1 -1
  99. package/dist/web-components/interaction/form/bds-combobox.d.ts +18 -0
  100. package/dist/web-components/interaction/form/bds-combobox.js +1 -1
  101. package/dist/web-components/interaction/form/bds-field-group.d.ts +89 -0
  102. package/dist/web-components/interaction/form/bds-field-group.js +7 -0
  103. package/dist/web-components/interaction/form/bds-file-input.d.ts +1 -1
  104. package/dist/web-components/interaction/form/bds-file-input.js +1 -1
  105. package/dist/web-components/interaction/form/bds-form-input.d.ts +92 -0
  106. package/dist/web-components/interaction/form/bds-form-input.js +7 -0
  107. package/dist/web-components/interaction/form/bds-number-input.d.ts +18 -1
  108. package/dist/web-components/interaction/form/bds-number-input.js +1 -1
  109. package/dist/web-components/interaction/form/bds-radio-group.d.ts +81 -0
  110. package/dist/web-components/interaction/form/bds-radio-group.js +7 -0
  111. package/dist/web-components/interaction/form/bds-radio.d.ts +34 -6
  112. package/dist/web-components/interaction/form/bds-radio.js +1 -1
  113. package/dist/web-components/interaction/form/bds-segmented-control.d.ts +4 -4
  114. package/dist/web-components/interaction/form/bds-segmented-control.js +1 -1
  115. package/dist/web-components/interaction/form/bds-select.d.ts +22 -1
  116. package/dist/web-components/interaction/form/bds-select.js +1 -1
  117. package/dist/web-components/interaction/form/bds-slider.d.ts +42 -10
  118. package/dist/web-components/interaction/form/bds-slider.js +1 -1
  119. package/dist/web-components/interaction/form/bds-switch.d.ts +20 -0
  120. package/dist/web-components/interaction/form/bds-switch.js +1 -1
  121. package/dist/web-components/interaction/form/bds-textarea.d.ts +23 -3
  122. package/dist/web-components/interaction/form/bds-textarea.js +1 -1
  123. package/dist/web-components/layout/bds-grid-item.d.ts +63 -0
  124. package/dist/web-components/layout/bds-grid-item.js +7 -0
  125. package/dist/web-components/layout/bds-grid.d.ts +108 -0
  126. package/dist/web-components/layout/bds-grid.js +7 -0
  127. package/dist/web-components/ui/bds-alert.d.ts +16 -2
  128. package/dist/web-components/ui/bds-alert.js +1 -1
  129. package/dist/web-components/ui/bds-avatar.d.ts +2 -1
  130. package/dist/web-components/ui/bds-avatar.js +1 -1
  131. package/dist/web-components/ui/bds-badge.js +1 -1
  132. package/dist/web-components/ui/bds-breadcrumb.d.ts +3 -1
  133. package/dist/web-components/ui/bds-breadcrumb.js +1 -1
  134. package/dist/web-components/ui/bds-button-container.d.ts +52 -0
  135. package/dist/web-components/ui/bds-button-container.js +7 -0
  136. package/dist/web-components/ui/bds-button-group.d.ts +21 -0
  137. package/dist/web-components/ui/bds-button-group.js +8 -0
  138. package/dist/web-components/ui/bds-calendar.d.ts +121 -0
  139. package/dist/web-components/ui/bds-calendar.js +7 -0
  140. package/dist/web-components/ui/bds-card.d.ts +12 -3
  141. package/dist/web-components/ui/bds-card.js +1 -1
  142. package/dist/web-components/ui/bds-carousel.d.ts +98 -0
  143. package/dist/web-components/ui/bds-carousel.js +7 -0
  144. package/dist/web-components/ui/bds-description-list.js +1 -1
  145. package/dist/web-components/ui/bds-icon-wrapper.d.ts +0 -9
  146. package/dist/web-components/ui/bds-icon-wrapper.js +1 -1
  147. package/dist/web-components/ui/bds-link.js +1 -1
  148. package/dist/web-components/ui/bds-loading.js +1 -1
  149. package/dist/web-components/ui/bds-notification-banner.js +1 -1
  150. package/dist/web-components/ui/bds-pagination.d.ts +47 -0
  151. package/dist/web-components/ui/bds-pagination.js +7 -0
  152. package/dist/web-components/ui/bds-progress-circle.d.ts +3 -1
  153. package/dist/web-components/ui/bds-progress-circle.js +1 -1
  154. package/dist/web-components/ui/bds-progress.d.ts +3 -1
  155. package/dist/web-components/ui/bds-progress.js +1 -1
  156. package/dist/web-components/ui/bds-rating.js +1 -1
  157. package/dist/web-components/ui/bds-section-header.d.ts +18 -4
  158. package/dist/web-components/ui/bds-section-header.js +1 -1
  159. package/dist/web-components/ui/bds-separator.js +1 -1
  160. package/dist/web-components/ui/bds-skeleton.js +1 -1
  161. package/dist/web-components/ui/bds-table.d.ts +52 -0
  162. package/dist/web-components/ui/bds-table.js +7 -0
  163. package/dist/web-components/ui/bds-typography.d.ts +1 -0
  164. package/dist/web-components/ui/bds-typography.js +1 -1
  165. package/package.json +60 -3
  166. package/src/components/interaction/Button/Button.module.css +23 -14
  167. package/src/components/interaction/Button/Button.spec.tsx +20 -0
  168. package/src/components/interaction/Button/Button.tsx +2 -2
  169. package/src/components/interaction/Command/Command.mdx +5 -2
  170. package/src/components/interaction/Command/Command.module.css +23 -7
  171. package/src/components/interaction/Command/Command.spec.tsx +35 -0
  172. package/src/components/interaction/Command/Command.tsx +15 -4
  173. package/src/components/interaction/Command/index.ts +1 -1
  174. package/src/components/interaction/Dialog/Dialog.mdx +4 -4
  175. package/src/components/interaction/Dialog/Dialog.module.css +20 -0
  176. package/src/components/interaction/Dialog/Dialog.spec.tsx +20 -0
  177. package/src/components/interaction/Dialog/Dialog.tsx +8 -3
  178. package/src/components/interaction/Dialog/index.ts +1 -0
  179. package/src/components/interaction/Drawer/Drawer.mdx +5 -2
  180. package/src/components/interaction/Drawer/Drawer.module.css +34 -3
  181. package/src/components/interaction/Drawer/Drawer.spec.tsx +67 -1
  182. package/src/components/interaction/Drawer/Drawer.tsx +30 -12
  183. package/src/components/interaction/Drawer/index.ts +1 -0
  184. package/src/components/interaction/DropdownMenu/DropdownMenu.mdx +2 -0
  185. package/src/components/interaction/DropdownMenu/DropdownMenu.spec.tsx +34 -0
  186. package/src/components/interaction/DropdownMenu/DropdownMenu.tsx +15 -5
  187. package/src/components/interaction/DropdownMenu/index.ts +1 -0
  188. package/src/components/interaction/Popover/Popover.mdx +6 -2
  189. package/src/components/interaction/Popover/Popover.module.css +26 -18
  190. package/src/components/interaction/Popover/Popover.spec.tsx +38 -0
  191. package/src/components/interaction/Popover/Popover.tsx +19 -5
  192. package/src/components/interaction/Popover/index.ts +1 -0
  193. package/src/components/interaction/Rating/Rating.mdx +1 -1
  194. package/src/components/interaction/Rating/Rating.module.css +2 -2
  195. package/src/components/interaction/Rating/Rating.tsx +1 -1
  196. package/src/components/interaction/Rating/index.ts +1 -0
  197. package/src/components/interaction/Toast/Toast.mdx +3 -0
  198. package/src/components/interaction/Toast/Toast.module.css +35 -5
  199. package/src/components/interaction/Toast/Toast.spec.tsx +69 -1
  200. package/src/components/interaction/Toast/Toast.tsx +15 -9
  201. package/src/components/interaction/form/Checkbox/Checkbox.mdx +3 -0
  202. package/src/components/interaction/form/Checkbox/Checkbox.module.css +13 -6
  203. package/src/components/interaction/form/Checkbox/Checkbox.spec.tsx +6 -0
  204. package/src/components/interaction/form/Checkbox/Checkbox.tsx +1 -1
  205. package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.mdx +16 -1
  206. package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.module.css +24 -8
  207. package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.spec.tsx +32 -2
  208. package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.tsx +14 -2
  209. package/src/components/interaction/form/Combobox/Combobox.mdx +11 -4
  210. package/src/components/interaction/form/Combobox/Combobox.module.css +6 -6
  211. package/src/components/interaction/form/Combobox/Combobox.spec.tsx +47 -0
  212. package/src/components/interaction/form/Combobox/Combobox.tsx +10 -5
  213. package/src/components/interaction/form/FieldGroup/FieldGroup.mdx +9 -10
  214. package/src/components/interaction/form/FieldGroup/FieldGroup.module.css +57 -23
  215. package/src/components/interaction/form/FieldGroup/FieldGroup.spec.tsx +129 -7
  216. package/src/components/interaction/form/FieldGroup/FieldGroup.tsx +72 -12
  217. package/src/components/interaction/form/FileInput/FileInput.mdx +9 -1
  218. package/src/components/interaction/form/FileInput/FileInput.module.css +8 -8
  219. package/src/components/interaction/form/FileInput/FileInput.spec.tsx +89 -1
  220. package/src/components/interaction/form/FileInput/FileInput.tsx +6 -2
  221. package/src/components/interaction/form/FormInput/FormInput.mdx +9 -5
  222. package/src/components/interaction/form/FormInput/FormInput.module.css +17 -8
  223. package/src/components/interaction/form/FormInput/FormInput.spec.tsx +20 -0
  224. package/src/components/interaction/form/FormInput/FormInput.tsx +7 -2
  225. package/src/components/interaction/form/NumberInput/NumberInput.mdx +5 -1
  226. package/src/components/interaction/form/NumberInput/NumberInput.module.css +6 -6
  227. package/src/components/interaction/form/NumberInput/NumberInput.spec.tsx +51 -0
  228. package/src/components/interaction/form/NumberInput/NumberInput.tsx +36 -8
  229. package/src/components/interaction/form/Radio/Radio.mdx +8 -1
  230. package/src/components/interaction/form/Radio/Radio.module.css +20 -7
  231. package/src/components/interaction/form/Radio/Radio.spec.tsx +15 -0
  232. package/src/components/interaction/form/Radio/Radio.tsx +10 -4
  233. package/src/components/interaction/form/RadioGroup/RadioGroup.mdx +16 -1
  234. package/src/components/interaction/form/RadioGroup/RadioGroup.module.css +24 -8
  235. package/src/components/interaction/form/RadioGroup/RadioGroup.spec.tsx +32 -2
  236. package/src/components/interaction/form/RadioGroup/RadioGroup.tsx +14 -2
  237. package/src/components/interaction/form/SegmentedControl/SegmentedControl.mdx +9 -3
  238. package/src/components/interaction/form/SegmentedControl/SegmentedControl.module.css +25 -12
  239. package/src/components/interaction/form/SegmentedControl/SegmentedControl.spec.tsx +86 -5
  240. package/src/components/interaction/form/SegmentedControl/SegmentedControl.tsx +44 -4
  241. package/src/components/interaction/form/Select/Select.mdx +10 -4
  242. package/src/components/interaction/form/Select/Select.module.css +4 -4
  243. package/src/components/interaction/form/Select/Select.spec.tsx +34 -0
  244. package/src/components/interaction/form/Select/Select.tsx +21 -9
  245. package/src/components/interaction/form/Slider/Slider.mdx +4 -1
  246. package/src/components/interaction/form/Slider/Slider.module.css +32 -8
  247. package/src/components/interaction/form/Slider/Slider.spec.tsx +29 -0
  248. package/src/components/interaction/form/Slider/Slider.tsx +9 -7
  249. package/src/components/interaction/form/Switch/Switch.mdx +2 -2
  250. package/src/components/interaction/form/Switch/Switch.module.css +12 -13
  251. package/src/components/interaction/form/Switch/Switch.spec.tsx +20 -0
  252. package/src/components/interaction/form/Switch/Switch.tsx +2 -1
  253. package/src/components/interaction/form/Textarea/Textarea.mdx +5 -0
  254. package/src/components/interaction/form/Textarea/Textarea.module.css +5 -5
  255. package/src/components/interaction/form/Textarea/Textarea.spec.tsx +13 -0
  256. package/src/components/interaction/form/Textarea/Textarea.tsx +3 -1
  257. package/src/components/interaction/form/atoms/Message.module.css +1 -1
  258. package/src/components/interaction/form/atoms/Message.spec.tsx +29 -0
  259. package/src/components/interaction/form/atoms/Message.tsx +1 -1
  260. package/src/components/layout/ButtonGroup/ButtonGroup.mdx +11 -0
  261. package/src/components/layout/ButtonGroup/ButtonGroup.module.css +1 -5
  262. package/src/components/layout/ButtonGroup/ButtonGroup.stories.tsx +14 -0
  263. package/src/components/layout/Card/Card.mdx +6 -1
  264. package/src/components/layout/Card/Card.module.css +26 -5
  265. package/src/components/layout/Card/Card.spec.tsx +7 -0
  266. package/src/components/layout/Card/Card.tsx +4 -3
  267. package/src/components/layout/Grid/Grid.spec.tsx +44 -0
  268. package/src/components/layout/Grid/Grid.tsx +5 -5
  269. package/src/components/layout/Grid/GridItem.tsx +6 -6
  270. package/src/components/layout/Grid/masonry.ts +31 -5
  271. package/src/components/layout/Grid/useIsomorphicLayoutEffect.ts +11 -0
  272. package/src/components/layout/IconWrapper/IconWrapper.mdx +8 -2
  273. package/src/components/layout/IconWrapper/IconWrapper.module.css +9 -6
  274. package/src/components/layout/SectionHeader/SectionHeader.mdx +4 -1
  275. package/src/components/layout/SectionHeader/SectionHeader.module.css +10 -9
  276. package/src/components/ui/Accordion/Accordion.mdx +4 -1
  277. package/src/components/ui/Accordion/Accordion.module.css +2 -1
  278. package/src/components/ui/Alert/Alert.mdx +21 -4
  279. package/src/components/ui/Alert/Alert.module.css +9 -4
  280. package/src/components/ui/Alert/Alert.spec.tsx +20 -0
  281. package/src/components/ui/Avatar/Avatar.mdx +8 -3
  282. package/src/components/ui/Avatar/Avatar.module.css +13 -8
  283. package/src/components/ui/Badge/Badge.mdx +3 -1
  284. package/src/components/ui/Breadcrumb/Breadcrumb.mdx +3 -0
  285. package/src/components/ui/Breadcrumb/Breadcrumb.module.css +4 -0
  286. package/src/components/ui/Breadcrumb/Breadcrumb.spec.tsx +12 -0
  287. package/src/components/ui/Breadcrumb/Breadcrumb.tsx +11 -3
  288. package/src/components/ui/Calendar/Calendar.mdx +6 -0
  289. package/src/components/ui/Calendar/Calendar.module.css +68 -19
  290. package/src/components/ui/Calendar/Calendar.spec.tsx +139 -24
  291. package/src/components/ui/Calendar/Calendar.stories.tsx +14 -0
  292. package/src/components/ui/Calendar/Calendar.tsx +143 -154
  293. package/src/components/ui/Calendar/CalendarRange.mdx +39 -0
  294. package/src/components/ui/Calendar/CalendarRange.spec.tsx +119 -0
  295. package/src/components/ui/Calendar/CalendarRange.stories.tsx +51 -0
  296. package/src/components/ui/Calendar/CalendarRange.tsx +213 -0
  297. package/src/components/ui/Calendar/MonthGrid.tsx +141 -0
  298. package/src/components/ui/Calendar/calendar-core.spec.ts +176 -0
  299. package/src/components/ui/Calendar/calendar-core.ts +164 -0
  300. package/src/components/ui/Calendar/index.ts +1 -0
  301. package/src/components/ui/Carousel/Carousel.mdx +8 -3
  302. package/src/components/ui/Carousel/Carousel.module.css +7 -5
  303. package/src/components/ui/Carousel/Carousel.spec.tsx +67 -0
  304. package/src/components/ui/Carousel/Carousel.tsx +19 -7
  305. package/src/components/ui/Collapsible/Collapsible.mdx +17 -6
  306. package/src/components/ui/Collapsible/Collapsible.module.css +7 -2
  307. package/src/components/ui/Collapsible/Collapsible.spec.tsx +40 -0
  308. package/src/components/ui/Collapsible/Collapsible.tsx +19 -2
  309. package/src/components/ui/DescriptionList/DescriptionList.mdx +2 -0
  310. package/src/components/ui/Link/Link.mdx +4 -2
  311. package/src/components/ui/Loading/Loading.mdx +6 -3
  312. package/src/components/ui/Loading/Loading.module.css +7 -7
  313. package/src/components/ui/Loading/Loading.spec.tsx +12 -0
  314. package/src/components/ui/Loading/Loading.tsx +8 -3
  315. package/src/components/ui/NotificationBanner/NotificationBanner.mdx +4 -0
  316. package/src/components/ui/NotificationBanner/NotificationBanner.module.css +5 -0
  317. package/src/components/ui/NotificationBanner/NotificationBanner.spec.tsx +20 -0
  318. package/src/components/ui/Pagination/Pagination.mdx +29 -7
  319. package/src/components/ui/Pagination/Pagination.module.css +15 -14
  320. package/src/components/ui/Progress/Progress.mdx +6 -2
  321. package/src/components/ui/Progress/Progress.module.css +1 -1
  322. package/src/components/ui/Progress/Progress.spec.tsx +17 -0
  323. package/src/components/ui/Progress/Progress.tsx +2 -2
  324. package/src/components/ui/ProgressCircle/ProgressCircle.mdx +8 -4
  325. package/src/components/ui/ProgressCircle/ProgressCircle.module.css +2 -2
  326. package/src/components/ui/ProgressCircle/ProgressCircle.spec.tsx +11 -1
  327. package/src/components/ui/ProgressCircle/ProgressCircle.tsx +1 -1
  328. package/src/components/ui/Separator/Separator.mdx +7 -0
  329. package/src/components/ui/Separator/Separator.module.css +1 -0
  330. package/src/components/ui/Skeleton/Skeleton.mdx +17 -0
  331. package/src/components/ui/Skeleton/Skeleton.module.css +12 -5
  332. package/src/components/ui/SkipLink/SkipLink.mdx +19 -0
  333. package/src/components/ui/SkipLink/SkipLink.module.css +8 -7
  334. package/src/components/ui/SkipLink/SkipLink.spec.tsx +28 -0
  335. package/src/components/ui/Table/Table.mdx +14 -0
  336. package/src/components/ui/Table/Table.module.css +13 -8
  337. package/src/components/ui/Table/Table.spec.tsx +56 -0
  338. package/src/components/ui/Table/Table.tsx +44 -6
  339. package/src/components/ui/Tabs/Tabs.mdx +16 -0
  340. package/src/components/ui/Tabs/Tabs.module.css +3 -3
  341. package/src/components/ui/Tabs/Tabs.spec.tsx +20 -0
  342. package/src/components/ui/Tabs/Tabs.tsx +5 -1
  343. package/src/components/ui/Tooltip/Tooltip.mdx +9 -0
  344. package/src/components/ui/Tooltip/Tooltip.module.css +32 -12
  345. package/src/components/ui/Tooltip/Tooltip.spec.tsx +56 -0
  346. package/src/components/ui/Tooltip/Tooltip.tsx +26 -7
  347. package/src/components/ui/Typography/Typography.mdx +7 -0
  348. package/src/components/ui/Typography/Typography.module.css +5 -5
  349. package/src/index.ts +7 -3
  350. package/src/stories/DesignSystem/Borders.mdx +14 -9
  351. package/src/stories/DesignSystem/Colors.mdx +43 -41
  352. package/src/stories/DesignSystem/Overview.mdx +4 -3
  353. package/src/stories/Introduction.mdx +5 -5
  354. package/src/web-components/globals.ts +7 -0
  355. package/src/web-components/index.ts +2 -0
  356. package/src/web-components/interaction/BdsAccordion.mdx +10 -1
  357. package/src/web-components/interaction/BdsButton.mdx +15 -4
  358. package/src/web-components/interaction/BdsButton.stories.tsx +1 -1
  359. package/src/web-components/interaction/BdsCollapsible.mdx +3 -3
  360. package/src/web-components/interaction/BdsDialog.mdx +12 -7
  361. package/src/web-components/interaction/BdsDialog.stories.tsx +2 -2
  362. package/src/web-components/interaction/BdsDrawer.mdx +9 -6
  363. package/src/web-components/interaction/BdsDropdownMenu.mdx +20 -1
  364. package/src/web-components/interaction/BdsPopover.mdx +7 -3
  365. package/src/web-components/interaction/BdsSkipLink.mdx +14 -1
  366. package/src/web-components/interaction/BdsTabs.mdx +18 -1
  367. package/src/web-components/interaction/BdsToastProvider.mdx +21 -3
  368. package/src/web-components/interaction/BdsTooltip.mdx +4 -4
  369. package/src/web-components/interaction/bds-accordion-item.ts +10 -0
  370. package/src/web-components/interaction/bds-accordion.spec.ts +41 -0
  371. package/src/web-components/interaction/bds-accordion.ts +28 -2
  372. package/src/web-components/interaction/bds-button.spec.ts +81 -0
  373. package/src/web-components/interaction/bds-button.ts +60 -13
  374. package/src/web-components/interaction/bds-collapsible.spec.ts +93 -2
  375. package/src/web-components/interaction/bds-collapsible.ts +49 -7
  376. package/src/web-components/interaction/bds-dialog.spec.ts +49 -0
  377. package/src/web-components/interaction/bds-dialog.ts +68 -11
  378. package/src/web-components/interaction/bds-drawer.spec.ts +93 -4
  379. package/src/web-components/interaction/bds-drawer.ts +54 -21
  380. package/src/web-components/interaction/bds-dropdown-menu-item.ts +12 -1
  381. package/src/web-components/interaction/bds-dropdown-menu.spec.ts +63 -0
  382. package/src/web-components/interaction/bds-dropdown-menu.ts +45 -7
  383. package/src/web-components/interaction/bds-popover.spec.ts +80 -6
  384. package/src/web-components/interaction/bds-popover.ts +83 -32
  385. package/src/web-components/interaction/bds-skip-link.spec.ts +18 -0
  386. package/src/web-components/interaction/bds-skip-link.ts +29 -8
  387. package/src/web-components/interaction/bds-tab-panel.ts +10 -0
  388. package/src/web-components/interaction/bds-tab.spec.ts +25 -0
  389. package/src/web-components/interaction/bds-tab.ts +20 -5
  390. package/src/web-components/interaction/bds-tabs.spec.ts +92 -5
  391. package/src/web-components/interaction/bds-tabs.ts +42 -1
  392. package/src/web-components/interaction/bds-toast-provider.spec.ts +43 -0
  393. package/src/web-components/interaction/bds-toast-provider.ts +50 -21
  394. package/src/web-components/interaction/bds-tooltip.spec.ts +71 -0
  395. package/src/web-components/interaction/bds-tooltip.ts +100 -5
  396. package/src/web-components/interaction/form/BdsCheckbox.mdx +20 -1
  397. package/src/web-components/interaction/form/BdsCheckbox.stories.tsx +8 -0
  398. package/src/web-components/interaction/form/BdsCheckboxGroup.mdx +4 -3
  399. package/src/web-components/interaction/form/BdsCombobox.mdx +39 -2
  400. package/src/web-components/interaction/form/BdsCombobox.stories.tsx +31 -0
  401. package/src/web-components/interaction/form/BdsFieldGroup.mdx +8 -3
  402. package/src/web-components/interaction/form/BdsFieldGroup.stories.tsx +1 -1
  403. package/src/web-components/interaction/form/BdsFileInput.mdx +26 -5
  404. package/src/web-components/interaction/form/BdsFormInput.mdx +16 -1
  405. package/src/web-components/interaction/form/BdsNumberInput.mdx +34 -2
  406. package/src/web-components/interaction/form/BdsNumberInput.stories.tsx +27 -3
  407. package/src/web-components/interaction/form/BdsRadio.mdx +39 -12
  408. package/src/web-components/interaction/form/BdsRadio.stories.tsx +26 -0
  409. package/src/web-components/interaction/form/BdsRadioGroup.mdx +9 -4
  410. package/src/web-components/interaction/form/BdsSegmentedControl.mdx +37 -11
  411. package/src/web-components/interaction/form/BdsSelect.mdx +22 -4
  412. package/src/web-components/interaction/form/BdsSelect.stories.tsx +33 -0
  413. package/src/web-components/interaction/form/BdsSlider.mdx +36 -19
  414. package/src/web-components/interaction/form/BdsSlider.stories.tsx +24 -0
  415. package/src/web-components/interaction/form/BdsSwitch.mdx +38 -11
  416. package/src/web-components/interaction/form/BdsSwitch.stories.tsx +16 -0
  417. package/src/web-components/interaction/form/BdsTextarea.mdx +42 -16
  418. package/src/web-components/interaction/form/BdsTextarea.stories.tsx +21 -0
  419. package/src/web-components/interaction/form/bds-checkbox-group.spec.ts +99 -0
  420. package/src/web-components/interaction/form/bds-checkbox-group.ts +95 -9
  421. package/src/web-components/interaction/form/bds-checkbox.spec.ts +55 -0
  422. package/src/web-components/interaction/form/bds-checkbox.ts +30 -5
  423. package/src/web-components/interaction/form/bds-combobox.spec.ts +79 -0
  424. package/src/web-components/interaction/form/bds-combobox.ts +102 -17
  425. package/src/web-components/interaction/form/bds-field-group.spec.ts +158 -0
  426. package/src/web-components/interaction/form/bds-field-group.ts +167 -23
  427. package/src/web-components/interaction/form/bds-file-input.spec.ts +73 -5
  428. package/src/web-components/interaction/form/bds-file-input.ts +71 -34
  429. package/src/web-components/interaction/form/bds-form-input.spec.ts +22 -0
  430. package/src/web-components/interaction/form/bds-form-input.ts +27 -16
  431. package/src/web-components/interaction/form/bds-number-input.spec.ts +49 -0
  432. package/src/web-components/interaction/form/bds-number-input.ts +118 -29
  433. package/src/web-components/interaction/form/bds-radio-group.spec.ts +57 -0
  434. package/src/web-components/interaction/form/bds-radio-group.ts +60 -12
  435. package/src/web-components/interaction/form/bds-radio.spec.ts +123 -0
  436. package/src/web-components/interaction/form/bds-radio.ts +136 -23
  437. package/src/web-components/interaction/form/bds-segmented-control.spec.ts +55 -0
  438. package/src/web-components/interaction/form/bds-segmented-control.ts +81 -59
  439. package/src/web-components/interaction/form/bds-select.spec.ts +57 -0
  440. package/src/web-components/interaction/form/bds-select.ts +96 -8
  441. package/src/web-components/interaction/form/bds-slider.spec.ts +83 -0
  442. package/src/web-components/interaction/form/bds-slider.ts +181 -33
  443. package/src/web-components/interaction/form/bds-switch.spec.ts +68 -0
  444. package/src/web-components/interaction/form/bds-switch.ts +142 -41
  445. package/src/web-components/interaction/form/bds-textarea.spec.ts +71 -0
  446. package/src/web-components/interaction/form/bds-textarea.ts +109 -8
  447. package/src/web-components/layout/BdsGrid.mdx +6 -2
  448. package/src/web-components/layout/BdsGrid.stories.tsx +4 -0
  449. package/src/web-components/layout/bds-grid-item.spec.ts +21 -0
  450. package/src/web-components/layout/bds-grid-item.ts +17 -3
  451. package/src/web-components/layout/bds-grid.spec.ts +98 -0
  452. package/src/web-components/layout/bds-grid.ts +139 -19
  453. package/src/web-components/ui/BdsAlert.mdx +6 -5
  454. package/src/web-components/ui/BdsAlert.stories.tsx +6 -6
  455. package/src/web-components/ui/BdsAvatar.mdx +4 -2
  456. package/src/web-components/ui/BdsBreadcrumb.mdx +3 -2
  457. package/src/web-components/ui/BdsButtonContainer.mdx +64 -0
  458. package/src/web-components/ui/BdsButtonContainer.stories.tsx +84 -0
  459. package/src/web-components/ui/BdsCalendar.mdx +29 -4
  460. package/src/web-components/ui/BdsCalendar.stories.tsx +16 -18
  461. package/src/web-components/ui/BdsCalendarRange.mdx +71 -0
  462. package/src/web-components/ui/BdsCalendarRange.stories.tsx +31 -0
  463. package/src/web-components/ui/BdsCard.mdx +7 -3
  464. package/src/web-components/ui/BdsCard.stories.tsx +17 -1
  465. package/src/web-components/ui/BdsCarousel.mdx +40 -12
  466. package/src/web-components/ui/BdsDescriptionList.mdx +6 -1
  467. package/src/web-components/ui/BdsIconWrapper.mdx +3 -2
  468. package/src/web-components/ui/BdsLink.mdx +14 -2
  469. package/src/web-components/ui/BdsNotificationBanner.mdx +18 -0
  470. package/src/web-components/ui/BdsPagination.mdx +40 -1
  471. package/src/web-components/ui/BdsProgress.mdx +8 -2
  472. package/src/web-components/ui/BdsProgressCircle.mdx +5 -2
  473. package/src/web-components/ui/BdsRating.mdx +7 -0
  474. package/src/web-components/ui/BdsSectionHeader.mdx +22 -3
  475. package/src/web-components/ui/BdsSectionHeader.stories.tsx +15 -13
  476. package/src/web-components/ui/BdsTable.mdx +23 -2
  477. package/src/web-components/ui/BdsTable.stories.tsx +8 -2
  478. package/src/web-components/ui/BdsTypography.mdx +17 -1
  479. package/src/web-components/ui/bds-alert.spec.ts +17 -2
  480. package/src/web-components/ui/bds-alert.ts +31 -5
  481. package/src/web-components/ui/bds-avatar.spec.ts +29 -0
  482. package/src/web-components/ui/bds-avatar.ts +30 -12
  483. package/src/web-components/ui/bds-badge.spec.ts +5 -0
  484. package/src/web-components/ui/bds-badge.ts +11 -1
  485. package/src/web-components/ui/bds-breadcrumb.spec.ts +30 -0
  486. package/src/web-components/ui/bds-breadcrumb.ts +26 -4
  487. package/src/web-components/ui/bds-button-container.spec.ts +39 -0
  488. package/src/web-components/ui/bds-button-container.ts +123 -0
  489. package/src/web-components/ui/bds-button-group.spec.ts +14 -20
  490. package/src/web-components/ui/bds-button-group.ts +13 -64
  491. package/src/web-components/ui/bds-calendar-range.spec.ts +123 -0
  492. package/src/web-components/ui/bds-calendar-range.ts +307 -0
  493. package/src/web-components/ui/bds-calendar.spec.ts +176 -0
  494. package/src/web-components/ui/bds-calendar.ts +186 -344
  495. package/src/web-components/ui/bds-card.spec.ts +32 -0
  496. package/src/web-components/ui/bds-card.ts +34 -9
  497. package/src/web-components/ui/bds-carousel.spec.ts +147 -0
  498. package/src/web-components/ui/bds-carousel.ts +113 -36
  499. package/src/web-components/ui/bds-description-list.spec.ts +15 -0
  500. package/src/web-components/ui/bds-description-list.ts +37 -3
  501. package/src/web-components/ui/bds-icon-wrapper.spec.ts +12 -0
  502. package/src/web-components/ui/bds-icon-wrapper.ts +16 -15
  503. package/src/web-components/ui/bds-link.spec.ts +17 -0
  504. package/src/web-components/ui/bds-link.ts +26 -11
  505. package/src/web-components/ui/bds-loading.ts +11 -1
  506. package/src/web-components/ui/bds-notification-banner.spec.ts +13 -0
  507. package/src/web-components/ui/bds-notification-banner.ts +18 -1
  508. package/src/web-components/ui/bds-pagination.spec.ts +44 -0
  509. package/src/web-components/ui/bds-pagination.ts +39 -19
  510. package/src/web-components/ui/bds-progress-circle.spec.ts +21 -0
  511. package/src/web-components/ui/bds-progress-circle.ts +17 -5
  512. package/src/web-components/ui/bds-progress.spec.ts +21 -0
  513. package/src/web-components/ui/bds-progress.ts +19 -6
  514. package/src/web-components/ui/bds-rating.spec.ts +6 -0
  515. package/src/web-components/ui/bds-rating.ts +12 -2
  516. package/src/web-components/ui/bds-section-header.spec.ts +39 -8
  517. package/src/web-components/ui/bds-section-header.ts +47 -13
  518. package/src/web-components/ui/bds-separator.ts +10 -0
  519. package/src/web-components/ui/bds-skeleton.ts +10 -0
  520. package/src/web-components/ui/bds-table.spec.ts +63 -0
  521. package/src/web-components/ui/bds-table.ts +88 -28
  522. package/src/web-components/ui/bds-typography.spec.ts +47 -0
  523. package/src/web-components/ui/bds-typography.ts +28 -10
  524. package/src/web-components/ui/calendar-styles.ts +94 -0
  525. package/dist/web-components/chunk-5TFWOPLH.js +0 -49
  526. package/dist/web-components/chunk-7FMR53BW.js +0 -127
  527. package/dist/web-components/chunk-AGKJTMJI.js +0 -56
  528. package/dist/web-components/chunk-BQLZ7I4G.js +0 -56
  529. package/dist/web-components/chunk-IYGF6CD5.js +0 -118
  530. package/dist/web-components/chunk-QBB6ZX4R.js +0 -107
  531. package/dist/web-components/chunk-Y3POAKGS.js +0 -133
  532. package/dist/web-components/chunk-Y4MAXTMA.js +0 -80
  533. package/dist/web-components/chunk-Y7V7LM6R.js +0 -98
  534. package/src/web-components/ui/BdsButtonGroup.mdx +0 -69
  535. package/src/web-components/ui/BdsButtonGroup.stories.tsx +0 -66
@@ -12,7 +12,11 @@ export interface CollapsibleProps extends WithClassName, Omit<HTMLAttributes<HTM
12
12
  open?: boolean;
13
13
  /** Uncontrolled initial open state */
14
14
  defaultOpen?: boolean;
15
- /** Called after each toggle with the new open state */
15
+ /**
16
+ * Called on toggle with the new open state. When `open` is controlled,
17
+ * this reports the requested next state instead of applying it — update
18
+ * `open` in response to actually expand or collapse the panel.
19
+ */
16
20
  onToggle?: (open: boolean) => void;
17
21
  /**
18
22
  * Groups multiple Collapsible elements so only one is open at a time
@@ -31,10 +35,23 @@ export function Collapsible({
31
35
  className,
32
36
  ...rest
33
37
  }: Readonly<CollapsibleProps>) {
38
+ const isControlled = open !== undefined;
39
+
34
40
  const handleToggle = (e: SyntheticEvent<HTMLDetailsElement>) => {
41
+ // Controlled instances report state changes via handleSummaryClick
42
+ // instead, so the native toggle is prevented before this ever fires.
43
+ if (isControlled) return;
35
44
  onToggle?.(e.currentTarget.open);
36
45
  };
37
46
 
47
+ const handleSummaryClick = (e: SyntheticEvent<HTMLElement>) => {
48
+ if (!isControlled) return;
49
+ // Own the toggle: cancel the native open/close and let the consumer
50
+ // decide the next state by updating the `open` prop in response.
51
+ e.preventDefault();
52
+ onToggle?.(!open);
53
+ };
54
+
38
55
  return (
39
56
  <details
40
57
  className={cn(css.collapsible, className)}
@@ -43,7 +60,7 @@ export function Collapsible({
43
60
  onToggle={handleToggle}
44
61
  {...rest}
45
62
  >
46
- <summary className={css.summary}>
63
+ <summary className={css.summary} onClick={handleSummaryClick}>
47
64
  <span className={css.summaryContent}>{summary}</span>
48
65
  <span className={css.icon} aria-hidden="true" />
49
66
  </summary>
@@ -21,6 +21,8 @@ Key-value pairs rendered as a semantic `<dl>` element. Supports stacked and inli
21
21
 
22
22
  ## Props
23
23
 
24
+ > **HTML attributes** — all standard HTML attributes for the root element are forwarded via `{...rest}` (`id`, `className`, `style`, `data-*`, `aria-*`, event handlers, etc.). Component-controlled attributes take precedence.
25
+
24
26
  <ArgTypes of={Stories} />
25
27
 
26
28
  ## Accessibility
@@ -5,7 +5,7 @@ import * as Stories from './Link.stories';
5
5
 
6
6
  # Link
7
7
 
8
- Styled anchor element with three visual variants. Renders as `<a>` by default, but can be rendered as a `<button>` or any other element via the `component` prop.
8
+ Styled anchor element with three visual variants. Renders as `<a>` by default, but can be rendered as a `<button>` or any other element via the `as` prop.
9
9
 
10
10
  ## When to use
11
11
  - Navigation to another page or route
@@ -36,6 +36,8 @@ Styled anchor element with three visual variants. Renders as `<a>` by default, b
36
36
 
37
37
  ## Props
38
38
 
39
+ > **HTML attributes** — all standard HTML attributes for the root element are forwarded via `{...rest}` (`id`, `className`, `style`, `data-*`, `aria-*`, event handlers, etc.). Component-controlled attributes take precedence.
40
+
39
41
  <ArgTypes of={Stories} />
40
42
 
41
43
  ## CSS variables
@@ -73,4 +75,4 @@ Defaults: `default` and `standalone` resolve to `--bds-color_interactive_on-bg`
73
75
  ## Accessibility
74
76
 
75
77
  - External links add `target="_blank"` with `rel="noopener noreferrer"` and a visually-hidden "(opens in new tab)" label
76
- - The `as` prop allows any element while maintaining link semantics via `role`
78
+ - The `as` prop lets you render any element (e.g. `button`, `span`), but it does not add a `role` or `href` for you — when rendering as a non-`<a>` element, pass `role` and/or `href`/`onClick` yourself so the element keeps the correct semantics
@@ -31,6 +31,8 @@ Animated spinner that communicates an in-progress operation.
31
31
 
32
32
  ## Props
33
33
 
34
+ > **HTML attributes** — all standard HTML attributes for the root element are forwarded via `{...rest}` (`id`, `className`, `style`, `data-*`, `aria-*`, event handlers, etc.). Component-controlled attributes take precedence.
35
+
34
36
  <ArgTypes of={Stories} />
35
37
 
36
38
  ## CSS variables
@@ -41,12 +43,13 @@ Animated spinner that communicates an in-progress operation.
41
43
  <tr><th>Variable</th><th>Description</th></tr>
42
44
  </thead>
43
45
  <tbody>
44
- <tr><td>`--loading_color`</td><td>Spinner stroke colour (defaults to `currentcolor`)</td></tr>
46
+ <tr><td>`--loading_color`</td><td>Spinner stroke colour (defaults to `var(--bds-color_interactive)`)</td></tr>
47
+ <tr><td>`--loading_radius`</td><td>Spinner border radius (defaults to `var(--bds-border_radius--circle)`)</td></tr>
45
48
  </tbody>
46
49
  </table>
47
50
 
48
51
 
49
52
  ## Accessibility
50
53
 
51
- - Renders with `role="status"` and a visually-hidden "Loading" label
52
- - Animation respects `prefers-reduced-motion` — the spinner fades instead of spinning
54
+ - Renders with `role="status"` and an accessible name of `aria-label="Loading"` on the root element — pass your own `aria-label` to override it
55
+ - Animation respects `prefers-reduced-motion` — the spin animation is disabled entirely instead of spinning
@@ -9,7 +9,7 @@
9
9
  inline-size: 2.5em;
10
10
  block-size: 2.5em;
11
11
  border: 4px solid var(--bds-color_bg);
12
- border-block-start: 4px solid var(--bds-color_interactive);
12
+ border-block-start: 4px solid var(--loading_color, var(--bds-color_interactive));
13
13
  border-radius: var(--loading_radius, var(--bds-border_radius--circle));
14
14
  animation: spin 1s linear infinite;
15
15
  }
@@ -25,15 +25,15 @@
25
25
  block-size: 4em;
26
26
  border-width: 6px;
27
27
  }
28
+
29
+ @media (prefers-reduced-motion: reduce) {
30
+ .spinner {
31
+ animation: none;
32
+ }
33
+ }
28
34
  }
29
35
 
30
36
  @keyframes spin {
31
37
  0% { transform: rotate(0deg); }
32
38
  100% { transform: rotate(360deg); }
33
39
  }
34
-
35
- @media (prefers-reduced-motion: reduce) {
36
- .spinner {
37
- animation: none;
38
- }
39
- }
@@ -16,4 +16,16 @@ describe('Loading', () => {
16
16
  const { container } = render(<Loading className="custom" />);
17
17
  expect(container.firstChild).toHaveClass('custom');
18
18
  });
19
+
20
+ it('puts the status role and accessible name on the root element receiving forwarded attributes', () => {
21
+ const { container } = render(<Loading data-testid="spinner" />);
22
+ const status = screen.getByRole('status');
23
+ expect(status).toBe(container.firstChild);
24
+ expect(status).toHaveAttribute('data-testid', 'spinner');
25
+ });
26
+
27
+ it('allows a consumer aria-label to override the default accessible name', () => {
28
+ render(<Loading aria-label="Fetching results" />);
29
+ expect(screen.getByRole('status', { name: 'Fetching results' })).toBeInTheDocument();
30
+ });
19
31
  });
@@ -7,10 +7,15 @@ interface LoadingProps extends WithClassName, HTMLAttributes<HTMLDivElement> {
7
7
  size?: 'small' | 'medium' | 'large';
8
8
  }
9
9
 
10
- export function Loading({ size = 'medium', className, ...rest }: LoadingProps) {
10
+ export function Loading({ size = 'medium', className, 'aria-label': ariaLabel, ...rest }: LoadingProps) {
11
11
  return (
12
- <div {...rest} className={cn(css.loading, css[`--size_${size}`], className)}>
13
- <div className={css.spinner} role="status" aria-label="Loading" />
12
+ <div
13
+ role="status"
14
+ aria-label={ariaLabel ?? 'Loading'}
15
+ {...rest}
16
+ className={cn(css.loading, css[`--size_${size}`], className)}
17
+ >
18
+ <div className={css.spinner} />
14
19
  </div>
15
20
  );
16
21
  }
@@ -37,6 +37,8 @@ Full-width banner for page-level system messages. Sits at the top of the page or
37
37
 
38
38
  ## Props
39
39
 
40
+ > **HTML attributes** — all standard HTML attributes for the root element are forwarded via `{...rest}` (`id`, `className`, `style`, `data-*`, `aria-*`, event handlers, etc.). Component-controlled attributes take precedence.
41
+
40
42
  <ArgTypes of={Stories} />
41
43
 
42
44
  ## CSS variables
@@ -56,6 +58,7 @@ The override surface is **layered**. Setting a public token on the banner (or an
56
58
  <tr><td>`--banner_dismiss-radius`</td><td>`var(--bds-border_radius--circle)`</td><td>Dismiss button border radius.</td></tr>
57
59
  <tr><td>`--banner_dismiss-border`</td><td>`none`</td><td>Dismiss button border.</td></tr>
58
60
  <tr><td>`--banner_dismiss-opacity--hover`</td><td>`0.7`</td><td>Dismiss button opacity on hover.</td></tr>
61
+ <tr><td>`--banner_dismiss-size`</td><td>`2.75rem`</td><td>Dismiss button minimum hit area (44x44px, WCAG 2.5.5). The 1rem icon stays centered inside it.</td></tr>
59
62
  </tbody>
60
63
  </table>
61
64
 
@@ -80,3 +83,4 @@ Defaults resolve to the corresponding foundation tokens.
80
83
 
81
84
  - Uses `role="alert"` for error/warning variants and `role="status"` for info/success
82
85
  - Dismiss button has `aria-label="Dismiss notification"`
86
+ - Dismiss button has a minimum 44x44px hit area (WCAG 2.5.5) even though its icon renders at 1rem
@@ -55,6 +55,11 @@
55
55
  flex-shrink: 0;
56
56
  cursor: pointer;
57
57
  color: currentcolor;
58
+
59
+ /* WCAG 2.5.5: minimum 44x44px interactive area — the visible icon stays
60
+ 1rem; the hit area grows around it via min-inline-size/min-block-size. */
61
+ min-inline-size: var(--banner_dismiss-size, 2.75rem);
62
+ min-block-size: var(--banner_dismiss-size, 2.75rem);
58
63
  border-radius: var(--banner_dismiss-radius, var(--bds-border_radius--circle));
59
64
  border: var(--banner_dismiss-border, none);
60
65
  transition: var(--bds-animation_transition);
@@ -1,7 +1,14 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { resolve } from 'node:path';
1
3
  import { render, screen } from '@testing-library/react';
2
4
  import userEvent from '@testing-library/user-event';
3
5
  import { NotificationBanner } from './NotificationBanner';
4
6
 
7
+ const cssSource = readFileSync(
8
+ resolve(process.cwd(), 'src/components/ui/NotificationBanner/NotificationBanner.module.css'),
9
+ 'utf8',
10
+ );
11
+
5
12
  describe('NotificationBanner', () => {
6
13
  it('renders children', () => {
7
14
  render(<NotificationBanner>System maintenance scheduled</NotificationBanner>);
@@ -39,4 +46,17 @@ describe('NotificationBanner', () => {
39
46
  render(<NotificationBanner action={<button>View details</button>}>Msg</NotificationBanner>);
40
47
  expect(screen.getByRole('button', { name: 'View details' })).toBeInTheDocument();
41
48
  });
49
+
50
+ it('gives the dismiss button a 44x44px minimum hit area (WCAG 2.5.5)', () => {
51
+ // jsdom has no layout engine, so this can't be asserted via
52
+ // getBoundingClientRect(); pin the contract in the CSS source instead
53
+ // (same approach as FieldGroup.spec.tsx). The visible icon (1rem) can
54
+ // stay small — only the interactive hit area must reach 44px (2.75rem).
55
+ const dismissRuleMatch = cssSource.match(/\.dismiss\s*{[^}]*}/);
56
+ expect(dismissRuleMatch).not.toBeNull();
57
+ const dismissRule = dismissRuleMatch?.[0] ?? '';
58
+
59
+ expect(dismissRule).toMatch(/min-inline-size:\s*var\(--banner_dismiss-size,\s*2\.75rem\)/);
60
+ expect(dismissRule).toMatch(/min-block-size:\s*var\(--banner_dismiss-size,\s*2\.75rem\)/);
61
+ });
42
62
  });
@@ -30,11 +30,13 @@ Navigation control for paged data sets. Renders prev/next buttons plus numbered
30
30
 
31
31
  ## Props
32
32
 
33
+ > **HTML attributes** — all standard HTML attributes for the root element are forwarded via `{...rest}` (`id`, `className`, `style`, `data-*`, `aria-*`, event handlers, etc.). Component-controlled attributes take precedence.
34
+
33
35
  <ArgTypes of={Stories} />
34
36
 
35
37
  ## CSS variables
36
38
 
37
- The override surface is **layered**. Setting `--btn_bg` / `--btn_color` / `--btn_border` on the pagination (or any ancestor) wins in every state — resting, hover, and active. Setting per-state tokens targets only that one state.
39
+ The override surface is **layered**. Setting `--pagination_item-bg` / `--pagination_item-color` / `--pagination_item-border` on the pagination (or any ancestor) wins in every state — resting, hover, and active. Setting per-state tokens targets only that one state.
38
40
 
39
41
  ### Public override tokens (win over per-state defaults)
40
42
 
@@ -44,9 +46,9 @@ The override surface is **layered**. Setting `--btn_bg` / `--btn_color` / `--btn
44
46
  </thead>
45
47
  <tbody>
46
48
  <tr><td>`--pagination_radius`</td><td>`var(--bds-border_radius--full)`</td><td>Page button border radius.</td></tr>
47
- <tr><td>`--btn_bg`</td><td>`transparent` (per state)</td><td>Button background. Set to theme every state at once.</td></tr>
48
- <tr><td>`--btn_color`</td><td>per state</td><td>Button text colour.</td></tr>
49
- <tr><td>`--btn_border`</td><td>per state</td><td>Button border colour.</td></tr>
49
+ <tr><td>`--pagination_item-bg`</td><td>`transparent` (per state)</td><td>Button background. Set to theme every state at once.</td></tr>
50
+ <tr><td>`--pagination_item-color`</td><td>per state</td><td>Button text colour.</td></tr>
51
+ <tr><td>`--pagination_item-border`</td><td>per state</td><td>Button border colour.</td></tr>
50
52
  </tbody>
51
53
  </table>
52
54
 
@@ -58,16 +60,36 @@ The override surface is **layered**. Setting `--btn_bg` / `--btn_color` / `--btn
58
60
  </thead>
59
61
  <tbody>
60
62
  <tr><td>resting</td><td>(`transparent`)</td><td>(`var(--bds-color_on-bg)`)</td><td>(`var(--bds-color_bg--subtle)`)</td></tr>
61
- <tr><td>hover</td><td>`--btn_bg--hover`</td><td>`--btn_color--hover`</td><td>—</td></tr>
62
- <tr><td>active (current page)</td><td>`--btn_bg--active`</td><td>`--btn_color--active`</td><td>`--btn_border--active`</td></tr>
63
+ <tr><td>hover</td><td>`--pagination_item-bg--hover`</td><td>`--pagination_item-color--hover`</td><td>—</td></tr>
64
+ <tr><td>active (current page)</td><td>`--pagination_item-bg--active`</td><td>`--pagination_item-color--active`</td><td>`--pagination_item-border--active`</td></tr>
63
65
  </tbody>
64
66
  </table>
65
67
 
66
- Defaults: hover resolves to `--bds-color_bg--subtle` / `--bds-color_interactive_on-bg`; active resolves to `--bds-color_interactive` / `--bds-color_on-interactive`.
68
+ Defaults: hover resolves to `--bds-color_bg--subtle` / `--bds-color_interactive_on-bg`; active resolves through the shared `--bdc-color_active` / `--bdc-color_on-active` hooks (`--bds-color_interactive` / `--bds-color_on-interactive` by default), so a global active-state theme override also re-colours the current page.
69
+
70
+ ### Deprecated aliases
71
+
72
+ The original `--btn_*` token names are still read as a fallback layer beneath the `--pagination_item-*` names above, so existing overrides keep working. Prefer the new names for new code.
67
73
 
74
+ <table>
75
+ <thead>
76
+ <tr><th>Deprecated</th><th>Use instead</th></tr>
77
+ </thead>
78
+ <tbody>
79
+ <tr><td>`--btn_bg`</td><td>`--pagination_item-bg`</td></tr>
80
+ <tr><td>`--btn_color`</td><td>`--pagination_item-color`</td></tr>
81
+ <tr><td>`--btn_border`</td><td>`--pagination_item-border`</td></tr>
82
+ <tr><td>`--btn_bg--hover`</td><td>`--pagination_item-bg--hover`</td></tr>
83
+ <tr><td>`--btn_color--hover`</td><td>`--pagination_item-color--hover`</td></tr>
84
+ <tr><td>`--btn_bg--active`</td><td>`--pagination_item-bg--active`</td></tr>
85
+ <tr><td>`--btn_color--active`</td><td>`--pagination_item-color--active`</td></tr>
86
+ <tr><td>`--btn_border--active`</td><td>`--pagination_item-border--active`</td></tr>
87
+ </tbody>
88
+ </table>
68
89
 
69
90
  ## Accessibility
70
91
 
71
92
  - Wraps in `<nav aria-label="Pagination">`
72
93
  - Current page button has `aria-current="page"`
73
94
  - Prev/next buttons are disabled (not just hidden) when at the boundary
95
+ - Page buttons meet the 44×44px (2.75rem) WCAG 2.5.5 minimum touch target
@@ -22,16 +22,17 @@
22
22
  display: inline-flex;
23
23
  align-items: center;
24
24
  justify-content: center;
25
- min-inline-size: 2.25rem;
26
- block-size: 2.25rem;
25
+ min-inline-size: 2.75rem;
26
+ block-size: 2.75rem;
27
27
  padding-inline: var(--bds-space_xs);
28
28
  border-radius: var(--pagination_radius, var(--bds-border_radius--full));
29
29
 
30
- /* Layered cascade: public overrides (--btn_bg, --btn_color, --btn_border) win
31
- over per-state defaults. Hover/active write to the inner --btn_*--state slot. */
32
- background-color: var(--btn_bg, var(--btn_bg--state, transparent));
33
- color: var(--btn_color, var(--btn_color--state, var(--bds-color_on-bg)));
34
- --bdc_color: var(--btn_border, var(--btn_border--state, var(--bds-color_bg--subtle)));
30
+ /* Layered cascade: public overrides (--pagination_item-bg, --pagination_item-color,
31
+ --pagination_item-border) win over per-state defaults. The old --btn_* names are
32
+ kept as deprecated aliases. Hover/active write to the inner --btn_*--state slot. */
33
+ background-color: var(--pagination_item-bg, var(--btn_bg, var(--btn_bg--state, transparent)));
34
+ color: var(--pagination_item-color, var(--btn_color, var(--btn_color--state, var(--bds-color_on-bg))));
35
+ --bdc_color: var(--pagination_item-border, var(--btn_border, var(--btn_border--state, var(--bds-color_bg--subtle))));
35
36
 
36
37
  border: none;
37
38
  box-shadow: inset 0 0 0 var(--bdc-outline_width) var(--bdc_color);
@@ -55,15 +56,15 @@
55
56
 
56
57
  @media (hover: hover) and (pointer: fine) {
57
58
  .button:not(:disabled, .--active):hover {
58
- --btn_bg--state: var(--btn_bg--hover, var(--bds-color_bg--subtle));
59
- --btn_color--state: var(--btn_color--hover, var(--bds-color_interactive_on-bg));
59
+ --btn_bg--state: var(--pagination_item-bg--hover, var(--btn_bg--hover, var(--bds-color_bg--subtle)));
60
+ --btn_color--state: var(--pagination_item-color--hover, var(--btn_color--hover, var(--bds-color_interactive_on-bg)));
60
61
  }
61
62
  }
62
63
 
63
64
  .button.--active {
64
- --btn_bg--state: var(--btn_bg--active, var(--bds-color_interactive));
65
- --btn_color--state: var(--btn_color--active, var(--bds-color_on-interactive));
66
- --btn_border--state: var(--btn_border--active, var(--bds-color_interactive));
65
+ --btn_bg--state: var(--pagination_item-bg--active, var(--btn_bg--active, var(--bdc-color_active)));
66
+ --btn_color--state: var(--pagination_item-color--active, var(--btn_color--active, var(--bdc-color_on-active)));
67
+ --btn_border--state: var(--pagination_item-border--active, var(--btn_border--active, var(--bdc-color_active)));
67
68
  }
68
69
 
69
70
  .button.--nav svg {
@@ -75,8 +76,8 @@
75
76
  display: inline-flex;
76
77
  align-items: center;
77
78
  justify-content: center;
78
- min-inline-size: 2.25rem;
79
- block-size: 2.25rem;
79
+ min-inline-size: 2.75rem;
80
+ block-size: 2.75rem;
80
81
  color: var(--bds-color_on-bg--subtle);
81
82
  font-size: var(--bds-font_size--body);
82
83
  user-select: none;
@@ -30,6 +30,8 @@ Horizontal progress bar communicating completion towards a goal.
30
30
 
31
31
  ## Props
32
32
 
33
+ > **HTML attributes** — all standard HTML attributes for the root element are forwarded via `{...rest}` (`id`, `className`, `style`, `data-*`, `aria-*`, event handlers, etc.). Component-controlled attributes take precedence.
34
+
33
35
  <ArgTypes of={Stories} />
34
36
 
35
37
  ## CSS variables
@@ -41,12 +43,14 @@ Horizontal progress bar communicating completion towards a goal.
41
43
  </thead>
42
44
  <tbody>
43
45
  <tr><td>`--progress_color-active`</td><td>Filled track colour (defaults to `var(--bdc-color_active)`)</td></tr>
44
- <tr><td>`--progress_color-track`</td><td>Empty track colour</td></tr>
46
+ <tr><td>`--progress_color-track`</td><td>Empty track colour (defaults to `var(--bds-color_bg--subtle)`)</td></tr>
47
+ <tr><td>`--progress_radius`</td><td>Track and fill corner radius (defaults to `var(--bds-border_radius--full)`)</td></tr>
48
+ <tr><td>`--progress_height`</td><td>Track block-size (defaults per `size`: `--bds-space_xxs`/`--bds-space_xs`/`--bds-space_s`)</td></tr>
45
49
  </tbody>
46
50
  </table>
47
51
 
48
52
 
49
53
  ## Accessibility
50
54
 
51
- - Uses `<progress>` element with `aria-valuenow`, `aria-valuemin`, `aria-valuemax`
55
+ - Uses `role="progressbar"` with `aria-valuenow`, `aria-valuemin`, `aria-valuemax`
52
56
  - `label` prop sets `aria-label` — always provide a meaningful label
@@ -21,7 +21,7 @@
21
21
  .track {
22
22
  inline-size: 100%;
23
23
  block-size: var(--progress_height, var(--bds-space_xs));
24
- background-color: var(--bds-color_bg--subtle);
24
+ background-color: var(--progress_color-track, var(--bds-color_bg--subtle));
25
25
  border-radius: var(--progress_radius, var(--bds-border_radius--full));
26
26
  overflow: hidden;
27
27
  }
@@ -52,4 +52,21 @@ describe('Progress', () => {
52
52
  render(<Progress value={-10} label="Empty" showLabel />);
53
53
  expect(screen.getByText('0%')).toBeInTheDocument();
54
54
  });
55
+
56
+ it('clamps aria-valuenow to max when value exceeds max', () => {
57
+ render(<Progress value={150} label="Overloaded" />);
58
+ expect(screen.getByRole('progressbar')).toHaveAttribute('aria-valuenow', '100');
59
+ });
60
+
61
+ it('clamps aria-valuenow to 0 when value is negative', () => {
62
+ render(<Progress value={-10} label="Empty" />);
63
+ expect(screen.getByRole('progressbar')).toHaveAttribute('aria-valuenow', '0');
64
+ });
65
+
66
+ it('sets fill inline-size via the logical inlineSize style property', () => {
67
+ const { container } = render(<Progress value={40} label="Loading" />);
68
+ const fill = container.querySelector('.fill') as HTMLElement;
69
+ expect(fill.style.inlineSize).toBe('40%');
70
+ expect(fill.style.width).toBe('');
71
+ });
55
72
  });
@@ -33,12 +33,12 @@ export function Progress({
33
33
  <div
34
34
  role="progressbar"
35
35
  aria-label={label}
36
- aria-valuenow={value}
36
+ aria-valuenow={Math.min(max, Math.max(0, value))}
37
37
  aria-valuemin={0}
38
38
  aria-valuemax={max}
39
39
  className={cn(css.track, css[`--size_${size}`])}
40
40
  >
41
- <div className={css.fill} style={{ width: `${percentage}%` }} />
41
+ <div className={css.fill} style={{ inlineSize: `${percentage}%` }} />
42
42
  </div>
43
43
  </div>
44
44
  );
@@ -24,6 +24,8 @@ Circular progress indicator. Use when a compact representation fits better than
24
24
 
25
25
  ## Props
26
26
 
27
+ > **HTML attributes** — all standard HTML attributes for the root element are forwarded via `{...rest}` (`id`, `className`, `style`, `data-*`, `aria-*`, event handlers, etc.). Component-controlled attributes take precedence.
28
+
27
29
  <ArgTypes of={Stories} />
28
30
 
29
31
  ## CSS variables
@@ -34,13 +36,15 @@ Circular progress indicator. Use when a compact representation fits better than
34
36
  <tr><th>Variable</th><th>Description</th></tr>
35
37
  </thead>
36
38
  <tbody>
37
- <tr><td>`--progress-circle_color-active`</td><td>Arc stroke colour</td></tr>
38
- <tr><td>`--progress-circle_color-track`</td><td>Background circle colour</td></tr>
39
+ <tr><td>`--progressCircle_color-active`</td><td>Arc stroke colour</td></tr>
40
+ <tr><td>`--progressCircle_color-track`</td><td>Background circle colour</td></tr>
41
+ <tr><td>`--progressCircle_font-size--small`</td><td>Value label font size at `size="small"`</td></tr>
39
42
  </tbody>
40
43
  </table>
41
44
 
42
45
 
43
46
  ## Accessibility
44
47
 
45
- - SVG uses `role="img"` with an `aria-label` derived from `label` and current value
46
- - Numeric value is visually rendered when `showValue` is true; screen readers announce via `aria-valuenow`
48
+ - The root `<div>` uses `role="progressbar"` with `aria-label={label}` plus `aria-valuenow`/`aria-valuemin`/`aria-valuemax`
49
+ - The SVG arc is decorative and hidden from assistive technology via `aria-hidden`
50
+ - Numeric value is visually rendered when `showValue` is true; screen readers announce progress via the `aria-valuenow` on the root element
@@ -11,7 +11,7 @@
11
11
  }
12
12
 
13
13
  .track {
14
- stroke: var(--bds-color_bg--subtle);
14
+ stroke: var(--progressCircle_color-track, var(--bds-color_bg--subtle));
15
15
  }
16
16
 
17
17
  .fill {
@@ -28,7 +28,7 @@
28
28
  line-height: 1;
29
29
  }
30
30
 
31
- .--size_small .value { font-size: 0.5rem; }
31
+ .--size_small .value { font-size: var(--progressCircle_font-size--small, var(--bds-font_size--body--s)); }
32
32
  .--size_medium .value { font-size: var(--bds-font_size--body--s); }
33
33
  .--size_large .value { font-size: var(--bds-font_size--body); }
34
34
 
@@ -19,7 +19,17 @@ describe('ProgressCircle', () => {
19
19
 
20
20
  it('clamps values above max', () => {
21
21
  render(<ProgressCircle value={150} label="Progress" />);
22
- expect(screen.getByRole('progressbar')).toHaveAttribute('aria-valuenow', '150');
22
+ expect(screen.getByRole('progressbar')).toHaveAttribute('aria-valuenow', '100');
23
+ });
24
+
25
+ it('clamps aria-valuenow below min', () => {
26
+ render(<ProgressCircle value={-20} label="Progress" />);
27
+ expect(screen.getByRole('progressbar')).toHaveAttribute('aria-valuenow', '0');
28
+ });
29
+
30
+ it('clamps aria-valuenow to a custom max', () => {
31
+ render(<ProgressCircle value={999} max={200} label="Progress" />);
32
+ expect(screen.getByRole('progressbar')).toHaveAttribute('aria-valuenow', '200');
23
33
  });
24
34
 
25
35
  it('shows percentage value when showValue is true', () => {
@@ -35,7 +35,7 @@ export function ProgressCircle({
35
35
  {...rest}
36
36
  role="progressbar"
37
37
  aria-label={label}
38
- aria-valuenow={value}
38
+ aria-valuenow={Math.min(max, Math.max(0, value))}
39
39
  aria-valuemin={0}
40
40
  aria-valuemax={max}
41
41
  className={cn(css.wrapper, css[`--size_${size}`], className)}
@@ -21,6 +21,8 @@ Visual divider between content sections. Renders a semantic `<hr>` (horizontal)
21
21
 
22
22
  ## Props
23
23
 
24
+ > **HTML attributes** — all standard HTML attributes for the root element are forwarded via `{...rest}` (`id`, `className`, `style`, `data-*`, `aria-*`, event handlers, etc.). Component-controlled attributes take precedence.
25
+
24
26
  <ArgTypes of={Stories} />
25
27
 
26
28
  ## CSS variables
@@ -33,6 +35,7 @@ Visual divider between content sections. Renders a semantic `<hr>` (horizontal)
33
35
  <tbody>
34
36
  <tr><td>`--separator_color`</td><td>`var(--bds-color_on-bg)`</td><td>Line colour</td></tr>
35
37
  <tr><td>`--separator_thickness`</td><td>`1px`</td><td>Line thickness (height for horizontal, width for vertical)</td></tr>
38
+ <tr><td>`--separator_length`</td><td>`1em`</td><td>Minimum height of the vertical separator when rendered outside a flex/grid container. Inside a flex or grid container the separator still stretches to fill the cross axis (`align-self: stretch`) — this token only sets a floor for standalone usage.</td></tr>
36
39
  </tbody>
37
40
  </table>
38
41
 
@@ -41,3 +44,7 @@ Visual divider between content sections. Renders a semantic `<hr>` (horizontal)
41
44
 
42
45
  - Horizontal variant uses `<hr>` — natively announces a thematic break to screen readers
43
46
  - Vertical variant uses `role="separator"` with `aria-orientation="vertical"`
47
+
48
+ ## Layout notes
49
+
50
+ - The vertical separator relies on `align-self: stretch` to fill the height of a flex or grid parent. Outside such a container it falls back to `min-block-size: var(--separator_length, 1em)` so it never collapses to zero height.
@@ -13,6 +13,7 @@
13
13
  .separator.--vertical {
14
14
  display: inline-block;
15
15
  inline-size: var(--separator_thickness, 1px);
16
+ min-block-size: var(--separator_length, 1em);
16
17
  align-self: stretch;
17
18
  }
18
19
  }
@@ -28,9 +28,26 @@ Layout-preserving placeholder shown while content is loading. Renders a shimmer
28
28
 
29
29
  ## Props
30
30
 
31
+ > **HTML attributes** — all standard HTML attributes for the root element are forwarded via `{...rest}` (`id`, `className`, `style`, `data-*`, `aria-*`, event handlers, etc.). Component-controlled attributes take precedence.
32
+
31
33
  <ArgTypes of={Stories} />
32
34
 
35
+ ## CSS variables
36
+
37
+ <table>
38
+ <thead>
39
+ <tr><th>Variable</th><th>Description</th></tr>
40
+ </thead>
41
+ <tbody>
42
+ <tr><td>`--skeleton_color-base`</td><td>Gradient base colour (defaults to `var(--bds-color_grey--subtle)`)</td></tr>
43
+ <tr><td>`--skeleton_color-highlight`</td><td>Gradient highlight colour that sweeps across the base (defaults to `var(--bds-color_bg)`)</td></tr>
44
+ <tr><td>`--skeleton_radius`</td><td>Corner radius (defaults to `var(--bds-border_radius--xs)`)</td></tr>
45
+ <tr><td>`--skeleton_min-block-size`</td><td>Minimum block-size when no height is set via `className`/inline style (defaults to `var(--bds-space_m)`)</td></tr>
46
+ </tbody>
47
+ </table>
48
+
33
49
  ## Accessibility
34
50
 
35
51
  - Renders `aria-hidden="true"` — skeleton blocks are invisible to screen readers
36
52
  - The containing region should use `aria-busy="true"` while loading, then `aria-live="polite"` when content arrives
53
+ - The shimmer animation respects `prefers-reduced-motion: reduce` — it is disabled and replaced with a static base colour
@@ -2,14 +2,21 @@
2
2
  .skeleton {
3
3
  background: linear-gradient(
4
4
  90deg,
5
- var(--bds-color_grey--subtle) 25%,
6
- var(--bds-color_bg) 50%,
7
- var(--bds-color_grey--subtle) 75%
5
+ var(--skeleton_color-base, var(--bds-color_grey--subtle)) 25%,
6
+ var(--skeleton_color-highlight, var(--bds-color_bg)) 50%,
7
+ var(--skeleton_color-base, var(--bds-color_grey--subtle)) 75%
8
8
  );
9
9
  background-size: 200% 100%;
10
10
  animation: shimmer 1.5s infinite;
11
- border-radius: var(--bds-border_radius--xs);
12
- min-block-size: var(--bds-space_m);
11
+ border-radius: var(--skeleton_radius, var(--bds-border_radius--xs));
12
+ min-block-size: var(--skeleton_min-block-size, var(--bds-space_m));
13
+ }
14
+
15
+ @media (prefers-reduced-motion: reduce) {
16
+ .skeleton {
17
+ animation: none;
18
+ background: var(--skeleton_color-base, var(--bds-color_grey--subtle));
19
+ }
13
20
  }
14
21
  }
15
22