@boostdev/design-system-components 2.8.0 → 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 (534) 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-OF6FFGOT.js → chunk-3AY2YKCM.js} +77 -21
  15. package/dist/web-components/chunk-3WAV6MDN.js +212 -0
  16. package/dist/web-components/{chunk-UUKSDCYS.js → chunk-47AT5KZD.js} +87 -15
  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-QLT6MTZF.js → chunk-AIBOHNDU.js} +10 -0
  23. package/dist/web-components/{chunk-X3NQMBAQ.js → chunk-AP4RDUL2.js} +14 -3
  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-ARMKC4BQ.js → chunk-JH6LQKLK.js} +77 -5
  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-FSZRP43R.js → chunk-WFVKU4GX.js} +21 -10
  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-ORC56MDY.js → chunk-XIZWAWMJ.js} +45 -6
  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 +55 -8
  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 +101 -16
  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 +135 -22
  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 +95 -7
  441. package/src/web-components/interaction/form/bds-slider.spec.ts +83 -0
  442. package/src/web-components/interaction/form/bds-slider.ts +154 -26
  443. package/src/web-components/interaction/form/bds-switch.spec.ts +68 -0
  444. package/src/web-components/interaction/form/bds-switch.ts +87 -20
  445. package/src/web-components/interaction/form/bds-textarea.spec.ts +71 -0
  446. package/src/web-components/interaction/form/bds-textarea.ts +108 -7
  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 +29 -11
  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 +109 -32
  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 +15 -14
  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 +10 -0
  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 +17 -4
  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-7YURXHTS.js +0 -147
  526. package/dist/web-components/chunk-A3RLT3AS.js +0 -49
  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-DZOEPVFT.js +0 -107
  530. package/dist/web-components/chunk-JYYRJS2D.js +0 -118
  531. package/dist/web-components/chunk-Y4MAXTMA.js +0 -80
  532. package/dist/web-components/chunk-Y7V7LM6R.js +0 -98
  533. package/src/web-components/ui/BdsButtonGroup.mdx +0 -69
  534. package/src/web-components/ui/BdsButtonGroup.stories.tsx +0 -66
