@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
@@ -4,37 +4,43 @@
4
4
  display: inline-grid;
5
5
  grid-auto-flow: column;
6
6
  grid-auto-columns: 1fr;
7
- padding: var(--bds-space_xxxs);
7
+ padding: var(--control_track-pad, var(--bds-space_xxs));
8
8
  background-color: var(--control_track-bg, var(--bds-color_bg--subtle));
9
9
  border-radius: var(--control_radius, var(--bds-border_radius--full));
10
10
  gap: 0;
11
+ --control_dir: 1;
12
+ }
13
+
14
+ [dir='rtl'] .control,
15
+ .control[dir='rtl'] {
16
+ --control_dir: -1;
11
17
  }
12
18
 
13
19
  /* Filled variant: sliding background thumb */
14
20
  .thumb {
15
21
  position: absolute;
16
- inset-block: var(--bds-space_xxxs);
17
- inset-inline-start: var(--bds-space_xxxs);
18
- inline-size: calc((100% - 2 * var(--bds-space_xxxs)) / var(--control_count, 1));
22
+ inset-block: var(--control_track-pad, var(--bds-space_xxs));
23
+ inset-inline-start: var(--control_track-pad, var(--bds-space_xxs));
24
+ inline-size: calc((100% - 2 * var(--control_track-pad, var(--bds-space_xxs))) / var(--control_count, 1));
19
25
  border-radius: var(--control_thumb-radius, var(--bds-border_radius--full));
20
26
  background-color: var(--control_thumb-bg, var(--bds-color_interactive));
21
- box-shadow: var(--bds-shadow_s);
27
+ box-shadow: var(--control_thumb-shadow, var(--bds-shadow_s));
22
28
  pointer-events: none;
23
- transform: translateX(calc(var(--control_selected-index, 0) * 100%));
29
+ transform: translateX(calc(var(--control_selected-index, 0) * var(--control_dir, 1) * 100%));
24
30
  transition: transform var(--bds-animation_transition-duration) var(--bds-animation_easing);
25
31
  }
26
32
 
27
33
  /* Outline variant: sliding inset-border indicator */
28
34
  .indicator {
29
35
  position: absolute;
30
- inset-block: var(--bds-space_xxxs);
31
- inset-inline-start: var(--bds-space_xxxs);
32
- inline-size: calc((100% - 2 * var(--bds-space_xxxs)) / var(--control_count, 1));
36
+ inset-block: var(--control_track-pad, var(--bds-space_xxs));
37
+ inset-inline-start: var(--control_track-pad, var(--bds-space_xxs));
38
+ inline-size: calc((100% - 2 * var(--control_track-pad, var(--bds-space_xxs))) / var(--control_count, 1));
33
39
  border-radius: var(--control_thumb-radius, var(--bds-border_radius--full));
34
40
  pointer-events: none;
35
41
  z-index: 2;
36
42
  display: none;
37
- transform: translateX(calc(var(--control_selected-index, 0) * 100%));
43
+ transform: translateX(calc(var(--control_selected-index, 0) * var(--control_dir, 1) * 100%));
38
44
  transition: transform var(--bds-animation_transition-duration) var(--bds-animation_easing);
39
45
  }
40
46
 
@@ -47,7 +53,7 @@
47
53
  justify-content: center;
48
54
  cursor: pointer;
49
55
  border-radius: var(--control_thumb-radius, var(--bds-border_radius--full));
50
- padding: var(--bds-space_xs) var(--bds-space_m);
56
+ padding: var(--control_item-padding, var(--bds-space_xs) var(--bds-space_m));
51
57
  font-size: var(--bds-font_size--body);
52
58
  font-family: var(--bds-font_family--body);
53
59
  line-height: var(--bds-font_line-height--body);
@@ -109,7 +115,14 @@
109
115
 
