@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
@@ -5,7 +5,7 @@ import * as Stories from './BdsFieldGroup.stories';
5
5
 
6
6
  # `<bds-field-group>`
7
7
 
8
- Framework-agnostic FieldGroup custom element. Wraps slotted fields in a `<fieldset>` with a styled `<legend>` and lays them out horizontally (with auto-collapse to vertical via CSS container query) or vertically.
8
+ Framework-agnostic FieldGroup custom element. Wraps slotted fields in a `<fieldset>` with a styled `<legend>` and lays them out horizontally (with auto-collapse to vertical, driven by a `ResizeObserver` — not a CSS container query, see below) or vertically.
9
9
 
10
10
  Mirrors the React `FieldGroup` component — same token surface, same behavior, same auto-derived collapse threshold.
11
11
 
@@ -15,7 +15,7 @@ Mirrors the React `FieldGroup` component — same token surface, same behavior,
15
15
  |-----------|--------|---------|-------------|
16
16
  | `variant` | `horizontal` \| `vertical` | `horizontal` | Layout direction. |
17
17
  | `legend` | string | — | Optional legend text. Falls back to `aria-label` semantics if you set that on the host directly. |
18
- | `disabled` | boolean | `false` | Forwards to the inner `<fieldset>`; the UA cascades it to descendant form controls (light-DOM children projected through the slot). |
18
+ | `disabled` | boolean | `false` | Forwards to the inner `<fieldset>` AND is propagated to each directly-slotted form control's `disabled` property (see [Notes on shadow DOM](#notes-on-shadow-dom) — the UA's fieldset-disables-descendants behaviour doesn't reach light-DOM children projected through a slot, so the component does it explicitly). |
19
19
 
20
20
  ## Slots
21
21
 
@@ -55,6 +55,7 @@ Same surface as the React component. All public tokens are read with foundation-
55
55
  | Variable | Default |
56
56
  |----------|---------|
57
57
  | `--fieldGroup_legend-color` | `var(--bds-color_on-bg)` |
58
+ | `--fieldGroup_legend-font-family` | `var(--bds-font_family--body)` |
58
59
  | `--fieldGroup_legend-font-size` | `var(--bds-font_size--heading-3)` |
59
60
  | `--fieldGroup_legend-font-weight` | `var(--bds-font_weight--semibold)` |
60
61
  | `--fieldGroup_legend-line-height` | `var(--bds-font_line-height--heading)` |
@@ -62,6 +63,10 @@ Same surface as the React component. All public tokens are read with foundation-
62
63
  | `--fieldGroup_legend-gap` | `var(--bds-space_m)` |
63
64
  | `--fieldGroup_legend-border-block-end` | `1px solid var(--bds-color_bg--subtle)` |
64
65
 
66
+ ## How auto-collapse works
67
+
68
+ CSS [`@container`](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/At-rules/@container) query *conditions* can't reference custom properties (`var()` inside a container-query feature value is invalid CSS), so the per-instance `--fieldGroup_collapse-threshold` can't drive an `@container` rule directly. Instead, the component renders a hidden `.probe` element whose own inline-size resolves `--fieldGroup_collapse-threshold` as a normal property value, and a `ResizeObserver` compares the probe's resolved pixel width against the `<fieldset>`'s own width, toggling `data-collapsed="true"` on the **host** when the fieldset is narrower. This mirrors the React `FieldGroup` component's mechanism exactly. `ResizeObserver` is required for the collapse to run; it's supported by all current browsers, and in its absence the layout simply stays in its declared variant.
69
+
65
70
  ## Notes on shadow DOM
66
71
 
67
- The component renders its own `<fieldset>` inside the shadow root and projects fields through a `<slot>`. Because slotted elements stay in the host's light DOM, the native `fieldset[disabled]` cascade onto descendants is browser-dependentmodern browsers do propagate disabled to slotted form controls; older ones may not. If you support an older runtime and need a hard guarantee, set `disabled` on each slotted field too.
72
+ The component renders its own `<fieldset>` inside the shadow root and projects fields through a `<slot>`. Slotted elements' actual DOM parent stays the host (not the shadow-root fieldset), so the UA's native `fieldset[disabled]` cascade-to-descendants behaviour which walks the DOM tree, not the flattened/composed tree **never reaches them**, in any browser. To compensate, the component explicitly sets `.disabled` on each directly-slotted form control whenever `disabled` changes or new fields are slotted in, and tracks which controls it disabled so re-enabling the group never overrides a control a consumer had individually disabled beforehand. Deeply-nested form controls (e.g. a slotted wrapper `<div>` containing an `<input>`) are not reached — keep form controls as direct children of `<bds-field-group>`.
@@ -34,7 +34,7 @@ const meta = {
34
34
  description: {
35
35
  component:
36
36
  'Framework-agnostic FieldGroup. Wraps slotted fields in a `<fieldset>` ' +
37
- 'and lays them out horizontally with a CSS container query that auto-collapses ' +
37
+ 'and lays them out horizontally with a ResizeObserver-driven auto-collapse ' +
38
38
  'to a single column when the host is too narrow to fit a complete row at minimum field width.',
39
39
  },
40
40
  },