@@ -1,10 +1,5 @@
1
1
  @layer boostdev.component {
2
2
  .switchGroup {
3
- --switch_thumb-size: 1.25em;
4
- --switch_track-pad: var(--bds-space_xxxs);
5
- --switch_track-height: calc(var(--switch_thumb-size) + var(--switch_track-pad) * 2);
6
- --switch_track-width: calc(var(--switch_thumb-size) * 2 + var(--switch_track-pad) * 2);
7
-
8
3
  color: var(--switch_color, var(--bds-color_on-bg));
9
4
  display: flex;
10
5
  flex-direction: column;
@@ -25,8 +20,8 @@
25
20
  display: inline-flex;
26
21
  align-items: center;
27
22
  flex-shrink: 0;
28
- inline-size: var(--switch_track-width);
29
- block-size: var(--switch_track-height);
23
+ inline-size: calc(var(--switch_thumb-size, 1.25em) * 2 + var(--switch_track-pad, var(--bds-space_xxxs)) * 2);
24
+ block-size: calc(var(--switch_thumb-size, 1.25em) + var(--switch_track-pad, var(--bds-space_xxxs)) * 2);
30
25
  }
31
26
 
32
27
  /* Real input — invisible overlay to capture pointer/keyboard events */
@@ -50,11 +45,11 @@
50
45
  .track {
51
46
  display: inline-flex;
52
47
  align-items: center;
53
- inline-size: var(--switch_track-width);
54
- block-size: var(--switch_track-height);
48
+ inline-size: calc(var(--switch_thumb-size, 1.25em) * 2 + var(--switch_track-pad, var(--bds-space_xxxs)) * 2);
49
+ block-size: calc(var(--switch_thumb-size, 1.25em) + var(--switch_track-pad, var(--bds-space_xxxs)) * 2);
55
50
  border-radius: var(--switch_track-radius, var(--bds-border_radius--full));
56
51
  background-color: var(--switch_track-bg, var(--bds-color_grey--subtle));
57
- padding-inline: var(--switch_track-pad);
52
+ padding-inline: var(--switch_track-pad, var(--bds-space_xxxs));
58
53
  pointer-events: none;
59
54
  box-shadow: inset 0 0 0 var(--bdc-outline_width) var(--bdc_color), var(--switch_shadow, var(--bdc-outline_shadow));
60
55
  transition: --bdc_color var(--bds-animation_transition-duration) var(--bds-animation_easing),
@@ -67,8 +62,8 @@
67
62
  /* Thumb */
68
63
  .thumb {
69
64
  display: block;
70
- inline-size: var(--switch_thumb-size);
71
- block-size: var(--switch_thumb-size);
65
+ inline-size: var(--switch_thumb-size, 1.25em);
66
+ block-size: var(--switch_thumb-size, 1.25em);
72
67
  border-radius: var(--switch_thumb-radius, var(--bds-border_radius--circle));
73
68
  background-color: var(--switch_thumb-bg, var(--bds-color_interactive));
74
69
  box-shadow: var(--bds-shadow_s);
@@ -90,7 +85,11 @@
90
85
 
91
86
  .switch:checked + .track .thumb {
92
87
  background-color: var(--switch_thumb-bg--active, var(--bds-color_interactive));
93
- transform: translateX(var(--switch_thumb-size));
88
+ transform: translateX(var(--switch_thumb-size, 1.25em));
89
+ }
90
+
91
+ [dir='rtl'] .switch:checked + .track .thumb {
92
+ transform: translateX(calc(var(--switch_thumb-size, 1.25em) * -1));
94
93
  }
95
94
 
96
95
  /* Focus visible on the visual track */
@@ -68,4 +68,24 @@ describe('Switch', () => {
68
68
  render(<Switch label="Toggle" name="size-l" size="large" />);
69
69
  expect(screen.getByRole('switch').closest('.switchGroup')).toHaveClass('--size_large');
70
70
  });
71
+
72
+ it('sets aria-invalid when an error is present', () => {
73
+ render(<Switch label="Accept" name="accept" error="Required" />);
74
+ expect(screen.getByRole('switch')).toHaveAttribute('aria-invalid', 'true');
75
+ });
76
+
77
+ it('does not set aria-invalid when there is no error', () => {
78
+ render(<Switch label="Accept" name="accept" />);
79
+ expect(screen.getByRole('switch')).toHaveAttribute('aria-invalid', 'false');
80
+ });
81
+
82
+ it('keeps the label associated with the input when a consumer id is passed', () => {
83
+ render(<Switch label="Toggle" name="toggle" id="custom-switch-id" />);
84
+ expect(screen.getByLabelText('Toggle')).toBeInTheDocument();
85
+ });
86
+
87
+ it('keeps role="switch" even when a consumer role is passed', () => {
88
+ render(<Switch label="Toggle" name="toggle" role="checkbox" />);
89
+ expect(screen.getByRole('switch')).toBeInTheDocument();
90
+ });
71
91
  });
@@ -36,13 +36,14 @@ export function Switch({
36
36
  {prefix && <span>{prefix}</span>}
37
37
  <div className={css.trackWrapper}>
38
38
  <input
39
+ {...props}
39
40
  type="checkbox"
40
41
  role="switch"
41
42
  id={id}
42
43
  name={name}
43
44
  aria-describedby={describedBy}
45
+ aria-invalid={!!error}
44
46
  className={cn(css.switch, error ? css.switchError : undefined)}
45
- {...props}
46
47
  />
47
48
  <span className={css.track} aria-hidden="true">
48
49
  <span className={css.thumb} />
@@ -47,6 +47,11 @@ Multi-line text input with label, hint, and error support.
47
47
  <tr><td>`--textarea_border`</td><td>`none`</td><td>Border</td></tr>
48
48
  <tr><td>`--textarea_radius`</td><td>`var(--bdc-outline_radius--l)` (1.5em)</td><td>Corner radius</td></tr>
49
49
  <tr><td>`--textarea_shadow`</td><td>`var(--bdc-outline_shadow)`</td><td>Box shadow</td></tr>
50
+ <tr><td>`--textarea_padding`</td><td>`var(--bds-space_s)`</td><td>Inner padding</td></tr>
51
+ <tr><td>`--textarea_font-family`</td><td>`var(--bds-font_family--body)`</td><td>Font family</td></tr>
52
+ <tr><td>`--textarea_font-size`</td><td>`var(--bds-font_size--body)`</td><td>Font size</td></tr>
53
+ <tr><td>`--textarea_line-height`</td><td>`var(--bds-font_line-height--body)`</td><td>Line height</td></tr>
54
+ <tr><td>`--textarea_min-block-size`</td><td>`calc(var(--bds-space_m) * 5)`</td><td>Minimum height</td></tr>
50
55
  </tbody>
51
56
  </table>
52
57
 
@@ -5,10 +5,10 @@
5
5
  }
6
6
 
7
7
  .textarea {
8
- font-family: var(--bds-font_family--body);
9
- font-size: var(--bds-font_size--body);
10
- line-height: var(--bds-font_line-height--body);
11
- padding: var(--bds-space_s);
8
+ font-family: var(--textarea_font-family, var(--bds-font_family--body));
9
+ font-size: var(--textarea_font-size, var(--bds-font_size--body));
10
+ line-height: var(--textarea_line-height, var(--bds-font_line-height--body));
11
+ padding: var(--textarea_padding, var(--bds-space_s));
12
12
  border: var(--textarea_border, none);
13
13
  --bdc_color: currentcolor;
14
14
  --bdc-outline_radius: var(--bdc-outline_radius--l);
@@ -18,7 +18,7 @@
18
18
  background-color: var(--textarea_color_bg, var(--bds-color_bg));
19
19
  color: var(--textarea_color, var(--bds-color_on-bg));
20
20
  resize: vertical;
21
- min-block-size: calc(var(--bds-space_m) * 5);
21
+ min-block-size: var(--textarea_min-block-size, calc(var(--bds-space_m) * 5));
22
22
  transition: --bdc_color var(--bds-animation_transition-duration) var(--bds-animation_easing),
23
23
  background-color var(--bds-animation_transition-duration) var(--bds-animation_easing);
24
24
  }
@@ -50,4 +50,17 @@ describe('Textarea', () => {
50
50
  render(<Textarea label="Message" name="message" rows={6} />);
51
51
  expect(screen.getByRole('textbox')).toHaveAttribute('rows', '6');
52
52
  });
53
+
54
+ it('keeps the label and message wired to a consumer-provided id', () => {
55
+ render(
56
+ <Textarea label="Message" name="message" id="custom-id" hint="Max 500 characters" error="Required" />
57
+ );
58
+ const textarea = screen.getByLabelText('Message');
59
+ expect(textarea).toHaveAttribute('id', 'custom-id');
60
+ const describedBy = textarea.getAttribute('aria-describedby');
61
+ expect(describedBy).toBeTruthy();
62
+ describedBy
63
+ ?.split(' ')
64
+ .forEach((describedById) => expect(describedById.startsWith('custom-id')).toBe(true));
65
+ });
53
66
  });