110
116
  .control.--variant_outline .indicator {
111
117
  display: block;
112
- box-shadow: inset 0 0 0 2px var(--control_indicator-color, var(--bds-color_interactive));
118
+ box-shadow: inset 0 0 0 var(--control_indicator-width, 2px) var(--control_indicator-color, var(--bds-color_interactive));
119
+ }
120
+
121
+ /* No item is active (no selectedIndex and no ARIA-marked child) — hide the sliding visuals.
122
+ Placed after the variant rules above so it wins the equal-specificity cascade. */
123
+ .control.--no-selection .thumb,
124
+ .control.--no-selection .indicator {
125
+ display: none;
113
126
  }
114
127
 
115
128
  @media (hover: hover) and (pointer: fine) {
@@ -40,13 +40,35 @@ describe('SegmentedControl', () => {
40
40
  expect(getControl(container).style.getPropertyValue('--control_selected-index')).toBe('2');
41
41
  });
42
42
 
43
- it('defaults to index 0 when no selectedIndex or aria attributes are provided', () => {
43
+ it('has no active item when neither selectedIndex nor an aria attribute is provided', () => {
44
44
  const { container } = render(
45
45
  <SegmentedControl>
46
46
  <button>A</button>
47
47
  <button>B</button>
48
48
  </SegmentedControl>,
49
49
  );
50
+ expect(getControl(container).style.getPropertyValue('--control_selected-index')).toBe('');
51
+ expect(screen.getByText('A').closest('button')).not.toHaveAttribute('aria-pressed');
52
+ expect(screen.getByText('B').closest('button')).not.toHaveAttribute('aria-pressed');
53
+ });
54
+
55
+ it('clamps an out-of-range selectedIndex to the last child', () => {
56
+ const { container } = render(
57
+ <SegmentedControl selectedIndex={99}>
58
+ <button>A</button>
59
+ <button>B</button>
60
+ </SegmentedControl>,
61
+ );
62
+ expect(getControl(container).style.getPropertyValue('--control_selected-index')).toBe('1');
63
+ });
64
+
65
+ it('clamps a negative selectedIndex to the first child', () => {
66
+ const { container } = render(
67
+ <SegmentedControl selectedIndex={-5}>
68
+ <button>A</button>
69
+ <button>B</button>
70
+ </SegmentedControl>,
71
+ );
50
72
  expect(getControl(container).style.getPropertyValue('--control_selected-index')).toBe('0');
51
73
  });
52
74
 
@@ -119,10 +141,69 @@ describe('SegmentedControl', () => {
119
141
  <button>B</button>
120
142
  </SegmentedControl>,
121
143
  );
122
- // Items get the --disabled modifier class — verify via aria or opacity is difficult;
123
- // check that pointer-events is none (jsdom doesn't apply CSS, so just verify the class is injected).
124
- // We verify by checking that buttons still render and the container has the right CSS var.
125
- expect(screen.getByText('A')).toBeInTheDocument();
144
+ expect(screen.getByText('A').closest('button')).toBeDisabled();
145
+ expect(screen.getByText('A').closest('button')).toHaveAttribute('aria-disabled', 'true');
146
+ expect(screen.getByText('B').closest('button')).toBeDisabled();
147
+ expect(screen.getByText('B').closest('button')).toHaveAttribute('aria-disabled', 'true');
148
+ });
149
+
150
+ it('disables only the child that sets its own disabled prop', () => {
151
+ render(
152
+ <SegmentedControl selectedIndex={0}>
153
+ <button>A</button>
154
+ <button disabled>B</button>
155
+ </SegmentedControl>,
156
+ );
157
+ expect(screen.getByText('A').closest('button')).not.toBeDisabled();
158
+ expect(screen.getByText('B').closest('button')).toBeDisabled();
159
+ expect(screen.getByText('B').closest('button')).toHaveAttribute('aria-disabled', 'true');
160
+ });
161
+
162
+ it('makes disabled link children keyboard-unreachable and blocks activation', async () => {
163
+ const user = userEvent.setup();
164
+ const onClick = vi.fn();
165
+ render(
166
+ <SegmentedControl disabled>
167
+ <a href="#" onClick={onClick}>Overview</a>
168
+ </SegmentedControl>,
169
+ );
170
+ const link = screen.getByText('Overview');
171
+ expect(link).toHaveAttribute('aria-disabled', 'true');
172
+ expect(link).toHaveAttribute('tabindex', '-1');
173
+ await user.click(link);
174
+ expect(onClick).not.toHaveBeenCalled();
175
+ });
176
+
177
+ it('injects aria-pressed on the active button when selectedIndex drives selection without an existing aria state', () => {
178
+ render(
179
+ <SegmentedControl selectedIndex={1}>
180
+ <button>A</button>
181
+ <button>B</button>
182
+ </SegmentedControl>,
183
+ );
184
+ expect(screen.getByText('B').closest('button')).toHaveAttribute('aria-pressed', 'true');
185
+ expect(screen.getByText('A').closest('button')).not.toHaveAttribute('aria-pressed');
186
+ });
187
+
188
+ it('injects aria-current="page" on the active link when selectedIndex drives selection without an existing aria state', () => {
189
+ render(
190
+ <SegmentedControl selectedIndex={0}>
191
+ <a href="#">Overview</a>
192
+ <a href="#">Usage</a>
193
+ </SegmentedControl>,
194
+ );
195
+ expect(screen.getByText('Overview')).toHaveAttribute('aria-current', 'page');
196
+ expect(screen.getByText('Usage')).not.toHaveAttribute('aria-current');
197
+ });
198
+
199
+ it('does not override an aria state the consumer already set', () => {
200
+ render(
201
+ <SegmentedControl selectedIndex={0}>
202
+ <button aria-pressed={false}>A</button>
203
+ <button>B</button>
204
+ </SegmentedControl>,
205
+ );
206
+ expect(screen.getByText('A').closest('button')).toHaveAttribute('aria-pressed', 'false');
126
207
  });
127
208
 
128
209
  it('forwards existing className on children', () => {
@@ -1,4 +1,4 @@
1
- import { Children, HTMLAttributes, ReactElement, cloneElement, isValidElement } from 'react';
1
+ import { Children, HTMLAttributes, MouseEvent, ReactElement, cloneElement, isValidElement } from 'react';
2
2
  import css from './SegmentedControl.module.css';
3
3
  import { cn } from '@boostdev/design-system-foundation';
4
4
  import type { WithClassName } from '../../../../types';
@@ -16,6 +16,11 @@ export interface SegmentedControlProps extends WithClassName, HTMLAttributes<HTM
16
16
  variant?: 'outline' | 'filled';
17
17
  }
18
18
 
19
+ /** Non-button children (e.g. links) have no native `disabled` attribute — block activation manually. */
20
+ const preventDisabledActivation = (event: MouseEvent<HTMLElement>) => {
21
+ event.preventDefault();
22
+ };
23
+
19
24
  export function SegmentedControl({
20
25
  children,
21
26
  selectedIndex: selectedIndexProp,
@@ -35,16 +40,31 @@ export function SegmentedControl({
35
40
  })
36
41
  : -1;
37
42
 
38
- const activeIndex = Math.max(0, selectedIndexProp ?? (autoIndex >= 0 ? autoIndex : 0));
43
+ // An explicit selectedIndex is clamped to the valid child range. Otherwise fall back to ARIA
44
+ // auto-detection. When neither is available, no item is active — the thumb/indicator stay hidden
45
+ // rather than defaulting to index 0.
46
+ const activeIndex = validChildren.length === 0
47
+ ? undefined
48
+ : selectedIndexProp !== undefined
49
+ ? Math.min(Math.max(selectedIndexProp, 0), validChildren.length - 1)
50
+ : autoIndex >= 0
51
+ ? autoIndex
52
+ : undefined;
39
53
 
40
54
  return (
41
55
  <div
42
56
  {...rest}
43
57
  role="group"
44
- className={cn(css.control, css[`--size_${size}`], css[`--variant_${variant}`], className)}
58
+ className={cn(
59
+ css.control,
60
+ css[`--size_${size}`],
61
+ css[`--variant_${variant}`],
62
+ activeIndex === undefined && css['--no-selection'],
63
+ className,
64
+ )}
45
65
  style={{
46
66
  '--control_count': validChildren.length,
47
- '--control_selected-index': activeIndex,
67
+ ...(activeIndex !== undefined ? { '--control_selected-index': activeIndex } : {}),
48
68
  } as React.CSSProperties}
49
69
  >
50
70
  <span className={css.thumb} aria-hidden="true" />
@@ -54,8 +74,28 @@ export function SegmentedControl({
54
74
  const isActive = index === activeIndex;
55
75
  const p = child.props as Record<string, unknown>;
56
76
  const isDisabled = disabled || !!p.disabled || p['aria-disabled'] === true;
77
+ const hasAriaState = p['aria-current'] !== undefined || p['aria-pressed'] !== undefined || p['aria-selected'] !== undefined;
78
+
79
+ const stateProps: Record<string, unknown> = {};
80
+ if (isDisabled) {
81
+ // Enforce disabled state for keyboard and expose it to assistive tech — the visual
82
+ // --disabled modifier alone leaves items keyboard-operable and unannounced.
83
+ stateProps['aria-disabled'] = true;
84
+ if (child.type === 'button') {
85
+ stateProps.disabled = true;
86
+ } else {
87
+ stateProps.tabIndex = -1;
88
+ stateProps.onClick = preventDisabledActivation;
89
+ }
90
+ } else if (isActive && selectedIndexProp !== undefined && !hasAriaState) {
91
+ // selectedIndex drives the visual active state; mirror it in ARIA when the consumer
92
+ // hasn't already wired their own aria-current/aria-pressed/aria-selected attribute.
93
+ stateProps[child.type === 'a' ? 'aria-current' : 'aria-pressed'] = child.type === 'a' ? 'page' : true;
94
+ }
95
+
57
96
  return cloneElement(child, {
58
97
  key: child.key ?? index,
98
+ ...stateProps,
59
99
  className: cn(
60
100
  css.item,
61
101
  isActive && css['--active'],
@@ -41,12 +41,18 @@ Native dropdown for choosing one option from a list. Renders a styled `<select>`
41
41
 
42
42
  <table>
43
43
  <thead>
44
- <tr><th>Variable</th><th>Description</th></tr>
44
+ <tr><th>Variable</th><th>Default</th><th>Description</th></tr>
45
45
  </thead>
46
46
  <tbody>
47
- <tr><td>`--select_border-color`</td><td>Border colour</td></tr>
48
- <tr><td>`--select_color`</td><td>Background colour</td></tr>
49
- <tr><td>`--select_on-color`</td><td>Text colour</td></tr>
47
+ <tr><td>`--select_border`</td><td>`none`</td><td>Additional border shorthand</td></tr>
48
+ <tr><td>`--select_radius`</td><td>`var(--bds-border_radius--full)`</td><td>Corner radius</td></tr>
49
+ <tr><td>`--select_shadow`</td><td>`var(--bdc-outline_shadow)`</td><td>Box shadow</td></tr>
50
+ <tr><td>`--select_color_bg`</td><td>`var(--bds-color_bg)`</td><td>Background colour</td></tr>
51
+ <tr><td>`--select_color`</td><td>`var(--bds-color_on-bg)`</td><td>Text colour</td></tr>
52
+ <tr><td>`--select_chevron-color`</td><td>`var(--bds-color_interactive)`</td><td>Chevron icon colour</td></tr>
53
+ <tr><td>`--select_padding`</td><td>`var(--bds-space_s)`</td><td>Control padding</td></tr>
54
+ <tr><td>`--select_padding-end`</td><td>`var(--bds-space_xxl)`</td><td>Inline-end padding (reserves space for the chevron)</td></tr>
55
+ <tr><td>`--select_chevron-size`</td><td>`1rem`</td><td>Chevron icon size</td></tr>
50
56
  </tbody>
51
57
  </table>
52
58
 
@@ -15,8 +15,8 @@
15
15
  inline-size: 100%;
16
16
  font-family: var(--bds-font_family--body);
17
17
  font-size: var(--bds-font_size--body);
18
- padding: var(--bds-space_s);
19
- padding-inline-end: var(--bds-space_xxl);
18
+ padding: var(--select_padding, var(--bds-space_s));
19
+ padding-inline-end: var(--select_padding-end, var(--bds-space_xxl));
20
20
  border: var(--select_border, none);
21
21
  --bdc_color: currentcolor;
22
22
  --bdc-outline_radius: var(--bds-border_radius--full);
@@ -58,7 +58,7 @@
58
58
  }
59
59
 
60
60
  .chevron svg {
61
- inline-size: 1rem;
62
- block-size: 1rem;
61
+ inline-size: var(--select_chevron-size, 1rem);
62
+ block-size: var(--select_chevron-size, 1rem);
63
63
  }
64
64
  }
@@ -32,6 +32,32 @@ describe('Select', () => {
32
32
  expect(screen.getByText('Pick a country')).toBeInTheDocument();
33
33
  });
34
34
 
35
+ it('selects the placeholder option initially when uncontrolled', () => {
36
+ render(<Select label="Country" name="country" options={options} placeholder="Pick a country" />);
37
+ expect(screen.getByRole('combobox')).toHaveValue('');
38
+ });
39
+
40
+ it('selects the provided defaultValue instead of the placeholder when uncontrolled', () => {
41
+ render(
42
+ <Select label="Country" name="country" options={options} placeholder="Pick a country" defaultValue="be" />
43
+ );
44
+ expect(screen.getByRole('combobox')).toHaveValue('be');
45
+ });
46
+
47
+ it('respects a controlled value over the placeholder', () => {
48
+ render(
49
+ <Select
50
+ label="Country"
51
+ name="country"
52
+ options={options}
53
+ placeholder="Pick a country"
54
+ value="nl"
55
+ onChange={vi.fn()}
56
+ />
57
+ );
58
+ expect(screen.getByRole('combobox')).toHaveValue('nl');
59
+ });
60
+
35
61
  it('marks a disabled option as disabled', () => {
36
62
  render(<Select label="Country" name="country" options={options} />);
37
63
  expect(screen.getByRole('option', { name: 'Germany' })).toBeDisabled();
@@ -59,4 +85,12 @@ describe('Select', () => {
59
85
  await user.selectOptions(screen.getByRole('combobox'), 'nl');
60
86
  expect(onChange).toHaveBeenCalled();
61
87
  });
88
+
89
+ it('keeps the label and error message associated with a consumer-provided id', () => {
90
+ render(<Select label="Country" name="country" options={options} error="Required" id="custom-id" />);
91
+ const select = screen.getByLabelText('Country');
92
+ expect(select).toHaveAttribute('id', 'custom-id');
93
+ expect(select).toHaveAttribute('aria-describedby', 'custom-iderror');
94
+ expect(screen.getByText('Required')).toHaveAttribute('id', 'custom-iderror');
95
+ });
62
96
  });
@@ -30,26 +30,38 @@ export function Select({
30
30
  hint,
31
31
  className,
32
32
  required,
33
- ...props
33
+ id,
34
+ value,
35
+ defaultValue,
36
+ ...rest
34
37
  }: Readonly<SelectProps>) {
35
- const id = name + useId();
36
- const hintId = id + 'hint';
37
- const errorId = id + 'error';
38
+ const generatedId = name + useId();
39
+ const selectId = id ?? generatedId;
40
+ const hintId = selectId + 'hint';
41
+ const errorId = selectId + 'error';
38
42
  const describedBy = [error && errorId, hint && hintId].filter(Boolean).join(' ') || undefined;
43
+ // Uncontrolled selects need an explicit defaultValue of "" so the disabled+hidden
44
+ // placeholder option is the initial selection (browsers otherwise preselect the
45
+ // first non-disabled <option>).
46
+ const isControlled = value !== undefined;
47
+ const initialValueProps = isControlled
48
+ ? { value }
49
+ : { defaultValue: defaultValue ?? (placeholder ? '' : undefined) };
39
50
 
40
51
  return (
41
52
  <InputContainer className={cn(css.formGroup, className)}>
42
- <Label id={id} label={label} />
53
+ <Label id={selectId} label={label} />
43
54
  <div className={css.selectWrapper}>
44
55
  <select
45
- id={id}
56
+ {...rest}
57
+ id={selectId}
46
58
  name={name}
47
59
  aria-invalid={!!error}
48
60
  aria-required={required || undefined}
49
61
  aria-describedby={describedBy}
50
62
  required={required}
51
63
  className={cn(css.select, error ? css.selectError : undefined)}
52
- {...props}
64
+ {...initialValueProps}
53
65
  >
54
66
  {placeholder && (
55
67
  <option value="" disabled hidden>
@@ -68,8 +80,8 @@ export function Select({
68
80
  </svg>
69
81
  </span>
70
82
  </div>
71
- <Message inputId={id} type="error" message={error} />
72
- <Message inputId={id} type="hint" message={hint} />
83
+ <Message inputId={selectId} type="error" message={error} />
84
+ <Message inputId={selectId} type="hint" message={hint} />
73
85
  </InputContainer>
74
86
  );
75
87
  }
@@ -48,7 +48,9 @@ Range input for selecting a numeric value within a bounded range.
48
48
  <tbody>
49
49
  <tr><td>`--slider_color-active`</td><td>`var(--bdc-color_active)`</td><td>Filled track and thumb colour</td></tr>
50
50
  <tr><td>`--slider_track-bg`</td><td>`var(--bds-color_bg--subtle)`</td><td>Unfilled track background</td></tr>
51
+ <tr><td>`--slider_track-height`</td><td>`var(--bds-space_xxs)`</td><td>Track thickness</td></tr>
51
52
  <tr><td>`--slider_track-radius`</td><td>`var(--bds-border_radius--full)`</td><td>Track border radius</td></tr>
53
+ <tr><td>`--slider_thumb-size`</td><td>`calc(var(--bds-space_s) * 2)`</td><td>Thumb diameter</td></tr>
52
54
  <tr><td>`--slider_thumb-radius`</td><td>`var(--bds-border_radius--circle)`</td><td>Thumb border radius</td></tr>
53
55
  <tr><td>`--slider_color--error`</td><td>`var(--bds-color_error)`</td><td>Track and thumb colour in error state</td></tr>
54
56
  </tbody>
@@ -57,6 +59,7 @@ Range input for selecting a numeric value within a bounded range.
57
59
 
58
60
  ## Accessibility
59
61
 
60
- - Native `<input type="range">` with `aria-valuemin`, `aria-valuemax`, `aria-valuenow`
62
+ - Native `<input type="range">` the browser derives the accessible value (`aria-valuemin`/`aria-valuemax`/`aria-valuenow`/`aria-valuetext`) from the `min`/`max`/`value` attributes automatically, so the component does not set redundant ARIA value attributes
63
+ - Sets `aria-invalid` when `error` is provided
61
64
  - Label linked via `id`/`htmlFor`
62
65
  - Arrow keys adjust value by `step`; `Home`/`End` jump to min/max
@@ -18,14 +18,12 @@
18
18
  }
19
19
 
20
20
  .slider {
21
- --slider_fill: 0%;
22
- --slider_track-height: var(--bds-space_xxs);
23
- --slider_thumb-size: calc(var(--bds-space_s) * 2);
21
+ --slider_fill: 0%;
24
22
 
25
23
  color: var(--slider_color, var(--bds-color_on-bg));
26
24
  appearance: none;
27
25
  inline-size: 100%;
28
- block-size: var(--slider_track-height);
26
+ block-size: var(--slider_track-height, var(--bds-space_xxs));
29
27
  border-radius: var(--slider_track-radius, var(--bds-border_radius--full));
30
28
  background: linear-gradient(
31
29
  to right,
@@ -38,6 +36,22 @@
38
36
  transition: var(--bds-animation_transition);
39
37
  }
40
38
 
39
+ /*
40
+ * The fill gradient is drawn with the physical `to right`, but native range
41
+ * inputs flip their fill direction under RTL writing modes. `:dir(rtl)`
42
+ * mirrors the gradient so the filled portion still grows from the thumb's
43
+ * resting edge instead of visually disagreeing with the native thumb position.
44
+ */
45
+ .slider:dir(rtl) {
46
+ background: linear-gradient(
47
+ to left,
48
+ var(--slider_color-active, var(--bdc-color_active)) 0%,
49
+ var(--slider_color-active, var(--bdc-color_active)) var(--slider_fill),
50
+ var(--slider_track-bg, var(--bds-color_bg--subtle)) var(--slider_fill),
51
+ var(--slider_track-bg, var(--bds-color_bg--subtle)) 100%
52
+ );
53
+ }
54
+
41
55
  .slider:focus-visible {
42
56
  outline: var(--bds-outline_default);
43
57
  outline-offset: var(--bds-outline_offset);
@@ -52,8 +66,8 @@
52
66
  /* Thumb — Webkit */
53
67
  .slider::-webkit-slider-thumb {
54
68
  appearance: none;
55
- inline-size: var(--slider_thumb-size);
56
- block-size: var(--slider_thumb-size);
69
+ inline-size: var(--slider_thumb-size, calc(var(--bds-space_s) * 2));
70
+ block-size: var(--slider_thumb-size, calc(var(--bds-space_s) * 2));
57
71
  border-radius: var(--slider_thumb-radius, var(--bds-border_radius--circle));
58
72
  background-color: var(--slider_color-active, var(--bdc-color_active));
59
73
  box-shadow: var(--bds-shadow_s);
@@ -63,8 +77,8 @@
63
77
 
64
78
  /* Thumb — Firefox */
65
79
  .slider::-moz-range-thumb {
66
- inline-size: var(--slider_thumb-size);
67
- block-size: var(--slider_thumb-size);
80
+ inline-size: var(--slider_thumb-size, calc(var(--bds-space_s) * 2));
81
+ block-size: var(--slider_thumb-size, calc(var(--bds-space_s) * 2));
68
82
  border: none;
69
83
  border-radius: var(--slider_thumb-radius, var(--bds-border_radius--circle));
70
84
  background-color: var(--slider_color-active, var(--bdc-color_active));
@@ -82,6 +96,16 @@
82
96
  );
83
97
  }
84
98
 
99
+ .sliderError:dir(rtl) {
100
+ background: linear-gradient(
101
+ to left,
102
+ var(--slider_color--error, var(--bds-color_error)) 0%,
103
+ var(--slider_color--error, var(--bds-color_error)) var(--slider_fill),
104
+ var(--slider_track-bg, var(--bds-color_bg--subtle)) var(--slider_fill),
105
+ var(--slider_track-bg, var(--bds-color_bg--subtle)) 100%
106
+ );
107
+ }
108
+
85
109
  .sliderError::-webkit-slider-thumb {
86
110
  background-color: var(--slider_color--error, var(--bds-color_error));
87
111
  }
@@ -50,4 +50,33 @@ describe('Slider', () => {
50
50
  render(<Slider label="Volume" name="volume" disabled />);
51
51
  expect(screen.getByRole('slider')).toBeDisabled();
52
52
  });
53
+
54
+ it('seeds internal state from the native midpoint default when uncontrolled without a defaultValue', () => {
55
+ render(<Slider label="Volume" name="volume" showValue />);
56
+ expect(screen.getByText('50')).toBeInTheDocument();
57
+ const slider = screen.getByRole('slider') as HTMLInputElement;
58
+ expect(slider.style.getPropertyValue('--slider_fill')).toBe('50%');
59
+ });
60
+
61
+ it('seeds internal state from the midpoint of a custom range when uncontrolled', () => {
62
+ render(<Slider label="Rating" name="rating" min={0} max={20} showValue />);
63
+ expect(screen.getByText('10')).toBeInTheDocument();
64
+ });
65
+
66
+ it('sets aria-invalid when there is an error', () => {
67
+ render(<Slider label="Volume" name="volume" error="Required" />);
68
+ expect(screen.getByRole('slider')).toHaveAttribute('aria-invalid', 'true');
69
+ });
70
+
71
+ it('keeps its own id when a consumer passes a conflicting id prop, preserving label association', () => {
72
+ render(<Slider label="Volume" name="volume" id="consumer-id" />);
73
+ expect(screen.getByLabelText('Volume')).toBeInTheDocument();
74
+ });
75
+
76
+ it('merges a consumer style prop with the internal fill custom property', () => {
77
+ render(<Slider label="Volume" name="volume" defaultValue={25} style={{ opacity: 0.5 }} />);
78
+ const slider = screen.getByRole('slider') as HTMLInputElement;
79
+ expect(slider.style.opacity).toBe('0.5');
80
+ expect(slider.style.getPropertyValue('--slider_fill')).toBe('25%');
81
+ });
53
82
  });
@@ -34,7 +34,12 @@ export function Slider({
34
34
  const describedBy = [error && errorId, hint && hintId].filter(Boolean).join(' ') || undefined;
35
35
 
36
36
  const isControlled = props.value !== undefined;
37
- const [internalValue, setInternalValue] = useState(Number(props.defaultValue ?? min));
37
+ // Seed internal state from the true initial value: a native range input with no
38
+ // defaultValue renders its thumb at the midpoint, not at `min`. Matching that here
39
+ // keeps state, fill percentage and showValue in sync with what the browser paints.
40
+ const [internalValue, setInternalValue] = useState(
41
+ Number(props.defaultValue ?? min + (max - min) / 2),
42
+ );
38
43
  const currentValue = isControlled ? Number(props.value) : internalValue;
39
44
 
40
45
  const fillPct = ((currentValue - min) / (max - min)) * 100;
@@ -51,20 +56,17 @@ export function Slider({
51
56
  {showValue && <span className={css.value}>{currentValue}</span>}
52
57
  </div>
53
58
  <input
59
+ {...props}
54
60
  type="range"
55
61
  id={id}
56
62
  name={name}
57
63
  min={min}
58
64
  max={max}
65
+ aria-invalid={!!error}
59
66
  aria-describedby={describedBy}
60
- aria-valuemin={min}
61
- aria-valuemax={max}
62
- aria-valuenow={currentValue}
63
- aria-valuetext={String(currentValue)}
64
67
  className={cn(css.slider, error ? css.sliderError : undefined)}
65
- style={{ '--slider_fill': `${fillPct}%` } as CSSProperties}
68
+ style={{ ...props.style, '--slider_fill': `${fillPct}%` } as CSSProperties}
66
69
  onChange={handleChange}
67
- {...props}
68
70
  />
69
71
  <Message inputId={id} type="error" message={error} />
70
72
  <Message inputId={id} type="hint" message={hint} />
@@ -53,9 +53,9 @@ Toggle control for binary settings that take immediate effect — without requir
53
53
  </thead>
54
54
  <tbody>
55
55
  <tr><td>`--switch_track-bg`</td><td>`var(--bds-color_grey--subtle)`</td><td>Track background when off</td></tr>
56
- <tr><td>`--switch_thumb-bg`</td><td>`var(--bds-color_grey)`</td><td>Thumb colour when off (also track outline)</td></tr>
56
+ <tr><td>`--switch_thumb-bg`</td><td>`var(--bds-color_interactive)`</td><td>Thumb colour when off (also track outline)</td></tr>
57
57
  <tr><td>`--switch_track-bg--active`</td><td>`var(--bdc-color_active--subtle)`</td><td>Track background when on</td></tr>
58
- <tr><td>`--switch_thumb-bg--active`</td><td>`var(--bdc-color_active--strong)`</td><td>Thumb colour when on (also track outline)</td></tr>
58
+ <tr><td>`--switch_thumb-bg--active`</td><td>`var(--bds-color_interactive)`</td><td>Thumb colour when on (also track outline)</td></tr>
59
59
  <tr><td>`--switch_track-radius`</td><td>`var(--bds-border_radius--full)`</td><td>Track border radius</td></tr>
60
60
  <tr><td>`--switch_thumb-radius`</td><td>`var(--bds-border_radius--circle)`</td><td>Thumb border radius</td></tr>
61
61
  <tr><td>`--switch_border-color--error`</td><td>`var(--bds-color_error)`</td><td>Track outline colour in error state</td></tr>