@@ -59,7 +59,20 @@ Use `<bds-file-input>` wherever users need to attach one or more files to a form
59
59
 
60
60
  | Event | Detail | Description |
61
61
  |--------------|--------------|-----------------------------------------|
62
- | `bds-change` | `FileList` | Fired when files are selected or dropped |
62
+ | `bds-change` | `FileList` | Fired when files are selected via the picker or accepted via drag-and-drop |
63
+
64
+ ## CSS Custom Properties
65
+
66
+ Token names match the React `FileInput` component (`--fileInput_*`) so themes written
67
+ against React apply here unchanged. The previous web-component-only `--file-input_*`
68
+ names still work as deprecated aliases.
69
+
70
+ | Property | Default | Description |
71
+ |------------------------------------|-------------------------------------------------------------|-------------------------------------------|
72
+ | `--fileInput_color` | `var(--bds-color_on-bg)` | Zone text/icon colour; also drives the `currentcolor` dashed border |
73
+ | `--fileInput_border-color` | `currentcolor` | Border colour while the zone has focus (`:focus-within`) |
74
+ | `--fileInput_border-color--hover` | `var(--bds-color_interactive)` | Border colour on hover |
75
+ | `--fileInput_bg--hover` | `rgb(from var(--bds-color_interactive) r g b / 4%)` | Background colour on hover |
63
76
 
64
77
  ## Usage in plain HTML
65
78
 
@@ -72,8 +85,16 @@ Use `<bds-file-input>` wherever users need to attach one or more files to a form
72
85
 
73
86
  ## Accessibility
74
87
 
75
- - The drop zone has `role="button"` and `tabindex="0"` so it is keyboard-reachable
76
- - `aria-label="Upload file"` is set on the zone for screen reader identification
77
- - `Enter` and `Space` open the native file picker from keyboard focus
78
- - `disabled` sets `tabindex="-1"` and `pointer-events: none`
88
+ - The drop zone is rendered as a `<label>` associated with the (visually hidden but
89
+ focusable) shadow file input the slotted text becomes the input's accessible name,
90
+ no hardcoded `aria-label` overrides it
91
+ - The shadow input is the only tab stop; the zone itself carries no `role`/`tabindex`
92
+ - `.zone:focus-within` shows a visible focus ring (`--bds-outline_default`) when the
93
+ shadow input has keyboard focus
94
+ - `Enter` and `Space` open the native file picker via the input's native keyboard handling
95
+ - `disabled` disables the shadow input (removing it from the tab order) and sets
96
+ `pointer-events: none` on the host
97
+ - Dropped files are filtered against `accept` (extension, `type/*`, or exact MIME type)
98
+ before being applied — files that don't match are silently discarded, matching the
99
+ native file picker's behaviour
79
100
  - Participates in HTML forms via the Form-Associated Custom Elements API; files are submitted as `FormData` entries
@@ -77,6 +77,20 @@ Use `<bds-form-input>` for single-line text fields in forms. It handles label as
77
77
  | `bds-input` | `{ value: string }` | Fired on every keystroke |
78
78
  | `bds-change` | `{ value: string }` | Fired when the value is committed |
79
79
 
80
+ ## CSS variables
81
+
82
+ Token names mirror the React `FormInput` component so themes carry over between the two implementations.
83
+
84
+ | Variable | Default | Description |
85
+ |----------|---------|-------------|
86
+ | `--formInput_color_bg` | `var(--bds-color_bg)` | Background colour |
87
+ | `--formInput_color` | `var(--bds-color_on-bg)` | Text colour |
88
+ | `--formInput_border` | `none` | Border (layered on top of the inset focus/error ring) |
89
+ | `--formInput_radius` | `var(--bds-border_radius--full)` | Corner radius |
90
+ | `--formInput_shadow` | `var(--bdc-outline_shadow)` | Box shadow |
91
+
92
+ `--input_*` (e.g. `--input_border`, `--input_radius`, `--input_shadow`, `--input_color`, `--input_color_bg`) are deprecated aliases for the `--formInput_*` tokens above — they still work but `--formInput_*` is the documented, forward-compatible name. `--formInput_border-color` is a web-component-only legacy override for the inset ring colour (fallback `currentcolor`); prefer `--formInput_border` for adding a visible border.
93
+
80
94
  ## Usage in plain HTML