@@ -20,9 +20,11 @@ export function Textarea({
20
20
  hint,
21
21
  className,
22
22
  required,
23
+ id: idProp,
23
24
  ...props
24
25
  }: Readonly<TextareaProps>) {
25
- const id = name + useId();
26
+ const generatedId = useId();
27
+ const id = idProp ?? name + generatedId;
26
28
  const hintId = id + 'hint';
27
29
  const errorId = id + 'error';
28
30
  const describedBy = [error && errorId, hint && hintId].filter(Boolean).join(' ') || undefined;
@@ -2,7 +2,7 @@
2
2
  .error,
3
3
  .hint {
4
4
  font-size: var(--bds-font_size--body--s);
5
- margin-inline-start: var(--labelPosition);
5
+ margin-inline-start: var(--labelPosition, 0);
6
6
  }
7
7
 
8
8
  .error {
@@ -0,0 +1,29 @@
1
+ import { render, screen } from '@testing-library/react';
2
+ import { Message } from './Message';
3
+
4
+ describe('Message', () => {
5
+ it('renders nothing when message is undefined', () => {
6
+ const { container } = render(<Message inputId="field-1" type="hint" message={undefined} />);
7
+ expect(container).toBeEmptyDOMElement();
8
+ });
9
+
10
+ it('renders the message text', () => {
11
+ render(<Message inputId="field-1" type="hint" message="At least 8 characters." />);
12
+ expect(screen.getByText('At least 8 characters.')).toBeInTheDocument();
13
+ });
14
+
15
+ it('exposes an error message via role=alert so it is announced to assistive tech', () => {
16
+ render(<Message inputId="field-1" type="error" message="This field is required." />);
17
+ expect(screen.getByRole('alert')).toHaveTextContent('This field is required.');
18
+ });
19
+
20
+ it('does not expose a hint message as an alert', () => {
21
+ render(<Message inputId="field-1" type="hint" message="Optional hint." />);
22
+ expect(screen.queryByRole('alert')).not.toBeInTheDocument();
23
+ });
24
+
25
+ it('sets the message id to inputId concatenated with type', () => {
26
+ render(<Message inputId="field-1" type="error" message="Required" />);
27
+ expect(screen.getByRole('alert')).toHaveAttribute('id', 'field-1error');
28
+ });
29
+ });
@@ -12,7 +12,7 @@ export const Message = ({ message, type, inputId, className }: MessageProps) =>
12
12
  if (!message) return null;
13
13
 
14
14
  return (
15
- <p id={inputId + type} className={cn(css[type], className)}>
15
+ <p id={inputId + type} role={type === 'error' ? 'alert' : undefined} className={cn(css[type], className)}>
16
16
  {message}
17
17
  </p>
18
18
  );
@@ -45,6 +45,17 @@ Layout wrapper that arranges `Button` children according to a contextual variant
45
45
 
46
46
  <ArgTypes of={Stories} />
47
47
 
48
+ ## CSS variables
49
+
50
+ <table>
51
+ <thead>
52
+ <tr><th>Variable</th><th>Default</th><th>Description</th></tr>
53
+ </thead>
54
+ <tbody>
55
+ <tr><td>`--buttonGroup_gap`</td><td>`var(--bds-space_l)`</td><td>Gap between buttons.</td></tr>
56
+ </tbody>
57
+ </table>
58
+
48
59
  ## Accessibility
49
60
 
50
61
  - Renders as `<div role="group">` — no additional ARIA needed for the wrapper
@@ -10,7 +10,7 @@
10
10
  position: relative;
11
11
  display: flex;
12
12
  flex-direction: column-reverse;
13
- gap: var(--bds-space_l);
13
+ gap: var(--buttonGroup_gap, var(--bds-space_l));
14
14
  align-items: center;
15
15
  }
16
16
 
@@ -51,10 +51,6 @@
51
51
  justify-content: flex-start;
52
52
  align-items: center;
53
53
  }
