@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,14 +4,16 @@ import '../index'; // auto-registers all custom elements
4
4
 
5
5
  function BdsTable({
6
6
  stickyHeader,
7
+ ariaLabel,
7
8
  children,
8
9
  }: {
9
10
  stickyHeader?: boolean;
11
+ ariaLabel?: string;
10
12
  children?: React.ReactNode;
11
13
  }) {
12
14
  return React.createElement(
13
15
  'bds-table',
14
- { 'sticky-header': stickyHeader || undefined },
16
+ { 'sticky-header': stickyHeader || undefined, 'aria-label': ariaLabel },
15
17
  children,
16
18
  );
17
19
  }
@@ -77,7 +79,11 @@ export const Default: Story = {
77
79
  export const StickyHeader: Story = {
78
80
  render: () => (
79
81
  <div style={{ padding: 24, maxHeight: 200, overflow: 'auto' }}>
80
- {React.createElement('bds-table', { 'sticky-header': true }, sampleTable())}
82
+ {React.createElement(
83
+ 'bds-table',
84
+ { 'sticky-header': true, 'aria-label': 'Team members' },
85
+ sampleTable(),
86
+ )}
81
87
  </div>
82
88
  ),
83
89
  };
@@ -52,7 +52,7 @@ import '@boostdev/design-system-components/web-components';
52
52
  | Attribute | Type | Default | Description |
53
53
  |-----------|------|---------|-------------|
54
54
  | `variant` | `"h1" \| "h2" \| "h3" \| "body" \| "body_s"` | `"body"` | Visual style and default semantic tag |
55
- | `component` | string | — | Override the rendered HTML tag (e.g. `"span"`, `"label"`) |
55
+ | `component` | string | — | Override the rendered HTML tag (e.g. `"span"`, `"label"`). Reflects to the host attribute, so it also works when set as a JS property (e.g. from React). |
56
56
 
57
57
  ## Slots
58
58
 
@@ -60,6 +60,17 @@ import '@boostdev/design-system-components/web-components';
60
60
  |------|-------------|
61
61
  | `(default)` | Text content |
62
62
 
63
+ ## CSS Custom Properties
64
+
65
+ | Property | Description |
66
+ |----------|-------------|
67
+ | `--typography_color` | Text colour (default: `--bds-color_on-bg`) |
68
+ | `--typography_font-size--h1` | Font size for the `h1` variant (default: `--bds-font_size--heading-1`) |
69
+ | `--typography_font-size--h2` | Font size for the `h2` variant (default: `--bds-font_size--heading-2`) |
70
+ | `--typography_font-size--h3` | Font size for the `h3` variant (default: `--bds-font_size--heading-3`) |
71
+ | `--typography_font-size--body` | Font size for the `body` variant (default: `--bds-font_size--body`) |
72
+ | `--typography_font-size--body_s` | Font size for the `body_s` variant (default: `--bds-font_size--body--s`) |
73
+
63
74
  ## Usage in plain HTML
64
75
 
65
76
  ```html
@@ -68,6 +79,11 @@ import '@boostdev/design-system-components/web-components';
68
79
  <bds-typography variant="body_s" component="span">Small helper text</bds-typography>
69
80
  ```
70
81
 
82
+ ## Layout
83
+
84
+ - The host is `display: block` by default (headings and paragraphs are block-level elements).
85
+ - `component="span"` switches the host to `display: inline` so the element flows inline like a native `<span>`. Other inline tag overrides (e.g. `"label"`) still need host restyling if inline flow is required.
86
+
71
87
  ## Accessibility
72
88
 
73
89
  - Uses semantic heading elements (`h1`–`h3`) or `<p>` by default
@@ -51,7 +51,15 @@ describe('bds-alert', () => {
51
51
  cleanup(el);
52
52
  });
53
53
 
54
- it('renders title when title attribute is set', async () => {
54
+ it('renders heading when heading attribute is set', async () => {
55
+ const el = await fixture('<bds-alert heading="Heads up">Message</bds-alert>');
56
+ const strong = el.shadowRoot!.querySelector('strong.title');
57
+ expect(strong).not.toBeNull();
58
+ expect(strong!.textContent).toBe('Heads up');
59
+ cleanup(el);
60
+ });
61
+
62
+ it('renders heading text from the deprecated title attribute as a fallback', async () => {
55
63
  const el = await fixture('<bds-alert title="Heads up">Message</bds-alert>');
56
64
  const strong = el.shadowRoot!.querySelector('strong.title');
57
65
  expect(strong).not.toBeNull();
@@ -59,7 +67,14 @@ describe('bds-alert', () => {
59
67
  cleanup(el);
60
68
  });
61
69
 
62
- it('does not render title element when title is not set', async () => {
70
+ it('prefers heading over the deprecated title attribute when both are set', async () => {
71
+ const el = await fixture('<bds-alert heading="New" title="Old">Message</bds-alert>');
72
+ const strong = el.shadowRoot!.querySelector('strong.title');
73
+ expect(strong!.textContent).toBe('New');
74
+ cleanup(el);
75
+ });
76
+
77
+ it('does not render title element when neither heading nor title is set', async () => {
63
78
  const el = await fixture('<bds-alert>Message</bds-alert>');
64
79
  const strong = el.shadowRoot!.querySelector('strong.title');
65
80
  expect(strong).toBeNull();
@@ -7,7 +7,11 @@ export type AlertVariant = 'info' | 'success' | 'warning' | 'error';
7
7
  *
8
8
  * Attributes:
9
9
  * variant — "info" (default) | "success" | "warning" | "error"
10
- * title — optional heading above the body text
10
+ * heading — optional heading above the body text
11
+ * title — deprecated alias for `heading`. Collides with the global HTML
12
+ * `title` attribute, which triggers a native browser tooltip on
13
+ * hover — use `heading` instead. Kept working for backwards
14
+ * compatibility; will be removed in a later major.
11
15
  * dismissible — boolean; shows a dismiss button when present
12
16
  *
13
17
  * Slots:
@@ -22,7 +26,7 @@ export type AlertVariant = 'info' | 'success' | 'warning' | 'error';
22
26
  * role="status" + aria-live="polite" for info/success variants.
23
27
  *
24
28
  * @example
25
- * <bds-alert variant="success" title="Saved!">Your changes have been saved.</bds-alert>
29
+ * <bds-alert variant="success" heading="Saved!">Your changes have been saved.</bds-alert>
26
30
  *
27
31
  * <bds-alert variant="error" dismissible>
28
32
  * <svg slot="icon">…</svg>
@@ -31,6 +35,16 @@ export type AlertVariant = 'info' | 'success' | 'warning' | 'error';
31
35
  */
32
36
  export class BdsAlert extends LitElement {
33
37
  static styles = css`
38
+ /* Shadow DOM does not inherit the global box-sizing reset, so set it
39
+ here; otherwise elements with an explicit size + padding size as
40
+ content-box and layouts drift from the React (light-DOM) versions. */
41
+ :host,
42
+ *,
43
+ *::before,
44
+ *::after {
45
+ box-sizing: border-box;
46
+ }
47
+
34
48
  :host {
35
49
  display: block;
36
50
  }
@@ -119,8 +133,8 @@ export class BdsAlert extends LitElement {
119
133
  }
120
134
 
121
135
  .dismiss svg {
122
- width: 1rem;
123
- height: 1rem;
136
+ inline-size: 1rem;
137
+ block-size: 1rem;
124
138
  }
125
139
 
126
140
  .dismiss:focus-visible {
@@ -137,6 +151,7 @@ export class BdsAlert extends LitElement {
137
151
 
138
152
  static properties = {
139
153
  variant: { type: String, reflect: true },
154
+ heading: { type: String },
140
155
  title: { type: String },
141
156
  dismissible: { type: Boolean, reflect: true },
142
157
  _iconFilled: { state: true },
@@ -145,6 +160,12 @@ export class BdsAlert extends LitElement {
145
160
  // `declare` annotates the type without emitting a class field initializer
146
161
  // that would shadow Lit's reactive accessors on the prototype.
147
162
  declare variant: AlertVariant;
163
+ declare heading: string;
164
+ /**
165
+ * @deprecated Use `heading` instead. Sharing the name with the global HTML
166
+ * `title` attribute makes the browser show a native tooltip on hover.
167
+ * Still read as a fallback for the heading text when `heading` is unset.
168
+ */
148
169
  declare title: string;
149
170
  declare dismissible: boolean;
150
171
  declare private _iconFilled: boolean;
@@ -152,11 +173,16 @@ export class BdsAlert extends LitElement {
152
173
  constructor() {
153
174
  super();
154
175
  this.variant = 'info';
176
+ this.heading = '';
155
177
  this.title = '';
156
178
  this.dismissible = false;
157
179
  this._iconFilled = false;
158
180
  }
159
181
 
182
+ private get _headingText() {
183
+ return this.heading || this.title;
184
+ }
185
+
160
186
  private _onIconSlotChange(e: Event) {
161
187
  const slot = e.target as HTMLSlotElement;
162
188
  this._iconFilled = slot.assignedNodes({ flatten: true }).length > 0;
@@ -182,7 +208,7 @@ export class BdsAlert extends LitElement {
182
208
  <slot name="icon" @slotchange=${this._onIconSlotChange}></slot>
183
209
  </span>
184
210
  <div class="content">
185
- ${this.title ? html`<strong class="title">${this.title}</strong>` : nothing}
211
+ ${this._headingText ? html`<strong class="title">${this._headingText}</strong>` : nothing}
186
212
  <div><slot></slot></div>
187
213
  </div>
188
214
  ${this.dismissible
@@ -72,4 +72,33 @@ describe('bds-avatar', () => {
72
72
  expect(el.getAttribute('size')).toBe('large');
73
73
  cleanup(el);
74
74
  });
75
+
76
+ it('preserves an explicit empty alt="" as decorative (does not fall back to name)', async () => {
77
+ const el = await fixture('<bds-avatar src="/photo.jpg" alt="" name="Jane Doe"></bds-avatar>');
78
+ const img = el.shadowRoot!.querySelector('img');
79
+ expect(img!.getAttribute('alt')).toBe('');
80
+ cleanup(el);
81
+ });
82
+
83
+ it('falls back to name when alt attribute is entirely absent', async () => {
84
+ const el = await fixture('<bds-avatar src="/photo.jpg" name="Jane Doe"></bds-avatar>');
85
+ const img = el.shadowRoot!.querySelector('img');
86
+ expect(img!.hasAttribute('alt')).toBe(true);
87
+ expect(img!.getAttribute('alt')).toBe('Jane Doe');
88
+ cleanup(el);
89
+ });
90
+
91
+ it('size selectors write to the --avatar_size--variant slot, not the public --avatar_size token (ancestor overrides stay effective)', () => {
92
+ const cssText = BdsAvatar.styles.cssText;
93
+ expect(cssText).toMatch(
94
+ /inline-size:\s*var\(--avatar_size,\s*var\(--avatar_size--variant,\s*3em\)\)/,
95
+ );
96
+ expect(cssText).toMatch(
97
+ /block-size:\s*var\(--avatar_size,\s*var\(--avatar_size--variant,\s*3em\)\)/,
98
+ );
99
+ expect(cssText).toMatch(/:host\(\[size='small'\]\)\s*\{\s*--avatar_size--variant:\s*2em;/);
100
+ expect(cssText).toMatch(/:host\(\[size='large'\]\)\s*\{\s*--avatar_size--variant:\s*4\.5em;/);
101
+ // The public --avatar_size token itself must never be set directly by a size selector.
102
+ expect(cssText).not.toMatch(/:host\(\[size=[^)]*\]\)\s*\{\s*--avatar_size:/);
103
+ });
75
104
  });
@@ -7,7 +7,8 @@ import { LitElement, css, html, nothing } from 'lit';
7
7
  *
8
8
  * Attributes:
9
9
  * src — image URL
10
- * alt — image alt text (defaults to `name` or "User avatar")
10
+ * alt — image alt text (defaults to `name` or "User avatar"). Set alt=""
11
+ * explicitly to mark the image as decorative (silences the accessible name).
11
12
  * name — full name; used to compute initials and as fallback aria-label
12
13
  * size — "small" | "medium" (default) | "large"
13
14
  *
@@ -17,20 +18,34 @@ import { LitElement, css, html, nothing } from 'lit';
17
18
  */
18
19
  export class BdsAvatar extends LitElement {
19
20
  static styles = css`
21
+ /* Shadow DOM does not inherit the global box-sizing reset, so set it
22
+ here; otherwise elements with an explicit size + padding size as
23
+ content-box and layouts drift from the React (light-DOM) versions. */
24
+ :host,
25
+ *,
26
+ *::before,
27
+ *::after {
28
+ box-sizing: border-box;
29
+ }
30
+
20
31
  :host {
21
32
  display: inline-flex;
22
33
  align-items: center;
23
34
  justify-content: center;
24
- inline-size: var(--avatar_size, 3em);
25
- block-size: var(--avatar_size, 3em);
26
- border-radius: 50%;
35
+ /* Layered cascade (mirrors the React Avatar): a public --avatar_size
36
+ override wins over the per-size-variant default. Size selectors
37
+ below write --avatar_size--variant only, so an ancestor setting
38
+ --avatar_size still cascades correctly. */
39
+ inline-size: var(--avatar_size, var(--avatar_size--variant, 3em));
40
+ block-size: var(--avatar_size, var(--avatar_size--variant, 3em));
41
+ border-radius: var(--avatar_radius, var(--bds-border_radius--circle));
27
42
  overflow: hidden;
28
43
  flex-shrink: 0;
29
44
  }
30
45
 
31
- :host([size='small']) { --avatar_size: 2em; }
32
- :host([size='medium']) { --avatar_size: 3em; }
33
- :host([size='large']) { --avatar_size: 4.5em; }
46
+ :host([size='small']) { --avatar_size--variant: 2em; }
47
+ :host([size='medium']) { --avatar_size--variant: 3em; }
48
+ :host([size='large']) { --avatar_size--variant: 4.5em; }
34
49
 
35
50
  .fallback {
36
51
  display: inline-flex;
@@ -92,11 +107,14 @@ export class BdsAvatar extends LitElement {
92
107
 
93
108
  render() {
94
109
  if (this.src) {
95
- return html`<img
96
- class="image"
97
- src=${this.src}
98
- alt=${this.alt || this.name || 'User avatar'}
99
- />`;
110
+ // An explicit alt="" attribute marks the image as decorative and must
111
+ // be preserved as-is — only substitute name/"User avatar" when the
112
+ // attribute was never provided (this.alt otherwise defaults to '').
113
+ const altText = this.hasAttribute('alt')
114
+ ? this.alt
115
+ : this.name || 'User avatar';
116
+
117
+ return html`<img class="image" src=${this.src} alt=${altText} />`;
100
118
  }
101
119
 
102
120
  return html`
@@ -48,4 +48,9 @@ describe('bds-badge', () => {
48
48
  cleanup(el);
49
49
  }
50
50
  });
51
+
52
+ it('falls back --badge_radius to the pill token, matching the React counterpart', () => {
53
+ const cssText = BdsBadge.styles.cssText;
54
+ expect(cssText).toMatch(/border-radius:\s*var\(--badge_radius,\s*var\(--bds-border_radius--full\)\)/);
55
+ });
51
56
  });
@@ -16,6 +16,16 @@ export type BadgeVariant = 'primary' | 'secondary' | 'success' | 'error' | 'warn
16
16
  */
17
17
  export class BdsBadge extends LitElement {
18
18
  static styles = css`
19
+ /* Shadow DOM does not inherit the global box-sizing reset, so set it
20
+ here; otherwise elements with an explicit size + padding size as
21
+ content-box and layouts drift from the React (light-DOM) versions. */
22
+ :host,
23
+ *,
24
+ *::before,
25
+ *::after {
26
+ box-sizing: border-box;
27
+ }
28
+
19
29
  :host {
20
30
  display: inline-flex;
21
31
  }
@@ -25,7 +35,7 @@ export class BdsBadge extends LitElement {
25
35
  align-items: center;
26
36
  justify-content: center;
27
37
  padding: var(--bds-space_xxs) var(--bds-space_xs);
28
- border-radius: var(--badge_radius, 2em);
38
+ border-radius: var(--badge_radius, var(--bds-border_radius--full));
29
39
  font-size: var(--badge_font-size, var(--bds-font_size--body--s));
30
40
  font-weight: var(--bds-font_weight--semibold);
31
41
  line-height: 1;
@@ -52,4 +52,34 @@ describe('bds-breadcrumb', () => {
52
52
  expect(separators.length).toBe(2); // between each pair
53
53
  cleanup(el);
54
54
  });
55
+
56
+ it('falls back to an empty list instead of crashing when items is null', async () => {
57
+ const el = await fixture('<bds-breadcrumb></bds-breadcrumb>') as BdsBreadcrumb;
58
+ // Simulates what Lit's default Array attribute converter produces for
59
+ // malformed JSON or a removed attribute: it returns null, not [].
60
+ (el as unknown as { items: unknown }).items = null;
61
+ await el.updateComplete;
62
+ const items = el.shadowRoot!.querySelectorAll('.item');
63
+ expect(items.length).toBe(0);
64
+ cleanup(el);
65
+ });
66
+
67
+ it('recovers from malformed items JSON set via the attribute', async () => {
68
+ const el = await fixture('<bds-breadcrumb items="not valid json"></bds-breadcrumb>') as BdsBreadcrumb;
69
+ const items = el.shadowRoot!.querySelectorAll('.item');
70
+ expect(items.length).toBe(0);
71
+ cleanup(el);
72
+ });
73
+
74
+ it('renders non-last items without href as non-interactive text, not a href="#" link', async () => {
75
+ const el = await fixture('<bds-breadcrumb></bds-breadcrumb>') as BdsBreadcrumb;
76
+ el.items = [{ label: 'Home' }, { label: 'Current' }];
77
+ await el.updateComplete;
78
+ const link = el.shadowRoot!.querySelector('a.link');
79
+ expect(link).toBeNull();
80
+ const text = el.shadowRoot!.querySelector('.text');
81
+ expect(text).not.toBeNull();
82
+ expect(text!.textContent).toBe('Home');
83
+ cleanup(el);
84
+ });
55
85
  });
@@ -10,13 +10,25 @@ export interface BreadcrumbItem {
10
10
  *
11
11
  * Attributes:
12
12
  * items — JSON string array of `{ label: string, href?: string }` objects.
13
- * The last item is treated as the current page (no link).
13
+ * The last item is treated as the current page (no link). Any other
14
+ * item without an `href` renders as plain text instead of a link.
15
+ * Malformed JSON (or a removed attribute) falls back to `[]`.
14
16
  *
15
17
  * @example
16
18
  * <bds-breadcrumb items='[{"label":"Home","href":"/"},{"label":"Products","href":"/products"},{"label":"Item"}]'></bds-breadcrumb>
17
19
  */
18
20
  export class BdsBreadcrumb extends LitElement {
19
21
  static styles = css`
22
+ /* Shadow DOM does not inherit the global box-sizing reset, so set it
23
+ here; otherwise elements with an explicit size + padding size as
24
+ content-box and layouts drift from the React (light-DOM) versions. */
25
+ :host,
26
+ *,
27
+ *::before,
28
+ *::after {
29
+ box-sizing: border-box;
30
+ }
31
+
20
32
  :host {
21
33
  display: block;
22
34
  }
@@ -65,6 +77,10 @@ export class BdsBreadcrumb extends LitElement {
65
77
  user-select: none;
66
78
  }
67
79
 
80
+ .text {
81
+ color: var(--bds-color_on-bg--subtle);
82
+ }
83
+
68
84
  .current {
69
85
  color: var(--bds-color_on-bg--subtle);
70
86
  font-weight: var(--bds-font_weight--semibold);
@@ -83,17 +99,23 @@ export class BdsBreadcrumb extends LitElement {
83
99
  }
84
100
 
85
101
  render() {
102
+ // this.items may be null: the Lit default Array/Object attribute
103
+ // converter returns null (rather than throwing) both for malformed
104
+ // JSON and for a removed attribute — fall back to an empty list.
105
+ const items = this.items ?? [];
86
106
  return html`
87
107
  <nav class="breadcrumb" aria-label="Breadcrumb">
88
108
  <ol class="list">
89
- ${this.items.map((item, index) => {
90
- const isLast = index === this.items.length - 1;
109
+ ${items.map((item, index) => {
110
+ const isLast = index === items.length - 1;
91
111
  return html`
92
112
  <li class="item">
93
113
  ${isLast
94
114
  ? html`<span class="current" aria-current="page">${item.label}</span>`
95
115
  : html`
96
- <a class="link" href=${item.href ?? '#'}>${item.label}</a>
116
+ ${item.href
117
+ ? html`<a class="link" href=${item.href}>${item.label}</a>`
118
+ : html`<span class="text">${item.label}</span>`}
97
119
  <span class="separator" aria-hidden="true">›</span>
98
120
  `}
99
121
  </li>
@@ -0,0 +1,39 @@
1
+ import { fixture, cleanup } from '../test/helpers';
2
+ import { BdsButtonContainer } from './bds-button-container';
3
+
4
+ describe('bds-button-container', () => {
5
+ it('is registered as a custom element', () => {
6
+ expect(customElements.get('bds-button-container')).toBe(BdsButtonContainer);
7
+ });
8
+
9
+ it('renders a group role element wrapping a slot', async () => {
10
+ const el = await fixture('<bds-button-container>content</bds-button-container>');
11
+ const group = el.shadowRoot!.querySelector('[role="group"]')!;
12
+ expect(group).not.toBeNull();
13
+ expect(group.querySelector('slot')).not.toBeNull();
14
+ cleanup(el);
15
+ });
16
+
17
+ it('reflects the variant attribute', async () => {
18
+ const el = await fixture(
19
+ '<bds-button-container variant="modal">content</bds-button-container>',
20
+ ) as BdsButtonContainer;
21
+ expect(el.variant).toBe('modal');
22
+ expect(el.getAttribute('variant')).toBe('modal');
23
+ cleanup(el);
24
+ });
25
+
26
+ it('forwards aria-label to the group', async () => {
27
+ const el = await fixture('<bds-button-container aria-label="Dialog actions">x</bds-button-container>');
28
+ const group = el.shadowRoot!.querySelector('[role="group"]')!;
29
+ expect(group.getAttribute('aria-label')).toBe('Dialog actions');
30
+ cleanup(el);
31
+ });
32
+
33
+ it('omits aria-label when unset', async () => {
34
+ const el = await fixture('<bds-button-container>x</bds-button-container>');
35
+ const group = el.shadowRoot!.querySelector('[role="group"]')!;
36
+ expect(group.hasAttribute('aria-label')).toBe(false);
37
+ cleanup(el);
38
+ });
39
+ });
@@ -0,0 +1,123 @@
1
+ import { LitElement, css, html, nothing } from 'lit';
2
+
3
+ export type ButtonContainerVariant = 'flow' | 'card' | 'modal' | 'content';
4
+
5
+ /**
6
+ * `<bds-button-container>` — responsive layout wrapper for a row of action
7
+ * buttons (Cancel / Confirm, Back / Next, …). Web-component port of the React
8
+ * `ButtonContainer`.
9
+ *
10
+ * Buttons stack vertically (primary on top via `column-reverse`) on narrow
11
+ * containers and lay out in a row once the container is at least 30rem wide.
12
+ * The `variant` controls alignment:
13
+ * - `flow` — multi-step navigation (Back / Next); single child pushed to the end
14
+ * - `card` — single-form submit; centered / full-width
15
+ * - `modal` — dialog actions; aligned to the end
16
+ * - `content` — inline content actions; aligned to the start
17
+ *
18
+ * Attributes:
19
+ * variant — `"flow"` | `"card"` | `"modal"` | `"content"`
20
+ * aria-label — accessible label for the group
21
+ *
22
+ * Slots:
23
+ * (default) — `<bds-button>` elements
24
+ *
25
+ * @example
26
+ * <bds-button-container variant="modal" aria-label="Dialog actions">
27
+ * <bds-button variant="outline">Cancel</bds-button>
28
+ * <bds-button>Confirm</bds-button>
29
+ * </bds-button-container>
30
+ */
31
+ export class BdsButtonContainer extends LitElement {
32
+ static styles = css`
33
+ /* Shadow DOM does not inherit the global box-sizing reset, so set it
34
+ here; otherwise elements with an explicit size + padding size as
35
+ content-box and layouts drift from the React (light-DOM) versions. */
36
+ :host,
37
+ *,
38
+ *::before,
39
+ *::after {
40
+ box-sizing: border-box;
41
+ }
42
+
43
+ :host {
44
+ display: block;
45
+ inline-size: 100%;
46
+ /* Span the full row when placed inside a bds-grid. */
47
+ grid-column: var(--bds-grid_span-100, 1 / -1);
48
+ container-type: inline-size;
49
+ container-name: button-container;
50
+ }
51
+
52
+ .container {
53
+ position: relative;
54
+ display: flex;
55
+ flex-direction: column-reverse;
56
+ gap: var(--buttonGroup_gap, var(--bds-space_l));
57
+ align-items: center;
58
+ }
59
+
60
+ :host([variant='card']) .container {
61
+ align-items: stretch;
62
+ }
63
+
64
+ :host([variant='flow']) .container,
65
+ :host([variant='modal']) .container {
66
+ align-items: center;
67
+ }
68
+
69
+ :host([variant='content']) .container {
70
+ align-items: flex-start;
71
+ }
72
+
73
+ @container button-container (min-width: 30rem) {
74
+ .container {
75
+ flex-direction: row;
76
+ justify-content: space-between;
77
+ }
78
+
79
+ /* A lone button in flow/modal is pushed to the end. */
80
+ :host([variant='modal']) ::slotted(:only-child),
81
+ :host([variant='flow']) ::slotted(:only-child) {
82
+ margin-inline-start: auto;
83
+ }
84
+
85
+ :host([variant='card']) .container {
86
+ justify-content: center;
87
+ }
88
+
89
+ :host([variant='modal']) .container {
90
+ justify-content: flex-end;
91
+ }
92
+
93
+ :host([variant='content']) .container {
94
+ justify-content: flex-start;
95
+ align-items: center;
96
+ }
97
+ }
98
+ `;
99
+
100
+ static properties = {
101
+ variant: { type: String, reflect: true },
102
+ 'aria-label': { type: String },
103
+ };
104
+
105
+ declare variant: ButtonContainerVariant | undefined;
106
+ declare ['aria-label']: string | undefined;
107
+
108
+ render() {
109
+ return html`
110
+ <div class="container" role="group" aria-label=${this['aria-label'] ?? nothing}>
111
+ <slot></slot>
112
+ </div>
113
+ `;
114
+ }
115
+ }
116
+
117
+ customElements.define('bds-button-container', BdsButtonContainer);
118
+
119
+ declare global {
120
+ interface HTMLElementTagNameMap {
121
+ 'bds-button-container': BdsButtonContainer;
122
+ }
123
+ }
@@ -1,40 +1,34 @@
1
1
  import { fixture, cleanup } from '../test/helpers';
2
2
  import { BdsButtonGroup } from './bds-button-group';
3
+ import { BdsButtonContainer } from './bds-button-container';
3
4
 
4
- describe('bds-button-group', () => {
5
+ describe('bds-button-group (deprecated alias of bds-button-container)', () => {
5
6
  it('is registered as a custom element', () => {
6
7
  expect(customElements.get('bds-button-group')).toBe(BdsButtonGroup);
7
8
  });
8
9
 
10
+ it('is a subclass of BdsButtonContainer and importing it registers the real element', () => {
11
+ expect(new BdsButtonGroup()).toBeInstanceOf(BdsButtonContainer);
12
+ expect(customElements.get('bds-button-container')).toBe(BdsButtonContainer);
13
+ });
14
+
9
15
  it('renders a group role element', async () => {
10
16
  const el = await fixture('<bds-button-group>content</bds-button-group>');
11
17
  expect(el.shadowRoot!.querySelector('[role="group"]')).not.toBeNull();
12
18
  cleanup(el);
13
19
  });
14
20
 
15
- it('defaults to horizontal orientation', async () => {
16
- const el = await fixture('<bds-button-group>content</bds-button-group>') as BdsButtonGroup;
17
- expect(el.orientation).toBe('horizontal');
18
- cleanup(el);
19
- });
20
-
21
- it('reflects vertical orientation attribute', async () => {
22
- const el = await fixture('<bds-button-group orientation="vertical">content</bds-button-group>') as BdsButtonGroup;
23
- expect(el.orientation).toBe('vertical');
24
- expect(el.getAttribute('orientation')).toBe('vertical');
25
- cleanup(el);
26
- });
27
-
28
- it('renders a slot', async () => {
29
- const el = await fixture('<bds-button-group><span>item</span></bds-button-group>');
30
- expect(el.shadowRoot!.querySelector('slot')).not.toBeNull();
31
- cleanup(el);
32
- });
33
-
34
21
  it('sets aria-label on the group element', async () => {
35
22
  const el = await fixture('<bds-button-group aria-label="View options">content</bds-button-group>');
36
23
  const group = el.shadowRoot!.querySelector('[role="group"]')!;
37
24
  expect(group.getAttribute('aria-label')).toBe('View options');
38
25
  cleanup(el);
39
26
  });
27
+
28
+ it('omits the aria-label attribute entirely when unset, instead of rendering an empty string', async () => {
29
+ const el = await fixture('<bds-button-group>content</bds-button-group>');
30
+ const group = el.shadowRoot!.querySelector('[role="group"]')!;
31
+ expect(group.hasAttribute('aria-label')).toBe(false);
32
+ cleanup(el);
33
+ });
40
34
  });