81
95
 
82
96
  ```html
@@ -94,5 +108,6 @@ Use `<bds-form-input>` for single-line text fields in forms. It handles label as
94
108
  - `required` adds `aria-required="true"` and a visual asterisk
95
109
  - `error` sets `aria-invalid="true"` and links the error message via `aria-describedby`
96
110
  - `hint` is linked via `aria-describedby` for screen reader announcement
111
+ - When both `error` and `hint` are set, both messages render (matching the React component) so `aria-describedby` never references an id that isn't in the DOM
97
112
  - Error messages use `role="alert"` so they are announced immediately
98
- - The focus ring is applied to the wrapper element, not the inner input
113
+ - The focus ring is applied to the wrapper element, not the inner input, and only appears for keyboard/`:focus-visible` focus — clicking into the field highlights the frame colour without showing the outline ring
@@ -24,12 +24,21 @@ Use `<bds-number-input>` for quantity selectors, counters, or any numeric field
24
24
  ### Default
25
25
  <Canvas of={Stories.Default} />
26
26
 
27
+ ### With label
28
+ <Canvas of={Stories.WithLabel} />
29
+
27
30
  ### With min and max
28
31
  <Canvas of={Stories.WithMinMax} />
29
32
 
30
33
  ### With custom step (5)
31
34
  <Canvas of={Stories.WithStep} />
32
35
 
36
+ ### With hint
37
+ <Canvas of={Stories.WithHint} />
38
+
39
+ ### With error
40
+ <Canvas of={Stories.WithError} />
41
+
33
42
  ### Disabled
34
43
  <Canvas of={Stories.Disabled} />
35
44
 
@@ -47,6 +56,9 @@ Use `<bds-number-input>` for quantity selectors, counters, or any numeric field
47
56
  | `max` | number | — | Maximum allowed value |
48
57
  | `step` | number | `1` | Increment/decrement step |
49
58
  | `disabled` | boolean | `false` | Disables the input and steppers |
59
+ | `label` | string | `""` | Visible label text, associated with the input via `for`/`id` |
60
+ | `hint` | string | — | Helper text shown below the input when there is no `error` |
61
+ | `error` | string | — | Error message; when set the input enters error state and the message replaces the hint |
50
62
 
51
63
  ## Events
52
64
 
@@ -58,13 +70,33 @@ Use `<bds-number-input>` for quantity selectors, counters, or any numeric field
58
70
  ## Usage in plain HTML
59
71
 
60
72
  ```html