54
-
55
- .buttonGroup.--variant_grid .container {
56
- justify-content: center;
57
- }
58
54
  }
59
55
  }
60
56
  }
@@ -20,6 +20,20 @@ const TwoButtons = () => (
20
20
  </>
21
21
  );
22
22
 
23
+ const ThreeButtons = () => (
24
+ <>
25
+ <Button variant="outline">Back</Button>
26
+ <Button variant="outline">Save draft</Button>
27
+ <Button variant="default">Publish</Button>
28
+ </>
29
+ );
30
+
31
+ /** Two actions — the common Cancel / Confirm row. */
32
+ export const TwoButtonsExample: Story = { render: () => <ButtonContainer variant="modal"><TwoButtons /></ButtonContainer> };
33
+
34
+ /** Three actions. */
35
+ export const ThreeButtonsExample: Story = { render: () => <ButtonContainer variant="content"><ThreeButtons /></ButtonContainer> };
36
+
23
37
  export const Default: Story = { render: () => <ButtonContainer><TwoButtons /></ButtonContainer> };
24
38
  export const Flow: Story = { render: () => <ButtonContainer variant="flow"><TwoButtons /></ButtonContainer> };
25
39
  export const Card: Story = { render: () => <ButtonContainer variant="card"><TwoButtons /></ButtonContainer> };
@@ -54,6 +54,9 @@ Contained surface for grouping related content. Three visual variants provide di
54
54
  <tr><td>`--card_on-color`</td><td>`var(--bds-color_on-bg)`</td><td>Card text colour.</td></tr>
55
55
  <tr><td>`--card_padding`</td><td>varies by `padding` prop</td><td>Card padding (overrides the prop default).</td></tr>
56
56
  <tr><td>`--card_border`</td><td>`none`</td><td>Border (outlined variant).</td></tr>
57
+ <tr><td>`--card_radius`</td><td>`var(--bds-border_radius--m)`</td><td>Card corner radius.</td></tr>
58
+ <tr><td>`--card_transition`</td><td>`var(--bds-animation_transition)`</td><td>Transition applied to colour/shadow/transform changes.</td></tr>
59
+ <tr><td>`--card_shadow--active`</td><td>`var(--bds-shadow_s)`</td><td>Box-shadow while a clickable card is pressed (`:active`).</td></tr>
57
60
  </tbody>
58
61
  </table>
59
62
 
@@ -76,6 +79,8 @@ Plus `--card_shadow--clickable-hover` (`var(--bds-shadow_xl)`) for hover on any
76
79
  ## Accessibility
77
80
 
78
81
  - Static card renders as `<div>` — no interactive role
79
- - Clickable card renders as `<button>` — keyboard and screen reader accessible
82
+ - Clickable card renders as `<button>` — keyboard and screen reader accessible, with browser UA button styling (font, alignment, border, width) reset to match a non-interactive card
83
+ - Focus-visible ring on a clickable card uses `--bds-outline_default` / `--bds-outline_offset` (the same focus treatment as every other interactive component)
84
+ - The hover lift and colour/shadow transitions respect `prefers-reduced-motion` — both are disabled when the user has opted out
80
85
  - When using `as="a"`, provide a valid `href`; when using a router `Link`, ensure it forwards `className` and `children`