61
- <bds-number-input name="qty" value="1" min="0" max="99" step="1"></bds-number-input>
73
+ <bds-number-input name="qty" label="Quantity" value="1" min="0" max="99" step="1"></bds-number-input>
62
74
  ```
63
75
 
64
76
  ## Accessibility
65
77
 
66
- - Decrement button has `aria-label="Decrease"` and increment has `aria-label="Increase"`
78
+ - `label` renders a shadow `<label for>` wired to the inner input's `id`, so the field always has an accessible name when a label is provided — leaving `label` unset renders no label element and no accessible name
79
+ - Decrement button has `aria-label="Decrease"` and increment has `aria-label="Increase"`, and both steppers carry `aria-controls` pointing at the input's `id`
80
+ - The input exposes `aria-invalid` (`"true"` when `error` is set) and `aria-describedby`, referencing the rendered error or hint message
67
81
  - Stepper buttons are disabled when the value is at `min` or `max`
68
82
  - The stepper buttons use `tabindex="-1"` so keyboard users navigate directly to the numeric input
69
83
  - `disabled` disables both the input and the stepper buttons
70
84
  - Participates in HTML forms via the Form-Associated Custom Elements API
85
+
86
+ ## CSS Custom Properties
87
+
88
+ | Property | Default | Description |
89
+ |----------------------------------------|---------------------------------------|-------------------------------------------------|
90
+ | `--numberInput_border` | `none` | Extra CSS `border` on the row frame (on top of the inset bdc border) |
91
+ | `--numberInput_radius` | `--bds-border_radius--full` | Corner radius of the row frame and outer stepper corners |
92
+ | `--numberInput_shadow` | `--bdc-outline_shadow` | Additional `box-shadow` layered after the bdc inset border |
93
+ | `--numberInput_font-size` | `--bds-font_size--body` | Input font size |
94
+ | `--numberInput_padding` | `--bds-space_s` | Input padding |
95
+ | `--numberInput_color` | `--bds-color_on-bg` | Input text color |
96
+ | `--numberInput_stepper-padding` | `--bds-space_xs` | Padding of each stepper button (drives its size together with the icon) |
97
+ | `--numberInput_stepper-bg` | `--bds-color_bg--subtle` | Stepper background color |
98
+ | `--numberInput_stepper-bg--hover` | `--bds-color_bg--subtle` | Stepper background color on hover |
99
+ | `--numberInput_stepper-opacity--hover`| `0.7` | Stepper opacity on hover |
100
+ | `--numberInput_stepper-color` | `--bds-color_interactive` | Stepper icon color |
101
+
102
+ > **Deprecated:** `--number-input_border-color`, `--number-input_radius`, `--number-input_shadow`, `--number-input_color_bg`, and `--number-input_color` (the original kebab-cased `--number-input_*` names) still work as legacy fallbacks but are superseded by the `--numberInput_*` names above and will be removed in a future major version.
@@ -9,6 +9,9 @@ function BdsNumberInput({
9
9
  max,
10
10
  step,
11
11
  disabled,
12
+ label,
13
+ hint,
14
+ error,
12
15
  }: {
13
16
  name?: string;
14
17
  value?: number;
@@ -16,6 +19,9 @@ function BdsNumberInput({
16
19
  max?: number;
17
20
  step?: number;
18
21
  disabled?: boolean;
22
+ label?: string;
23
+ hint?: string;
24
+ error?: string;
19
25
  }) {
20
26
  return React.createElement('bds-number-input', {
21
27
  name,
@@ -24,6 +30,9 @@ function BdsNumberInput({
24
30
  max,
25
31
  step,
26
32
  disabled: disabled || undefined,
33
+ label,
34
+ hint,
35
+ error,
27
36
  });
28
37
  }
29
38
 
@@ -38,6 +47,9 @@ const meta = {
38
47
  min: { control: 'number' },
39
48
  max: { control: 'number' },
40
49
  step: { control: 'number' },
50
+ label: { control: 'text' },
51
+ hint: { control: 'text' },
52
+ error: { control: 'text' },
41
53
  },
42
54
  decorators: [
43
55
  (Story: React.ComponentType) => (
@@ -55,14 +67,26 @@ export const Default: Story = {
55
67
  args: { name: 'quantity', value: 0 },
56
68
  };
57
69
 
70
+ export const WithLabel: Story = {
71
+ args: { name: 'quantity', label: 'Quantity', value: 1 },
72
+ };
73
+
58
74
  export const WithMinMax: Story = {
59
- args: { name: 'quantity', value: 5, min: 0, max: 10 },
75
+ args: { name: 'quantity', label: 'Quantity', value: 5, min: 0, max: 10 },
60
76
  };
61
77
 
62
78
  export const WithStep: Story = {
63
- args: { name: 'quantity', value: 0, step: 5, min: 0, max: 100 },
79
+ args: { name: 'quantity', label: 'Quantity', value: 0, step: 5, min: 0, max: 100 },
80
+ };
81
+
82
+ export const WithHint: Story = {
83
+ args: { name: 'quantity', label: 'Quantity', value: 1, hint: 'Whole numbers only' },
84
+ };
85
+
86
+ export const WithError: Story = {
87
+ args: { name: 'quantity', label: 'Quantity', value: 0, min: 1, error: 'Quantity must be at least 1' },
64
88
  };
65
89
 
66
90
  export const Disabled: Story = {
67
- args: { name: 'quantity', value: 3, disabled: true },
91
+ args: { name: 'quantity', label: 'Quantity', value: 3, disabled: true },
68
92
  };
@@ -30,19 +30,30 @@ Use `<bds-radio>` for single-choice selection from a set of options. Always grou
30
30
  ### Disabled
31
31
  <Canvas of={Stories.Disabled} />
32
32
 
33
+ ### With description
34
+ <Canvas of={Stories.WithDescription} />
35
+
36
+ ### With error
37
+ <Canvas of={Stories.WithError} />
38
+
39
+ ### Group (mutually exclusive selection)
40
+ <Canvas of={Stories.Group} />
41
+
33
42
  ## Props
34
43
 
35
44
  <ArgTypes of={Stories} />
36
45
 
37
46
  ## Attributes
38
47
 
39
- | Attribute | Type | Default | Description |
40
- |------------|---------|---------|--------------------------------------------------|
41
- | `name` | string | `""` | Form field name (groups radio buttons) |
42
- | `value` | string | `""` | Value submitted when this option is selected |
43
- | `checked` | boolean | `false` | Whether this option is selected |
44
- | `required` | boolean | `false` | Marks the field as required |
45
- | `disabled` | boolean | `false` | Disables this radio option |
48
+ | Attribute | Type | Default | Description |
49
+ |---------------|---------|---------|------------------------------------------------------------------|
50
+ | `name` | string | `""` | Form field name radios sharing a `name` form a mutually exclusive group |
51
+ | `value` | string | `""` | Value submitted when this option is selected |
52
+ | `checked` | boolean | `false` | Whether this option is selected |
53
+ | `required` | boolean | `false` | Marks the field as required |
54
+ | `disabled` | boolean | `false` | Disables this radio option |
55
+ | `error` | boolean | `false` | Error visual state; sets `aria-invalid="true"` on the input |
56
+ | `description` | string | — | Supporting text rendered below the label, wired via `aria-describedby` |
46
57
 
47
58
  ## Slots
48
59
 
@@ -52,9 +63,23 @@ Use `<bds-radio>` for single-choice selection from a set of options. Always grou
52
63
 
53
64
  ## Events
54
65
 
55
- | Event | Detail | Description |
56
- |----------|--------|------------------------------------------------|
57
- | `change` | | Native change event forwarded from the inner `<input>` |
66
+ | Event | Detail | Description |
67
+ |--------------|--------------------------------------|---------------------------------------------------------------------|
68
+ | `bds-change` | `{ value: string, checked: true }` | Fired when this radio becomes checked via user interaction (click or arrow-key navigation). Composed — crosses the shadow boundary, unlike the native `change` event. |
69
+
70
+ ## Overridable CSS custom properties
71
+
72
+ | Token | Default | Description |
73
+ |------------------------------|-----------------------------------|-------------------------------------------------|
74
+ | `--radio_color` | `--bds-color_on-bg` (via `--radio_border-color`, deprecated) | Border/text colour driving the `currentcolor` frame |
75
+ | `--radio_border` | `none` | Border shorthand around the frame |
76
+ | `--radio_radius` | `--bds-border_radius--circle` | Corner radius |
77
+ | `--radio_shadow` | `--bdc-outline_shadow` | Extra box-shadow layered with the inset border |
78
+ | `--radio_color_bg` | `--bds-color_bg` | Background colour |
79
+ | `--radio_color-active` | `--bdc-color_active` | Colour of the inner dot / border when checked |
80
+ | `--radio_description-color` | `--bds-color_on-bg--subtle` | Colour of the `description` text |
81
+
82
+ > `--radio_border-color` is a **deprecated alias** for `--radio_color` — it still works but new code should use `--radio_color`.
58
83
 
59
84
  ## Usage in plain HTML
60
85
 
@@ -67,6 +92,8 @@ Use `<bds-radio>` for single-choice selection from a set of options. Always grou
67
92
  ## Accessibility
68
93
 
69
94
  - The inner `<input type="radio">` is associated with a `<label>` via matching `id`/`for` attributes
70
- - Radios with the same `name` form a mutually exclusive group for keyboard navigation
95
+ - Radios sharing a `name` form a real mutually exclusive group: checking one unchecks the others (searched within the same document/shadow root), and `ArrowUp`/`ArrowDown`/`ArrowLeft`/`ArrowRight` move selection between them
96
+ - Roving `tabindex`: only the checked radio (or the first radio if none is checked) is a tab stop within its group, matching native `<input type="radio">` keyboard semantics
97
+ - `error` sets `aria-invalid="true"` on the inner input; `description` is wired via `aria-describedby`
71
98
  - Use `<bds-radio-group>` to wrap related radios in a `<fieldset>`/`<legend>` for proper screen reader announcements
72
- - Participates in HTML forms via the Form-Associated Custom Elements API
99
+ - Participates in HTML forms via the Form-Associated Custom Elements API; `formResetCallback` restores the radio's initial `checked` state on form reset
@@ -8,6 +8,8 @@ function BdsRadio({
8
8
  checked,
9
9
  required,
10
10
  disabled,
11
+ error,
12
+ description,
11
13
  children,
12
14
  }: {
13
15
  name?: string;
@@ -15,6 +17,8 @@ function BdsRadio({
15
17
  checked?: boolean;
16
18
  required?: boolean;
17
19
  disabled?: boolean;
20
+ error?: boolean;
21
+ description?: string;
18
22
  children?: React.ReactNode;
19
23
  }) {
20
24
  return React.createElement(
@@ -25,6 +29,8 @@ function BdsRadio({
25
29
  checked: checked || undefined,
26
30
  required: required || undefined,
27
31
  disabled: disabled || undefined,
32
+ error: error || undefined,
33
+ description,
28
34
  },
29
35
  children,
30
36
  );
@@ -39,6 +45,8 @@ const meta = {
39
45
  checked: { control: 'boolean' },
40
46
  required: { control: 'boolean' },
41
47
  disabled: { control: 'boolean' },
48
+ error: { control: 'boolean' },
49
+ description: { control: 'text' },
42
50
  },
43
51
  } satisfies Meta<typeof BdsRadio>;
44
52
 
@@ -56,3 +64,21 @@ export const Checked: Story = {
56
64
  export const Disabled: Story = {
57
65
  args: { name: 'size', value: 'm', disabled: true, children: 'Medium (disabled)' },
58
66
  };
67
+
68
+ export const WithDescription: Story = {
69
+ args: { name: 'size', value: 'm', description: 'Fits most people', children: 'Medium' },
70
+ };
71
+
72
+ export const WithError: Story = {
73
+ args: { name: 'size', value: 'm', error: true, children: 'Medium' },
74
+ };
75
+
76
+ export const Group: Story = {
77
+ render: () => (
78
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '0.5rem' }}>
79
+ {React.createElement('bds-radio', { name: 'group-size', value: 's' }, 'Small')}
80
+ {React.createElement('bds-radio', { name: 'group-size', value: 'm', checked: true }, 'Medium')}
81
+ {React.createElement('bds-radio', { name: 'group-size', value: 'l' }, 'Large')}
82
+ </div>
83
+ ),
84
+ };
@@ -45,8 +45,8 @@ Use `<bds-radio-group>` whenever you have a set of mutually exclusive options. T
45
45
  | `name` | string | `""` | Shared name propagated to all slotted `<bds-radio>` elements |
46
46
  | `error` | string | — | Error message shown below items; takes priority over `hint` |
47
47
  | `hint` | string | — | Helper text shown below items |
48
- | `required` | boolean | `false` | Shows a required indicator on the legend |
49
- | `disabled` | boolean | `false` | Disables the entire fieldset |
48
+ | `required` | boolean | `false` | Shows a required indicator on the legend and sets `aria-required` on the fieldset |
49
+ | `disabled` | boolean | `false` | Disables the fieldset **and** propagates `disabled` to every slotted `<bds-radio>` |
50
50
 
51
51
  ## Slots
52
52
 
@@ -54,6 +54,10 @@ Use `<bds-radio-group>` whenever you have a set of mutually exclusive options. T
54
54
  |-------------|---------------------------|
55
55
  | `(default)` | `<bds-radio>` elements |
56
56
 
57
+ ## Overridable CSS custom properties
58
+
59
+ The legend uses `var(--bds-font_weight--medium)` (matching the React `RadioGroup`). `bds-radio-group` has no component-local override tokens of its own — style slotted `<bds-radio>` elements directly via their own tokens.
60
+
57
61
  ## Usage in plain HTML
58
62
 
59
63
  ```html
@@ -68,6 +72,7 @@ Use `<bds-radio-group>` whenever you have a set of mutually exclusive options. T
68
72
 
69
73
  - Renders a `<fieldset>` with a `<legend>`, which is announced as a group by screen readers
70
74
  - The `name` attribute is automatically propagated to all slotted `<bds-radio>` elements
71
- - `required` adds a visual asterisk to the legend
72
- - `disabled` on the group disables all contained radios via the native `<fieldset disabled>` behaviour
75
+ - `required` adds a visual asterisk to the legend and sets `aria-required="true"` on the fieldset
76
+ - `disabled` on the group disables the native `<fieldset>` **and** is explicitly propagated (attribute set/removed) to every slotted `<bds-radio>` — a shadow-DOM `<fieldset disabled>` alone has no effect on slotted light-DOM content, so this propagation is required for the group's `disabled` state to actually disable its radios. A `<bds-radio>` that was already individually marked `disabled` in markup stays disabled if the group is later re-enabled.
77
+ - `aria-describedby` on the fieldset references the error/hint message id so assistive technology announces it alongside the group
73
78
  - Error messages use `role="alert"` so they are announced immediately
@@ -52,9 +52,10 @@ Use `<bds-segmented-control>` for mutually exclusive view or mode toggles where
52
52
 