81
86
  - Ensure clickable cards have a meaningful accessible name (via visible text content)
@@ -2,11 +2,21 @@
2
2
  .card {
3
3
  background-color: var(--card_color, var(--bds-color_bg));
4
4
  color: var(--card_on-color, var(--bds-color_on-bg));
5
- border-radius: var(--bds-border_radius--m);
6
- transition: all 0.3s ease;
5
+ border-radius: var(--card_radius, var(--bds-border_radius--m));
6
+ transition: var(--card_transition, var(--bds-animation_transition));
7
7
  position: relative;
8
8
  }
9
9
 
10
+ /* Clickable cards render as <button> — normalize UA button styles so it
11
+ looks and lays out identically to a non-interactive card. */
12
+ .card:is(button) {
13
+ border: none;
14
+ font: inherit;
15
+ text-align: inherit;
16
+ display: block;
17
+ inline-size: 100%;
18
+ }
19
+
10
20
  /* Resting shadows — consumers can override per-variant via
11
21
  --card_shadow--default / --card_shadow--elevated / --card_shadow--outlined. */
12
22
  .card.--default {
@@ -61,13 +71,13 @@
61
71
  }
62
72
 
63
73
  .card.--clickable:focus-visible {
64
- outline: 2px solid var(--color_focus, currentcolor);
65
- outline-offset: 2px;
74
+ outline: var(--bds-outline_default);
75
+ outline-offset: var(--bds-outline_offset);
66
76
  }
67
77
 
68
78
  .card.--clickable:active {
69
79
  transform: translateY(0);
70
- box-shadow: var(--bds-shadow_s);
80
+ box-shadow: var(--card_shadow--active, var(--bds-shadow_s));
71
81
  }
72
82
 
73
83
  @media (hover: hover) and (pointer: fine) {
@@ -88,4 +98,15 @@
88
98
  box-shadow: var(--card_shadow--outlined-hover, var(--bds-shadow_s));
89
99
  }
90
100
  }
101
+
102
+ @media (prefers-reduced-motion: reduce) {
103
+ .card {
104
+ transition: none;
105
+ }
106
+
107
+ .card.--clickable:hover,
108
+ .card.--clickable:active {
109
+ transform: none;
110
+ }
111
+ }
91
112
  }
@@ -18,6 +18,13 @@ describe('Card', () => {
18
18
  expect(screen.getByRole('button')).toBeInTheDocument();
19
19
  });
20
20
 