53
53
  ## Events
54
54
 
55
- | Event | Detail | Description |
56
- |----------|--------|----------------------------------------------------------|
57
- | `change` | | Fired when a new segment is selected (radio mode only) |
55
+ | Event | Detail | Description |
56
+ |--------------|-----------------|-----------------------------------------------------------------------|
57
+ | `bds-change` | `{ value }` | Fired when a new segment is selected (radio mode only) |
58
+ | `change` | — | **Deprecated** alias for `bds-change`, kept for backward compatibility |
58
59
 
59
60
  ## Usage in plain HTML
60
61
 
@@ -76,19 +77,44 @@ Use `<bds-segmented-control>` for mutually exclusive view or mode toggles where
76
77
 
77
78
  ## CSS Custom Properties
78
79
 
80
+ Token names match the React `SegmentedControl` component (`--control_*`) so themes
81
+ written against React apply here unchanged. The previous web-component-only
82
+ `--segmented_*` names still work as deprecated aliases.
83
+
79
84
  | Property | Default | Description |
80
85
  |----------|---------|-------------|
81
- | `--segmented_color_bg` | `var(--bds-color_bg--subtle)` | Track background colour (both variants) |
82
- | `--segmented_item-bg` | `transparent` | Inactive item background (outline variant) |
83
- | `--segmented_item-bg--active` | `var(--bds-color_bg)` | Active item background (outline variant) |
84
- | `--segmented_thumb-color` | `var(--bds-color_interactive)` | Filled thumb colour (filled variant) |
85
- | `--segmented_color` | `var(--bds-color_on-bg)` | Item text colour |
86
- | `--segmented_color--active` | `var(--bds-color_on-interactive)` (filled) / `var(--bds-color_interactive)` (outline) | Active item text colour |
86
+ | `--control_track-pad` | `var(--bds-space_xxs)` | Padding between the track edge and the items/thumb |
87
+ | `--control_track-bg` | `var(--bds-color_bg--subtle)` | Track background colour (both variants) |
88
+ | `--control_radius` | `var(--bds-border_radius--full)` | Track (outer) border radius pill by default |
89
+ | `--control_thumb-radius` | `var(--bds-border_radius--full)` | Thumb, indicator, and item border radius |
90
+ | `--control_thumb-bg` | `var(--bds-color_interactive)` | Filled thumb colour (filled variant) |
91
+ | `--control_thumb-shadow` | `var(--bds-shadow_s)` | Filled thumb box-shadow (filled variant) |
92
+ | `--control_indicator-width` | `2px` | Inset border width of the sliding indicator (outline variant) |
93
+ | `--control_indicator-color` | `var(--bds-color_interactive)` | Inset border colour of the sliding indicator (outline variant) |
94
+ | `--control_item-bg` | `transparent` | Inactive item background (outline variant) |
95
+ | `--control_item-bg--active` | `var(--bds-color_bg)` | Active item background (outline variant) |
96
+ | `--control_label-color` | `var(--bds-color_on-bg)` | Item text colour |
97
+ | `--control_label-color--active` | `var(--bds-color_on-interactive)` (filled) / `var(--bds-color_interactive)` (outline) | Active item text colour |
98
+ | `--control_label-color--hover` | `var(--bds-color_on-bg)` | Inactive, non-disabled item text colour on hover (fine pointers only) |
99
+
100
+ <details>
101
+ <summary>Deprecated aliases</summary>
102
+
103
+ | Old property | Maps to |
104
+ |--------------|---------|
105
+ | `--segmented_color_bg` | `--control_track-bg` |
106
+ | `--segmented_item-bg` | `--control_item-bg` |
107
+ | `--segmented_item-bg--active` | `--control_item-bg--active` |
108
+ | `--segmented_thumb-color` | `--control_thumb-bg` |
109
+ | `--segmented_color` | `--control_label-color` |
110
+ | `--segmented_color--active` | `--control_label-color--active` |
111
+
112
+ </details>
87
113
 
88
114
  ## Accessibility
89
115
 
90
- - In radio mode, each option renders as a visually hidden `<input type="radio">` inside a `<label>`, so keyboard users can navigate with arrow keys
91
- - In link mode, options render as `<a>` elements with `aria-current="page"` on the active item
116
+ - In radio mode, each option renders as a visually hidden `<input type="radio">` inside a `<label>`, so keyboard users can navigate with arrow keys; the visible `<label>` shows a focus ring when its radio has keyboard (`:focus-visible`) focus
117
+ - In link mode, options render as `<a>` elements with `aria-current="page"` on the active item and get the focus ring directly
92
118
  - Disabled options have `aria-disabled="true"` and remove the `href` from link mode items
93
119
  - `disabled` on the host element disables all options
94
120
  - The sliding thumb and indicator use `aria-hidden="true"` so they are not announced by screen readers
@@ -27,6 +27,15 @@ Use `<bds-select>` for pick-from-list dropdowns where users cannot type to searc
27
27
  ### With placeholder
28
28
  <Canvas of={Stories.WithPlaceholder} />
29
29
 
30
+ ### With label
31
+ <Canvas of={Stories.WithLabel} />
32
+
33
+ ### With hint
34
+ <Canvas of={Stories.WithHint} />
35
+
36
+ ### With error
37
+ <Canvas of={Stories.WithError} />
38
+
30
39
  ### Required
31
40
  <Canvas of={Stories.Required} />
32
41
 