21
+ it('keeps the card class on the button so UA button styles are normalized', () => {
22
+ render(<Card onClick={() => {}}>Clickable</Card>);
23
+ // The `.card:is(button)` rule (font/text-align/display/border reset) only
24
+ // applies if the rendered <button> still carries the base `card` class.
25
+ expect(screen.getByRole('button')).toHaveClass('card');
26
+ });
27
+
21
28
  it('calls onClick when clicked', async () => {
22
29
  const user = userEvent.setup();
23
30
  const onClick = vi.fn();
@@ -3,14 +3,15 @@ import css from './Card.module.css';
3
3
  import { cn } from '@boostdev/design-system-foundation';
4
4
  import type { WithClassName } from '../../../types';
5
5
 
6
- type CardOwnProps = WithClassName & {
6
+ type CardOwnProps<C extends ElementType> = WithClassName & {
7
7
  variant?: 'default' | 'elevated' | 'outlined';
8
8
  padding?: 'none' | 'small' | 'medium' | 'large' | 'extra-large';
9
9
  textAlign?: 'start' | 'center' | 'end';
10
- as?: ElementType;
10
+ as?: C;
11
11
  };
12
12
 
13
- type CardProps<C extends ElementType = 'div'> = CardOwnProps & Omit<ComponentPropsWithoutRef<C>, keyof CardOwnProps>;
13
+ type CardProps<C extends ElementType = 'div'> = CardOwnProps<C> &
14
+ Omit<ComponentPropsWithoutRef<C>, keyof CardOwnProps<C>>;
14
15
 
15
16
  export function Card<C extends ElementType = 'div'>({
16
17
  children,
@@ -402,6 +402,50 @@ describe('applyMasonryLayout', () => {
402
402
  expect(a.style.gridColumn).toBe('var(--bds-grid_span-100)');
403
403
  });
404
404
 
405
+ it('accounts for a row wrap when an explicit-span item does not fit the remaining columns', () => {
406
+ // Regression: the demotion cursor advanced by `col + consumed` even when
407
+ // `consumed` overflowed the remaining row space. CSS Grid's `dense`
408
+ // auto-placement actually wraps a too-wide explicit item to the start of
409
+ // the next row, so the cursor must jump to `consumed`, not `col + consumed`.
410
+ const container = makeContainer(10);
411
+ container.style.gridTemplateColumns = '100px 100px 100px 100px';
412
+ const a = makeAutoItem(50);
413
+ const explicit = makeItem(50);
414
+ explicit.style.gridColumn = 'span 3';
415
+ const b = makeAutoItem(50);
416
+ container.append(a, explicit, b);
417
+ // 'half' in a 4-col grid → 2 cols (fraction fallback).
418
+ applyMasonryLayout(container, [a, explicit, b], { preferredColumnSpan: 'half' });
419
+ expect(a.style.gridColumn).toBe('span 2'); // cols 0-1, cursor -> 2
420
+ expect(explicit.style.gridColumn).toBe('span 3'); // doesn't fit remaining 2 cols -> wraps, cursor -> 3
421
+ expect(b.style.gridColumn).toBe('span 1'); // only 1 col remains in the wrapped row -> demoted
422
+ });
423
+
424
+ it('refreshes the restore snapshot when something else rewrites the item inline gridColumn between runs', () => {
425
+ // Regression: GridItem's `columnSpan="auto"` re-renders (e.g. once an
426
+ // image's aspect ratio resolves) overwrite the inline `gridColumn` the
427
+ // polyfill previously wrote. The polyfill only snapshotted the ORIGINAL
428
+ // value once, so it never picked up React's fresh value — unsetting
429
+ // `masonryPreferredColumnSpan` later restored the stale pre-resolve span.
430
+ const container = makeContainer(10);
431
+ container.style.gridTemplateColumns = '100px 100px 100px 100px';
432
+ const a = makeAutoItem(50);
433
+ a.style.gridColumn = 'span var(--bds-grid_columns-25)'; // placeholder before media resolves
434
+ container.append(a);
435
+
436
+ applyMasonryLayout(container, [a], { preferredColumnSpan: 'half' });
437
+ expect(a.style.gridColumn).toBe('span 2');
438
+
439
+ // Simulate React re-rendering GridItem after the image resolves, which
440
+ // overwrites the inline style the polyfill wrote.
441
+ a.style.gridColumn = 'span var(--bds-grid_columns-50)';
442
+ applyMasonryLayout(container, [a], { preferredColumnSpan: 'half' });
443
+ expect(a.style.gridColumn).toBe('span 2'); // preferred span still wins while set
444
+
445
+ applyMasonryLayout(container, [a]); // preferredColumnSpan dropped
446
+ expect(a.style.gridColumn).toBe('span var(--bds-grid_columns-50)'); // restores the fresh value, not the stale placeholder
447
+ });
448
+
405
449
  it('clearMasonryLayout restores gridColumn on data-column-span-auto items', () => {
406
450
  const container = makeContainer(10);
407
451
  container.style.gridTemplateColumns = '100px 100px 100px 100px';
@@ -34,7 +34,7 @@ export function getGridContext(): Context<GridContextValue> {
34
34
  return _GridContext;
35
35
  }
36
36
 
37
- type GridOwnProps = WithClassName & {
37
+ type GridOwnProps<C extends ElementType> = WithClassName & {
38
38
  variant?: GridVariant;
39
39
  columns?: number;
40
40
  isCentered?: boolean;
@@ -68,11 +68,11 @@ type GridOwnProps = WithClassName & {
68
68
  * you've confirmed the auto-tuner is wrong for your case.
69
69
  */
70
70
  masonryRowUnitPx?: number;
71
- as?: ElementType;
71
+ as?: C;
72
72
  };
73
73
 
74
- type GridProps<C extends ElementType = 'div'> = GridOwnProps &
75
- Omit<ComponentPropsWithoutRef<C>, keyof GridOwnProps>;
74
+ type GridProps<C extends ElementType = 'div'> = GridOwnProps<C> &
75
+ Omit<ComponentPropsWithoutRef<C>, keyof GridOwnProps<C>>;
76
76
 
77
77
  export function Grid<C extends ElementType = 'div'>({
78
78
  children,
@@ -113,7 +113,7 @@ export function Grid<C extends ElementType = 'div'>({
113
113
  const ctx = useMemo<GridContextValue>(() => ({ autoSpanMedia }), [autoSpanMedia]);
114
114
 
115
115
  return (
116
- <Component ref={ref} {...rest} className={classNames} style={composedStyle}>
116
+ <Component ref={ref as never} {...rest} className={classNames} style={composedStyle}>
117
117
  <GridContext.Provider value={ctx}>{children}</GridContext.Provider>
118
118
  </Component>
119
119
  );
@@ -3,7 +3,6 @@ import {
3
3
  ComponentPropsWithoutRef,
4
4
  CSSProperties,
5
5
  useContext,
6
- useLayoutEffect,
7
6
  useRef,
8
7
  useState,
9
8
  } from 'react';
@@ -18,6 +17,7 @@ import {
18
17
  readMediaAspect,
19
18
  type AutoSpanResult,
20
19
  } from './autoSpan';
20
+ import { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect';
21
21
 
22
22
  export type GridItemSpanValue =
23
23
  | 'full'
@@ -53,16 +53,16 @@ function resolveSpan(value: Exclude<GridItemSpanValue, 'auto'>): string {
53
53
  return SPAN_VAR[value];
54
54
  }
55
55
 
56
- type GridItemOwnProps = WithClassName & {
56
+ type GridItemOwnProps<C extends ElementType> = WithClassName & {
57
57
  columnSpan?: GridItemSpanValue;
58
58
  rowSpan?: number;
59
59
  startColumn?: number;
60
60
  endColumn?: number;
61
- as?: ElementType;
61
+ as?: C;
62
62
  };
63
63
 
64
- type GridItemProps<C extends ElementType = 'div'> = GridItemOwnProps &
65
- Omit<ComponentPropsWithoutRef<C>, keyof GridItemOwnProps>;
64
+ type GridItemProps<C extends ElementType = 'div'> = GridItemOwnProps<C> &
65
+ Omit<ComponentPropsWithoutRef<C>, keyof GridItemOwnProps<C>>;
66
66
 
67
67
  export function GridItem<C extends ElementType = 'div'>({
68
68
  children,
@@ -82,7 +82,7 @@ export function GridItem<C extends ElementType = 'div'>({
82
82
  const ref = useRef<HTMLElement | null>(null);
83
83
  const [autoSpan, setAutoSpan] = useState<AutoSpanResult>('one-quarter');
84
84
 
85
- useLayoutEffect(() => {
85
+ useIsomorphicLayoutEffect(() => {
86
86
  if (effectiveSpan !== 'auto') return;
87
87
  const el = ref.current;
88
88
  if (!el) return;
@@ -1,5 +1,6 @@
1
- import { RefObject, useLayoutEffect } from 'react';
1
+ import { RefObject } from 'react';
2
2
  import type { GridItemSpanValue } from './GridItem';
3
+ import { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect';
3
4
 
4
5
  type NamedSpan = Exclude<GridItemSpanValue, 'auto' | number>;
5
6
 
@@ -114,6 +115,17 @@ export type MasonryOptions = {
114
115
  // items pinned to their polyfill-assigned span.
115
116
  const ORIGINAL_COL_ATTR = 'data-bds-masonry-original-column';
116
117
 
118
+ // Data attribute caching the last `gridColumn` value the polyfill itself wrote
119
+ // for a preferred-span item. Used to detect drift: React re-renders a
120
+ // `data-column-span-auto` GridItem whenever its own computed span changes
121
+ // (e.g. `columnSpan="auto"` resolving after an image's aspect ratio loads),
122
+ // overwriting the inline `gridColumn` the polyfill previously set. Without
123
+ // this check, ORIGINAL_COL_ATTR would stay pinned to whatever value existed
124
+ // the very first time the polyfill ran (often a placeholder), so removing
125
+ // `masonryPreferredColumnSpan`/`isMasonry` later would restore that stale
126
+ // value instead of the item's real current span.
127
+ const LAST_COL_ATTR = 'data-bds-masonry-col';
128
+
117
129
  // Data attribute caching the last applied row-span. Used to short-circuit no-op
118
130
  // re-runs: when every child's newly-measured span matches the cached value, the
119
131
  // polyfill skips all writes. This prevents `grid-auto-flow: dense` from
@@ -190,17 +202,30 @@ export function applyMasonryLayout(
190
202
  let col = 0;
191
203
  for (const child of children) {
192
204
  if (child.hasAttribute('data-column-span-auto')) {
193
- if (!child.hasAttribute(ORIGINAL_COL_ATTR)) {
194
- child.setAttribute(ORIGINAL_COL_ATTR, child.style.gridColumn);
205
+ const currentInline = child.style.gridColumn;
206
+ const lastWritten = child.getAttribute(LAST_COL_ATTR);
207
+ // Refresh the snapshot on first sight, or when something other than
208
+ // the polyfill (i.e. React re-rendering the item) has since changed
209
+ // the inline value — otherwise we'd restore a stale span later.
210
+ if (!child.hasAttribute(ORIGINAL_COL_ATTR) || currentInline !== lastWritten) {
211
+ child.setAttribute(ORIGINAL_COL_ATTR, currentInline);
195
212
  }
196
213
  const remaining = totalCols - col;
197
214
  const span = Math.max(1, Math.min(preferredCols, remaining));
198
215
  child.style.gridColumn = `span ${span}`;
216
+ child.setAttribute(LAST_COL_ATTR, child.style.gridColumn);
199
217
  col = (col + span) % totalCols;
200
218
  } else {
201
219
  // Item has an explicit span — consume its columns for the demotion budget.
202
220
  const consumed = Math.min(totalCols, readExplicitSpan(child, totalCols));
203
- col = (col + consumed) % totalCols;
221
+ // A span that doesn't fit the remaining row wraps to a fresh row in
222
+ // the browser's auto-placement algorithm (dense packing places it at
223
+ // the start of the next row, not at `col + consumed`).
224
+ if (consumed > totalCols - col) {
225
+ col = consumed % totalCols;
226
+ } else {
227
+ col = (col + consumed) % totalCols;
228
+ }
204
229
  }
205
230
  }
206
231
  }
@@ -340,6 +365,7 @@ function restoreOriginalColumn(el: HTMLElement): void {
340
365
  if (!el.hasAttribute(ORIGINAL_COL_ATTR)) return;
341
366
  el.style.gridColumn = el.getAttribute(ORIGINAL_COL_ATTR) ?? '';
342
367
  el.removeAttribute(ORIGINAL_COL_ATTR);
368
+ el.removeAttribute(LAST_COL_ATTR);
343
369
  }
344
370
 
345
371
  /**
@@ -353,7 +379,7 @@ export function useMasonry(
353
379
  options: MasonryOptions = {},
354
380
  ): void {
355
381
  const { preferredColumnSpan, rowUnitPx } = options;
356
- useLayoutEffect(() => {
382
+ useIsomorphicLayoutEffect(() => {
357
383
  const container = ref.current;
358
384
  if (!container || !enabled) return;
359
385
  if (supportsNativeMasonry()) return;
@@ -0,0 +1,11 @@
1
+ import { useEffect, useLayoutEffect } from 'react';
2
+
3
+ /**
4
+ * `useLayoutEffect` that falls back to `useEffect` when there is no DOM
5
+ * (SSR / RSC). React 18 logs a warning ("useLayoutEffect does nothing on
6
+ * the server") whenever `useLayoutEffect` runs during a non-browser render —
7
+ * this avoids that warning while preserving the synchronous-before-paint
8
+ * timing `GridItem` and the masonry polyfill both depend on in the browser.
9
+ */
10
+ export const useIsomorphicLayoutEffect =
11
+ typeof window !== 'undefined' ? useLayoutEffect : useEffect;
@@ -28,11 +28,17 @@ Circular container that sizes to its own `font-size`. Use to give an SVG icon a
28
28
  <tr><th>Variable</th><th>Default</th><th>Description</th></tr>
29
29
  </thead>
30
30
  <tbody>
31
- <tr><td>`--icon-wrapper-color`</td><td>`var(--bds-color_bg)`</td><td>Background colour</td></tr>
32
- <tr><td>`--bds-on-icon-wrapper-color`</td><td>`var(--bds-color_on-bg)`</td><td>Icon colour</td></tr>
31
+ <tr><td>`--icon-wrapper_color`</td><td>`var(--bds-color_bg)`</td><td>Background colour</td></tr>
32
+ <tr><td>`--icon-wrapper_on-color`</td><td>`var(--bds-color_on-bg)`</td><td>Icon colour (text/fill)</td></tr>
33
+ <tr><td>`--icon-wrapper_radius`</td><td>`var(--bds-border_radius--circle)`</td><td>Corner radius</td></tr>
34
+ <tr><td>`--icon-wrapper_size`</td><td>`3em`</td><td>Font size — drives the icon's `1em`-based glyph size</td></tr>
35
+ <tr><td>`--icon-wrapper_margin-block-start`</td><td>`var(--bds-space_l)`</td><td>Space above the wrapper</td></tr>
36
+ <tr><td>`--icon-wrapper_margin-block-end`</td><td>`var(--bds-space_m)`</td><td>Space below the wrapper</td></tr>
33
37
  </tbody>
34
38
  </table>
35
39
 
40
+ > `--icon-wrapper-color` and `--icon-wrapper-radius` (hyphen-delimited) are deprecated aliases for `--icon-wrapper_color` and `--icon-wrapper_radius` — still supported, but new code should use the underscore-delimited names.
41
+
36
42
 
37
43
  ## Accessibility
38
44