@@ -48,20 +57,26 @@ Use `<bds-select>` for pick-from-list dropdowns where users cannot type to searc
48
57
  | `value` | string | `""` | Currently selected value |
49
58
  | `options` | string | `"[]"` | JSON array of `{ value, label, disabled? }` option objects |
50
59
  | `placeholder` | string | `""` | Placeholder option label (disabled, empty value) |
60
+ | `label` | string | `""` | Visible label text (rendered as a shadow `<label for>`) |
61
+ | `hint` | string | — | Helper text shown below the select |
62
+ | `error` | string | — | Error message; when set the select enters error state |
51
63
  | `required` | boolean | `false` | Marks the field as required |
52
64
  | `disabled` | boolean | `false` | Disables the select |
53
65
 
66
+ When `label` is omitted, set `aria-label` on the host element (`<bds-select aria-label="Country">`) and it is forwarded to the inner `<select>` so the control still has an accessible name.
67
+
54
68
  ## Events
55
69
 
56
- | Event | Detail | Description |
57
- |----------|--------|-------------------------------------------------------|
58
- | `change` | — | Native change event forwarded from the inner `<select>` |
70
+ | Event | Detail | Description |
71
+ |--------------|----------------------|-----------------------------------------|
72
+ | `bds-change` | `{ value: string }` | Fired when the selected value changes |
59
73
 
60
74
  ## Usage in plain HTML
61
75
 
62
76
  ```html
63
77
  <bds-select
64
78
  name="country"
79
+ label="Country"
65
80
  placeholder="Choose a country…"
66
81
  options='[{"value":"nl","label":"Netherlands"},{"value":"be","label":"Belgium"}]'
67
82
  ></bds-select>
@@ -70,7 +85,10 @@ Use `<bds-select>` for pick-from-list dropdowns where users cannot type to searc
70
85
  ## Accessibility
71
86
 
72
87
  - Wraps a native `<select>` which has full browser and assistive technology support
88
+ - `label` renders a shadow `<label for>` associated with the inner `<select>` via matching `id`/`for`; if omitted, a host `aria-label` is forwarded to the select instead
89
+ - `error` sets `aria-invalid="true"` and links the error message via `aria-describedby`; the message uses `role="alert"` so it is announced immediately
90
+ - `hint` is linked via `aria-describedby` for screen reader announcement
73
91
  - The custom chevron icon is `aria-hidden="true"` to avoid duplicate announcements
74
- - `required` uses the native `<select required>` attribute for browser validation
92
+ - `required` uses the native `<select required>` attribute for browser validation and sets `aria-required="true"`
75
93
  - `disabled` uses the native `<select disabled>` attribute
76
94
  - Participates in HTML forms via the Form-Associated Custom Elements API
@@ -22,6 +22,9 @@ function BdsSelect({
22
22
  value,
23
23
  options,
24
24
  placeholder,
25
+ label,
26
+ hint,
27
+ error,
25
28
  required,
26
29
  disabled,
27
30
  }: {
@@ -29,6 +32,9 @@ function BdsSelect({
29
32
  value?: string;
30
33
  options?: string;
31
34
  placeholder?: string;
35
+ label?: string;
36
+ hint?: string;
37
+ error?: string;
32
38
  required?: boolean;
33
39
  disabled?: boolean;
34
40
  }) {
@@ -37,6 +43,9 @@ function BdsSelect({
37
43
  value,
38
44
  options,
39
45
  placeholder,
46
+ label,
47
+ hint,
48
+ error,
40
49
  required: required || undefined,
41
50
  disabled: disabled || undefined,
42
51
  });
@@ -71,6 +80,30 @@ export const WithPlaceholder: Story = {
71
80
  args: { name: 'country', options: COUNTRIES, placeholder: 'Choose a country…' },
72
81
  };
73
82
 
83
+ export const WithLabel: Story = {
84
+ args: { name: 'country', options: COUNTRIES, label: 'Country', placeholder: 'Choose a country…' },
85
+ };
86
+
87
+ export const WithHint: Story = {
88
+ args: {
89
+ name: 'country',
90
+ options: COUNTRIES,
91
+ label: 'Country',
92
+ placeholder: 'Choose a country…',
93
+ hint: 'Used to calculate shipping costs',
94
+ },
95
+ };
96
+
97
+ export const WithError: Story = {
98
+ args: {
99
+ name: 'country',
100
+ options: COUNTRIES,
101
+ label: 'Country',
102
+ placeholder: 'Choose a country…',
103
+ error: 'Please select a country',
104
+ },
105
+ };
106
+
74
107
  export const Required: Story = {
75
108
  args: { name: 'country', options: COUNTRIES, placeholder: 'Choose a country…', required: true },
76
109
  };