@boostdev/design-system-components 2.8.0 → 2.12.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 +75 -46
  2. package/README.md +41 -20
  3. package/dist/client.cjs +1317 -779
  4. package/dist/client.css +1037 -820
  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 +1037 -820
  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-4A2YYTYN.js +93 -0
  17. package/dist/web-components/{chunk-Q4T5BJT6.js → chunk-62NK3ZSC.js} +18 -3
  18. package/dist/web-components/chunk-66M6ETWD.js +77 -0
  19. package/dist/web-components/{chunk-NCPQ7AF3.js → chunk-6G22I2CK.js} +18 -3
  20. package/dist/web-components/{chunk-QDST57JC.js → chunk-7ZOJ7N4E.js} +14 -4
  21. package/dist/web-components/{chunk-QLT6MTZF.js → chunk-AIBOHNDU.js} +10 -0
  22. package/dist/web-components/{chunk-X3NQMBAQ.js → chunk-AP4RDUL2.js} +14 -3
  23. package/dist/web-components/{chunk-QWPACK5L.js → chunk-BPYKZVDK.js} +11 -1
  24. package/dist/web-components/chunk-CUKQ2L5B.js +245 -0
  25. package/dist/web-components/chunk-DIZDCL7Z.js +14 -0
  26. package/dist/web-components/{chunk-2QA62WCQ.js → chunk-EF7IVYTY.js} +10 -0
  27. package/dist/web-components/{chunk-L3XHOMN6.js → chunk-F3ZDNHZZ.js} +26 -1
  28. package/dist/web-components/chunk-FEDABOR5.js +248 -0
  29. package/dist/web-components/{chunk-KUI55GFB.js → chunk-FUQEFHRC.js} +51 -19
  30. package/dist/web-components/{chunk-6I2DBFQ7.js → chunk-HGFCJXOQ.js} +36 -5
  31. package/dist/web-components/{chunk-YLVTEY23.js → chunk-HRD3NOA3.js} +53 -21
  32. package/dist/web-components/chunk-IDSM74LM.js +189 -0
  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-UUKSDCYS.js → chunk-J3HVUIUH.js} +87 -15
  36. package/dist/web-components/{chunk-ARMKC4BQ.js → chunk-JH6LQKLK.js} +77 -5
  37. package/dist/web-components/chunk-JMCXAAFK.js +120 -0
  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-2FGATTGT.js → chunk-NTQ4TCUT.js} +76 -55
  46. package/dist/web-components/chunk-OY74D4X6.js +302 -0
  47. package/dist/web-components/{chunk-3S42DZ7W.js → chunk-P24JYC5V.js} +7 -0
  48. package/dist/web-components/{chunk-TQ7IQ4GZ.js → chunk-PLWCDDP6.js} +72 -30
  49. package/dist/web-components/{chunk-BKIHQYJR.js → chunk-PXPPKCLT.js} +17 -2
  50. package/dist/web-components/{chunk-PC3IOQAH.js → chunk-QKWXCBTH.js} +28 -8
  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-VANAKB6D.js +152 -0
  59. package/dist/web-components/{chunk-PXZWYO6Z.js → chunk-VED2DFJ6.js} +108 -29
  60. package/dist/web-components/chunk-W6H5ID2U.js +161 -0
  61. package/dist/web-components/{chunk-FSZRP43R.js → chunk-WFVKU4GX.js} +21 -10
  62. package/dist/web-components/{chunk-OQTRTMAB.js → chunk-WIBAN7KP.js} +10 -0
  63. package/dist/web-components/chunk-X7PS7GSN.js +424 -0
  64. package/dist/web-components/chunk-XI7KRAH7.js +54 -0
  65. package/dist/web-components/{chunk-ORC56MDY.js → chunk-XIZWAWMJ.js} +45 -6
  66. package/dist/web-components/{chunk-FXURM6D5.js → chunk-YFAXGRPR.js} +10 -0
  67. package/dist/web-components/{chunk-65JXQOBA.js → chunk-Z7XTADXX.js} +52 -8
  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 +24 -8
  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 +21 -1
  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 +35 -4
  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.module.css +1 -1
  186. package/src/components/interaction/DropdownMenu/DropdownMenu.spec.tsx +34 -0
  187. package/src/components/interaction/DropdownMenu/DropdownMenu.tsx +15 -5
  188. package/src/components/interaction/DropdownMenu/index.ts +1 -0
  189. package/src/components/interaction/Popover/Popover.mdx +6 -2
  190. package/src/components/interaction/Popover/Popover.module.css +27 -19
  191. package/src/components/interaction/Popover/Popover.spec.tsx +38 -0
  192. package/src/components/interaction/Popover/Popover.tsx +19 -5
  193. package/src/components/interaction/Popover/index.ts +1 -0
  194. package/src/components/interaction/Rating/Rating.mdx +1 -1
  195. package/src/components/interaction/Rating/Rating.module.css +2 -2
  196. package/src/components/interaction/Rating/Rating.tsx +1 -1
  197. package/src/components/interaction/Rating/index.ts +1 -0
  198. package/src/components/interaction/Toast/Toast.mdx +3 -0
  199. package/src/components/interaction/Toast/Toast.module.css +36 -6
  200. package/src/components/interaction/Toast/Toast.spec.tsx +69 -1
  201. package/src/components/interaction/Toast/Toast.tsx +15 -9
  202. package/src/components/interaction/form/Checkbox/Checkbox.mdx +3 -0
  203. package/src/components/interaction/form/Checkbox/Checkbox.module.css +13 -6
  204. package/src/components/interaction/form/Checkbox/Checkbox.spec.tsx +6 -0
  205. package/src/components/interaction/form/Checkbox/Checkbox.tsx +1 -1
  206. package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.mdx +16 -1
  207. package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.module.css +24 -8
  208. package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.spec.tsx +32 -2
  209. package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.tsx +14 -2
  210. package/src/components/interaction/form/Combobox/Combobox.mdx +11 -4
  211. package/src/components/interaction/form/Combobox/Combobox.module.css +6 -6
  212. package/src/components/interaction/form/Combobox/Combobox.spec.tsx +47 -0
  213. package/src/components/interaction/form/Combobox/Combobox.tsx +10 -5
  214. package/src/components/interaction/form/FieldGroup/FieldGroup.mdx +9 -10
  215. package/src/components/interaction/form/FieldGroup/FieldGroup.module.css +57 -23
  216. package/src/components/interaction/form/FieldGroup/FieldGroup.spec.tsx +129 -7
  217. package/src/components/interaction/form/FieldGroup/FieldGroup.tsx +72 -12
  218. package/src/components/interaction/form/FileInput/FileInput.mdx +9 -1
  219. package/src/components/interaction/form/FileInput/FileInput.module.css +8 -8
  220. package/src/components/interaction/form/FileInput/FileInput.spec.tsx +89 -1
  221. package/src/components/interaction/form/FileInput/FileInput.tsx +6 -2
  222. package/src/components/interaction/form/FormInput/FormInput.mdx +9 -5
  223. package/src/components/interaction/form/FormInput/FormInput.module.css +17 -8
  224. package/src/components/interaction/form/FormInput/FormInput.spec.tsx +20 -0
  225. package/src/components/interaction/form/FormInput/FormInput.tsx +7 -2
  226. package/src/components/interaction/form/NumberInput/NumberInput.mdx +5 -1
  227. package/src/components/interaction/form/NumberInput/NumberInput.module.css +6 -6
  228. package/src/components/interaction/form/NumberInput/NumberInput.spec.tsx +51 -0
  229. package/src/components/interaction/form/NumberInput/NumberInput.tsx +36 -8
  230. package/src/components/interaction/form/Radio/Radio.mdx +8 -1
  231. package/src/components/interaction/form/Radio/Radio.module.css +20 -7
  232. package/src/components/interaction/form/Radio/Radio.spec.tsx +15 -0
  233. package/src/components/interaction/form/Radio/Radio.tsx +10 -4
  234. package/src/components/interaction/form/RadioGroup/RadioGroup.mdx +16 -1
  235. package/src/components/interaction/form/RadioGroup/RadioGroup.module.css +24 -8
  236. package/src/components/interaction/form/RadioGroup/RadioGroup.spec.tsx +32 -2
  237. package/src/components/interaction/form/RadioGroup/RadioGroup.tsx +14 -2
  238. package/src/components/interaction/form/SegmentedControl/SegmentedControl.mdx +9 -3
  239. package/src/components/interaction/form/SegmentedControl/SegmentedControl.module.css +25 -12
  240. package/src/components/interaction/form/SegmentedControl/SegmentedControl.spec.tsx +86 -5
  241. package/src/components/interaction/form/SegmentedControl/SegmentedControl.tsx +44 -4
  242. package/src/components/interaction/form/Select/Select.mdx +10 -4
  243. package/src/components/interaction/form/Select/Select.module.css +4 -4
  244. package/src/components/interaction/form/Select/Select.spec.tsx +34 -0
  245. package/src/components/interaction/form/Select/Select.tsx +21 -9
  246. package/src/components/interaction/form/Slider/Slider.mdx +4 -1
  247. package/src/components/interaction/form/Slider/Slider.module.css +32 -8
  248. package/src/components/interaction/form/Slider/Slider.spec.tsx +29 -0
  249. package/src/components/interaction/form/Slider/Slider.tsx +9 -7
  250. package/src/components/interaction/form/Switch/Switch.mdx +2 -2
  251. package/src/components/interaction/form/Switch/Switch.module.css +12 -13
  252. package/src/components/interaction/form/Switch/Switch.spec.tsx +20 -0
  253. package/src/components/interaction/form/Switch/Switch.tsx +2 -1
  254. package/src/components/interaction/form/Textarea/Textarea.mdx +5 -0
  255. package/src/components/interaction/form/Textarea/Textarea.module.css +5 -5
  256. package/src/components/interaction/form/Textarea/Textarea.spec.tsx +13 -0
  257. package/src/components/interaction/form/Textarea/Textarea.tsx +3 -1
  258. package/src/components/interaction/form/atoms/Message.module.css +1 -1
  259. package/src/components/interaction/form/atoms/Message.spec.tsx +29 -0
  260. package/src/components/interaction/form/atoms/Message.tsx +1 -1
  261. package/src/components/layout/ButtonGroup/ButtonGroup.mdx +11 -0
  262. package/src/components/layout/ButtonGroup/ButtonGroup.module.css +1 -5
  263. package/src/components/layout/ButtonGroup/ButtonGroup.stories.tsx +14 -0
  264. package/src/components/layout/Card/Card.mdx +6 -1
  265. package/src/components/layout/Card/Card.module.css +27 -6
  266. package/src/components/layout/Card/Card.spec.tsx +7 -0
  267. package/src/components/layout/Card/Card.tsx +4 -3
  268. package/src/components/layout/Grid/Grid.spec.tsx +44 -0
  269. package/src/components/layout/Grid/Grid.tsx +5 -5
  270. package/src/components/layout/Grid/GridItem.tsx +6 -6
  271. package/src/components/layout/Grid/masonry.ts +31 -5
  272. package/src/components/layout/Grid/useIsomorphicLayoutEffect.ts +11 -0
  273. package/src/components/layout/IconWrapper/IconWrapper.mdx +8 -2
  274. package/src/components/layout/IconWrapper/IconWrapper.module.css +9 -6
  275. package/src/components/layout/SectionHeader/SectionHeader.mdx +4 -1
  276. package/src/components/layout/SectionHeader/SectionHeader.module.css +10 -9
  277. package/src/components/ui/Accordion/Accordion.mdx +4 -1
  278. package/src/components/ui/Accordion/Accordion.module.css +2 -1
  279. package/src/components/ui/Alert/Alert.mdx +21 -4
  280. package/src/components/ui/Alert/Alert.module.css +9 -4
  281. package/src/components/ui/Alert/Alert.spec.tsx +20 -0
  282. package/src/components/ui/Avatar/Avatar.mdx +8 -3
  283. package/src/components/ui/Avatar/Avatar.module.css +13 -8
  284. package/src/components/ui/Badge/Badge.mdx +3 -1
  285. package/src/components/ui/Breadcrumb/Breadcrumb.mdx +3 -0
  286. package/src/components/ui/Breadcrumb/Breadcrumb.module.css +4 -0
  287. package/src/components/ui/Breadcrumb/Breadcrumb.spec.tsx +12 -0
  288. package/src/components/ui/Breadcrumb/Breadcrumb.tsx +11 -3
  289. package/src/components/ui/Calendar/Calendar.mdx +6 -0
  290. package/src/components/ui/Calendar/Calendar.module.css +69 -20
  291. package/src/components/ui/Calendar/Calendar.spec.tsx +139 -24
  292. package/src/components/ui/Calendar/Calendar.stories.tsx +14 -0
  293. package/src/components/ui/Calendar/Calendar.tsx +143 -154
  294. package/src/components/ui/Calendar/CalendarRange.mdx +39 -0
  295. package/src/components/ui/Calendar/CalendarRange.spec.tsx +119 -0
  296. package/src/components/ui/Calendar/CalendarRange.stories.tsx +51 -0
  297. package/src/components/ui/Calendar/CalendarRange.tsx +213 -0
  298. package/src/components/ui/Calendar/MonthGrid.tsx +141 -0
  299. package/src/components/ui/Calendar/calendar-core.spec.ts +176 -0
  300. package/src/components/ui/Calendar/calendar-core.ts +164 -0
  301. package/src/components/ui/Calendar/index.ts +1 -0
  302. package/src/components/ui/Carousel/Carousel.mdx +8 -3
  303. package/src/components/ui/Carousel/Carousel.module.css +7 -5
  304. package/src/components/ui/Carousel/Carousel.spec.tsx +67 -0
  305. package/src/components/ui/Carousel/Carousel.tsx +19 -7
  306. package/src/components/ui/Collapsible/Collapsible.mdx +17 -6
  307. package/src/components/ui/Collapsible/Collapsible.module.css +7 -2
  308. package/src/components/ui/Collapsible/Collapsible.spec.tsx +40 -0
  309. package/src/components/ui/Collapsible/Collapsible.tsx +19 -2
  310. package/src/components/ui/DescriptionList/DescriptionList.mdx +2 -0
  311. package/src/components/ui/Link/Link.mdx +4 -2
  312. package/src/components/ui/Loading/Loading.mdx +6 -3
  313. package/src/components/ui/Loading/Loading.module.css +7 -7
  314. package/src/components/ui/Loading/Loading.spec.tsx +12 -0
  315. package/src/components/ui/Loading/Loading.tsx +8 -3
  316. package/src/components/ui/NotificationBanner/NotificationBanner.mdx +4 -0
  317. package/src/components/ui/NotificationBanner/NotificationBanner.module.css +5 -0
  318. package/src/components/ui/NotificationBanner/NotificationBanner.spec.tsx +20 -0
  319. package/src/components/ui/Pagination/Pagination.mdx +29 -7
  320. package/src/components/ui/Pagination/Pagination.module.css +15 -14
  321. package/src/components/ui/Progress/Progress.mdx +6 -2
  322. package/src/components/ui/Progress/Progress.module.css +1 -1
  323. package/src/components/ui/Progress/Progress.spec.tsx +17 -0
  324. package/src/components/ui/Progress/Progress.tsx +2 -2
  325. package/src/components/ui/ProgressCircle/ProgressCircle.mdx +8 -4
  326. package/src/components/ui/ProgressCircle/ProgressCircle.module.css +2 -2
  327. package/src/components/ui/ProgressCircle/ProgressCircle.spec.tsx +11 -1
  328. package/src/components/ui/ProgressCircle/ProgressCircle.tsx +1 -1
  329. package/src/components/ui/Separator/Separator.mdx +7 -0
  330. package/src/components/ui/Separator/Separator.module.css +1 -0
  331. package/src/components/ui/Skeleton/Skeleton.mdx +17 -0
  332. package/src/components/ui/Skeleton/Skeleton.module.css +12 -5
  333. package/src/components/ui/SkipLink/SkipLink.mdx +19 -0
  334. package/src/components/ui/SkipLink/SkipLink.module.css +8 -7
  335. package/src/components/ui/SkipLink/SkipLink.spec.tsx +28 -0
  336. package/src/components/ui/Table/Table.mdx +14 -0
  337. package/src/components/ui/Table/Table.module.css +13 -8
  338. package/src/components/ui/Table/Table.spec.tsx +56 -0
  339. package/src/components/ui/Table/Table.tsx +44 -6
  340. package/src/components/ui/Tabs/Tabs.mdx +16 -0
  341. package/src/components/ui/Tabs/Tabs.module.css +3 -3
  342. package/src/components/ui/Tabs/Tabs.spec.tsx +20 -0
  343. package/src/components/ui/Tabs/Tabs.tsx +5 -1
  344. package/src/components/ui/Tooltip/Tooltip.mdx +9 -0
  345. package/src/components/ui/Tooltip/Tooltip.module.css +32 -12
  346. package/src/components/ui/Tooltip/Tooltip.spec.tsx +56 -0
  347. package/src/components/ui/Tooltip/Tooltip.tsx +26 -7
  348. package/src/components/ui/Typography/Typography.mdx +7 -0
  349. package/src/components/ui/Typography/Typography.module.css +5 -5
  350. package/src/index.ts +7 -3
  351. package/src/stories/DesignSystem/Borders.mdx +14 -9
  352. package/src/stories/DesignSystem/Colors.mdx +43 -41
  353. package/src/stories/DesignSystem/Overview.mdx +4 -3
  354. package/src/stories/Introduction.mdx +5 -5
  355. package/src/web-components/globals.ts +7 -0
  356. package/src/web-components/index.ts +2 -0
  357. package/src/web-components/interaction/BdsAccordion.mdx +10 -1
  358. package/src/web-components/interaction/BdsButton.mdx +15 -4
  359. package/src/web-components/interaction/BdsButton.stories.tsx +1 -1
  360. package/src/web-components/interaction/BdsCollapsible.mdx +3 -3
  361. package/src/web-components/interaction/BdsDialog.mdx +12 -7
  362. package/src/web-components/interaction/BdsDialog.stories.tsx +2 -2
  363. package/src/web-components/interaction/BdsDrawer.mdx +9 -6
  364. package/src/web-components/interaction/BdsDropdownMenu.mdx +20 -1
  365. package/src/web-components/interaction/BdsPopover.mdx +7 -3
  366. package/src/web-components/interaction/BdsSkipLink.mdx +14 -1
  367. package/src/web-components/interaction/BdsTabs.mdx +18 -1
  368. package/src/web-components/interaction/BdsToastProvider.mdx +21 -3
  369. package/src/web-components/interaction/BdsTooltip.mdx +4 -4
  370. package/src/web-components/interaction/bds-accordion-item.ts +10 -0
  371. package/src/web-components/interaction/bds-accordion.spec.ts +41 -0
  372. package/src/web-components/interaction/bds-accordion.ts +28 -2
  373. package/src/web-components/interaction/bds-button.spec.ts +81 -0
  374. package/src/web-components/interaction/bds-button.ts +55 -8
  375. package/src/web-components/interaction/bds-collapsible.spec.ts +93 -2
  376. package/src/web-components/interaction/bds-collapsible.ts +49 -7
  377. package/src/web-components/interaction/bds-dialog.spec.ts +49 -0
  378. package/src/web-components/interaction/bds-dialog.ts +69 -12
  379. package/src/web-components/interaction/bds-drawer.spec.ts +93 -4
  380. package/src/web-components/interaction/bds-drawer.ts +55 -22
  381. package/src/web-components/interaction/bds-dropdown-menu-item.ts +12 -1
  382. package/src/web-components/interaction/bds-dropdown-menu.spec.ts +63 -0
  383. package/src/web-components/interaction/bds-dropdown-menu.ts +45 -7
  384. package/src/web-components/interaction/bds-popover.spec.ts +80 -6
  385. package/src/web-components/interaction/bds-popover.ts +84 -33
  386. package/src/web-components/interaction/bds-skip-link.spec.ts +18 -0
  387. package/src/web-components/interaction/bds-skip-link.ts +29 -8
  388. package/src/web-components/interaction/bds-tab-panel.ts +10 -0
  389. package/src/web-components/interaction/bds-tab.spec.ts +25 -0
  390. package/src/web-components/interaction/bds-tab.ts +20 -5
  391. package/src/web-components/interaction/bds-tabs.spec.ts +92 -5
  392. package/src/web-components/interaction/bds-tabs.ts +42 -1
  393. package/src/web-components/interaction/bds-toast-provider.spec.ts +43 -0
  394. package/src/web-components/interaction/bds-toast-provider.ts +50 -21
  395. package/src/web-components/interaction/bds-tooltip.spec.ts +71 -0
  396. package/src/web-components/interaction/bds-tooltip.ts +100 -5
  397. package/src/web-components/interaction/form/BdsCheckbox.mdx +20 -1
  398. package/src/web-components/interaction/form/BdsCheckbox.stories.tsx +8 -0
  399. package/src/web-components/interaction/form/BdsCheckboxGroup.mdx +4 -3
  400. package/src/web-components/interaction/form/BdsCombobox.mdx +39 -2
  401. package/src/web-components/interaction/form/BdsCombobox.stories.tsx +31 -0
  402. package/src/web-components/interaction/form/BdsFieldGroup.mdx +8 -3
  403. package/src/web-components/interaction/form/BdsFieldGroup.stories.tsx +1 -1
  404. package/src/web-components/interaction/form/BdsFileInput.mdx +26 -5
  405. package/src/web-components/interaction/form/BdsFormInput.mdx +16 -1
  406. package/src/web-components/interaction/form/BdsNumberInput.mdx +34 -2
  407. package/src/web-components/interaction/form/BdsNumberInput.stories.tsx +27 -3
  408. package/src/web-components/interaction/form/BdsRadio.mdx +39 -12
  409. package/src/web-components/interaction/form/BdsRadio.stories.tsx +26 -0
  410. package/src/web-components/interaction/form/BdsRadioGroup.mdx +9 -4
  411. package/src/web-components/interaction/form/BdsSegmentedControl.mdx +37 -11
  412. package/src/web-components/interaction/form/BdsSelect.mdx +22 -4
  413. package/src/web-components/interaction/form/BdsSelect.stories.tsx +33 -0
  414. package/src/web-components/interaction/form/BdsSlider.mdx +36 -19
  415. package/src/web-components/interaction/form/BdsSlider.stories.tsx +24 -0
  416. package/src/web-components/interaction/form/BdsSwitch.mdx +38 -11
  417. package/src/web-components/interaction/form/BdsSwitch.stories.tsx +16 -0
  418. package/src/web-components/interaction/form/BdsTextarea.mdx +42 -16
  419. package/src/web-components/interaction/form/BdsTextarea.stories.tsx +21 -0
  420. package/src/web-components/interaction/form/bds-checkbox-group.spec.ts +99 -0
  421. package/src/web-components/interaction/form/bds-checkbox-group.ts +95 -9
  422. package/src/web-components/interaction/form/bds-checkbox.spec.ts +55 -0
  423. package/src/web-components/interaction/form/bds-checkbox.ts +30 -5
  424. package/src/web-components/interaction/form/bds-combobox.spec.ts +79 -0
  425. package/src/web-components/interaction/form/bds-combobox.ts +101 -16
  426. package/src/web-components/interaction/form/bds-field-group.spec.ts +158 -0
  427. package/src/web-components/interaction/form/bds-field-group.ts +167 -23
  428. package/src/web-components/interaction/form/bds-file-input.spec.ts +73 -5
  429. package/src/web-components/interaction/form/bds-file-input.ts +71 -34
  430. package/src/web-components/interaction/form/bds-form-input.spec.ts +22 -0
  431. package/src/web-components/interaction/form/bds-form-input.ts +27 -16
  432. package/src/web-components/interaction/form/bds-number-input.spec.ts +49 -0
  433. package/src/web-components/interaction/form/bds-number-input.ts +118 -29
  434. package/src/web-components/interaction/form/bds-radio-group.spec.ts +57 -0
  435. package/src/web-components/interaction/form/bds-radio-group.ts +60 -12
  436. package/src/web-components/interaction/form/bds-radio.spec.ts +123 -0
  437. package/src/web-components/interaction/form/bds-radio.ts +135 -22
  438. package/src/web-components/interaction/form/bds-segmented-control.spec.ts +55 -0
  439. package/src/web-components/interaction/form/bds-segmented-control.ts +81 -59
  440. package/src/web-components/interaction/form/bds-select.spec.ts +57 -0
  441. package/src/web-components/interaction/form/bds-select.ts +95 -7
  442. package/src/web-components/interaction/form/bds-slider.spec.ts +83 -0
  443. package/src/web-components/interaction/form/bds-slider.ts +154 -26
  444. package/src/web-components/interaction/form/bds-switch.spec.ts +68 -0
  445. package/src/web-components/interaction/form/bds-switch.ts +87 -20
  446. package/src/web-components/interaction/form/bds-textarea.spec.ts +71 -0
  447. package/src/web-components/interaction/form/bds-textarea.ts +108 -7
  448. package/src/web-components/layout/BdsGrid.mdx +6 -2
  449. package/src/web-components/layout/BdsGrid.stories.tsx +4 -0
  450. package/src/web-components/layout/bds-grid-item.spec.ts +21 -0
  451. package/src/web-components/layout/bds-grid-item.ts +17 -3
  452. package/src/web-components/layout/bds-grid.spec.ts +98 -0
  453. package/src/web-components/layout/bds-grid.ts +139 -19
  454. package/src/web-components/ui/BdsAlert.mdx +6 -5
  455. package/src/web-components/ui/BdsAlert.stories.tsx +6 -6
  456. package/src/web-components/ui/BdsAvatar.mdx +4 -2
  457. package/src/web-components/ui/BdsBreadcrumb.mdx +3 -2
  458. package/src/web-components/ui/BdsButtonContainer.mdx +64 -0
  459. package/src/web-components/ui/BdsButtonContainer.stories.tsx +84 -0
  460. package/src/web-components/ui/BdsCalendar.mdx +29 -4
  461. package/src/web-components/ui/BdsCalendar.stories.tsx +16 -18
  462. package/src/web-components/ui/BdsCalendarRange.mdx +71 -0
  463. package/src/web-components/ui/BdsCalendarRange.stories.tsx +31 -0
  464. package/src/web-components/ui/BdsCard.mdx +7 -3
  465. package/src/web-components/ui/BdsCard.stories.tsx +17 -1
  466. package/src/web-components/ui/BdsCarousel.mdx +40 -12
  467. package/src/web-components/ui/BdsDescriptionList.mdx +6 -1
  468. package/src/web-components/ui/BdsIconWrapper.mdx +3 -2
  469. package/src/web-components/ui/BdsLink.mdx +14 -2
  470. package/src/web-components/ui/BdsNotificationBanner.mdx +18 -0
  471. package/src/web-components/ui/BdsPagination.mdx +40 -1
  472. package/src/web-components/ui/BdsProgress.mdx +8 -2
  473. package/src/web-components/ui/BdsProgressCircle.mdx +5 -2
  474. package/src/web-components/ui/BdsRating.mdx +7 -0
  475. package/src/web-components/ui/BdsSectionHeader.mdx +22 -3
  476. package/src/web-components/ui/BdsSectionHeader.stories.tsx +15 -13
  477. package/src/web-components/ui/BdsTable.mdx +23 -2
  478. package/src/web-components/ui/BdsTable.stories.tsx +8 -2
  479. package/src/web-components/ui/BdsTypography.mdx +17 -1
  480. package/src/web-components/ui/bds-alert.spec.ts +17 -2
  481. package/src/web-components/ui/bds-alert.ts +31 -5
  482. package/src/web-components/ui/bds-avatar.spec.ts +29 -0
  483. package/src/web-components/ui/bds-avatar.ts +29 -11
  484. package/src/web-components/ui/bds-badge.spec.ts +5 -0
  485. package/src/web-components/ui/bds-badge.ts +11 -1
  486. package/src/web-components/ui/bds-breadcrumb.spec.ts +30 -0
  487. package/src/web-components/ui/bds-breadcrumb.ts +26 -4
  488. package/src/web-components/ui/bds-button-container.spec.ts +39 -0
  489. package/src/web-components/ui/bds-button-container.ts +123 -0
  490. package/src/web-components/ui/bds-button-group.spec.ts +14 -20
  491. package/src/web-components/ui/bds-button-group.ts +13 -64
  492. package/src/web-components/ui/bds-calendar-range.spec.ts +123 -0
  493. package/src/web-components/ui/bds-calendar-range.ts +307 -0
  494. package/src/web-components/ui/bds-calendar.spec.ts +176 -0
  495. package/src/web-components/ui/bds-calendar.ts +186 -344
  496. package/src/web-components/ui/bds-card.spec.ts +32 -0
  497. package/src/web-components/ui/bds-card.ts +35 -10
  498. package/src/web-components/ui/bds-carousel.spec.ts +147 -0
  499. package/src/web-components/ui/bds-carousel.ts +109 -32
  500. package/src/web-components/ui/bds-description-list.spec.ts +15 -0
  501. package/src/web-components/ui/bds-description-list.ts +37 -3
  502. package/src/web-components/ui/bds-icon-wrapper.spec.ts +12 -0
  503. package/src/web-components/ui/bds-icon-wrapper.ts +15 -14
  504. package/src/web-components/ui/bds-link.spec.ts +17 -0
  505. package/src/web-components/ui/bds-link.ts +26 -11
  506. package/src/web-components/ui/bds-loading.ts +10 -0
  507. package/src/web-components/ui/bds-notification-banner.spec.ts +13 -0
  508. package/src/web-components/ui/bds-notification-banner.ts +18 -1
  509. package/src/web-components/ui/bds-pagination.spec.ts +44 -0
  510. package/src/web-components/ui/bds-pagination.ts +39 -19
  511. package/src/web-components/ui/bds-progress-circle.spec.ts +21 -0
  512. package/src/web-components/ui/bds-progress-circle.ts +17 -5
  513. package/src/web-components/ui/bds-progress.spec.ts +21 -0
  514. package/src/web-components/ui/bds-progress.ts +17 -4
  515. package/src/web-components/ui/bds-rating.spec.ts +6 -0
  516. package/src/web-components/ui/bds-rating.ts +12 -2
  517. package/src/web-components/ui/bds-section-header.spec.ts +39 -8
  518. package/src/web-components/ui/bds-section-header.ts +47 -13
  519. package/src/web-components/ui/bds-separator.ts +10 -0
  520. package/src/web-components/ui/bds-skeleton.ts +10 -0
  521. package/src/web-components/ui/bds-table.spec.ts +63 -0
  522. package/src/web-components/ui/bds-table.ts +88 -28
  523. package/src/web-components/ui/bds-typography.spec.ts +47 -0
  524. package/src/web-components/ui/bds-typography.ts +28 -10
  525. package/src/web-components/ui/calendar-styles.ts +94 -0
  526. package/dist/web-components/chunk-7YURXHTS.js +0 -147
  527. package/dist/web-components/chunk-A3RLT3AS.js +0 -49
  528. package/dist/web-components/chunk-AGKJTMJI.js +0 -56
  529. package/dist/web-components/chunk-BQLZ7I4G.js +0 -56
  530. package/dist/web-components/chunk-DZOEPVFT.js +0 -107
  531. package/dist/web-components/chunk-JYYRJS2D.js +0 -118
  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
@@ -68,4 +68,29 @@ describe('bds-tab', () => {
68
68
  expect(btn.hasAttribute('disabled')).toBe(true);
69
69
  cleanup(el);
70
70
  });
71
+
72
+ it('lets the public --tab_color/--tab_border-color tokens win over selected/hover-state defaults', () => {
73
+ const cssText = BdsTab.styles.cssText;
74
+ expect(cssText).toMatch(
75
+ /\.tab\s*{[^}]*color:\s*var\(--tab_color,\s*var\(--tab_color--state,\s*var\(--bds-color_on-bg\)\)\)/,
76
+ );
77
+ expect(cssText).toMatch(
78
+ /\.tab\s*{[^}]*border-block-end:\s*2px solid var\(--tab_border-color,\s*var\(--tab_border-color--state,\s*transparent\)\)/,
79
+ );
80
+ });
81
+
82
+ it('has the selected/hover rules write only to the internal --tab_*--state slots, not the public tokens', () => {
83
+ const cssText = BdsTab.styles.cssText;
84
+ expect(cssText).not.toMatch(/:host\(\[selected\]\)\s*\.tab\s*{[^}]*--tab_color:/);
85
+ expect(cssText).not.toMatch(/:host\(\[selected\]\)\s*\.tab\s*{[^}]*--tab_border-color:/);
86
+ expect(cssText).toMatch(
87
+ /:host\(\[selected\]\)\s*\.tab\s*{[^}]*--tab_color--state:\s*var\(--tab_color--active,/,
88
+ );
89
+ expect(cssText).toMatch(
90
+ /:host\(\[selected\]\)\s*\.tab\s*{[^}]*--tab_border-color--state:\s*var\(--tab_border-color--active,/,
91
+ );
92
+ expect(cssText).toMatch(
93
+ /--tab_color--state:\s*var\(--tab_color--hover,/,
94
+ );
95
+ });
71
96
  });
@@ -17,6 +17,16 @@ import { LitElement, css, html } from 'lit';
17
17
  */
18
18
  export class BdsTab extends LitElement {
19
19
  static styles = css`
20
+ /* Shadow DOM does not inherit the global box-sizing reset, so set it
21
+ here; otherwise elements with an explicit size + padding size as
22
+ content-box and layouts drift from the React (light-DOM) versions. */
23
+ :host,
24
+ *,
25
+ *::before,
26
+ *::after {
27
+ box-sizing: border-box;
28
+ }
29
+
20
30
  :host {
21
31
  display: inline-flex;
22
32
  }
@@ -29,8 +39,13 @@ export class BdsTab extends LitElement {
29
39
  font-family: var(--bds-font_family--body);
30
40
  font-size: var(--bds-font_size--body);
31
41
  font-weight: var(--bds-font_weight--semibold);
32
- color: var(--tab_color, var(--bds-color_on-bg));
33
- border-block-end: 2px solid var(--tab_border-color, transparent);
42
+
43
+ /* Layered cascade: public overrides (--tab_color, --tab_border-color) win over
44
+ per-state defaults. Active/hover write to the inner --tab_*--state slot —
45
+ mirrors the React Tabs.module.css pattern so a consumer's --tab_color
46
+ override is never shadowed by the selected/hover rules below. */
47
+ color: var(--tab_color, var(--tab_color--state, var(--bds-color_on-bg)));
48
+ border-block-end: 2px solid var(--tab_border-color, var(--tab_border-color--state, transparent));
34
49
  margin-block-end: -1px;
35
50
  cursor: pointer;
36
51
  transition: var(--bds-animation_transition);
@@ -38,8 +53,8 @@ export class BdsTab extends LitElement {
38
53
  }
39
54
 
40
55
  :host([selected]) .tab {
41
- --tab_color: var(--bds-color_interactive_on-bg);
42
- --tab_border-color: var(--bds-color_interactive);
56
+ --tab_color--state: var(--tab_color--active, var(--bds-color_interactive_on-bg));
57
+ --tab_border-color--state: var(--tab_border-color--active, var(--bds-color_interactive));
43
58
  }
44
59
 
45
60
  .tab:disabled {
@@ -55,7 +70,7 @@ export class BdsTab extends LitElement {
55
70
 
56
71
  @media (hover: hover) and (pointer: fine) {
57
72
  .tab:not(:disabled, [aria-selected='true']):hover {
58
- --tab_color: var(--bds-color_interactive_on-bg);
73
+ --tab_color--state: var(--tab_color--hover, var(--bds-color_interactive_on-bg));
59
74
  }
60
75
  }
61
76
  `;
@@ -36,6 +36,23 @@ describe('bds-tabs', () => {
36
36
  cleanup(el);
37
37
  });
38
38
 
39
+ it('does not select a disabled first tab — activates the first enabled tab instead', async () => {
40
+ const el = await fixture(`
41
+ <bds-tabs>
42
+ <bds-tab slot="tab" disabled>Tab 1</bds-tab>
43
+ <bds-tab slot="tab">Tab 2</bds-tab>
44
+ <bds-tab-panel slot="panel">Panel 1</bds-tab-panel>
45
+ <bds-tab-panel slot="panel">Panel 2</bds-tab-panel>
46
+ </bds-tabs>
47
+ `);
48
+ // Wait for deferred _applyState
49
+ await Promise.resolve();
50
+ const tabs = [...el.querySelectorAll<BdsTab>('bds-tab')];
51
+ expect(tabs[0].selected).toBe(false);
52
+ expect(tabs[1].selected).toBe(true);
53
+ cleanup(el);
54
+ });
55
+
39
56
  it('first panel is visible, others are hidden by default', async () => {
40
57
  const el = await fixture(html);
41
58
  await Promise.resolve();
@@ -77,9 +94,10 @@ describe('bds-tabs', () => {
77
94
  it('ArrowRight moves to next enabled tab', async () => {
78
95
  const el = await fixture(html);
79
96
  await Promise.resolve();
80
- el.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowRight', bubbles: true }));
81
- await Promise.resolve();
82
97
  const tabs = [...el.querySelectorAll<BdsTab>('bds-tab')];
98
+ // Real usage: the keydown originates from the focused (currently active) tab.
99
+ tabs[0].dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowRight', bubbles: true }));
100
+ await Promise.resolve();
83
101
  expect(tabs[1].selected).toBe(true);
84
102
  cleanup(el);
85
103
  });
@@ -89,7 +107,7 @@ describe('bds-tabs', () => {
89
107
  await Promise.resolve();
90
108
  const tabs = [...el.querySelectorAll<BdsTab>('bds-tab')];
91
109
  tabs[2].disabled = true; // ensure disabled is set (Lit property may not reflect from HTML attribute in jsdom)
92
- el.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowLeft', bubbles: true }));
110
+ tabs[0].dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowLeft', bubbles: true }));
93
111
  // disabled tab is skipped; enabled tabs are 0 and 1 → wraps to last enabled (index 1)
94
112
  expect(tabs[1].selected).toBe(true);
95
113
  cleanup(el);
@@ -102,7 +120,7 @@ describe('bds-tabs', () => {
102
120
  await Promise.all(tabs.map(t => t.updateComplete));
103
121
  // Navigate to tab 1 first
104
122
  tabs[1].dispatchEvent(new CustomEvent('bds-tab-select', { bubbles: true, composed: true }));
105
- el.dispatchEvent(new KeyboardEvent('keydown', { key: 'Home', bubbles: true }));
123
+ tabs[1].dispatchEvent(new KeyboardEvent('keydown', { key: 'Home', bubbles: true }));
106
124
  expect(tabs[0].selected).toBe(true);
107
125
  cleanup(el);
108
126
  });
@@ -112,9 +130,78 @@ describe('bds-tabs', () => {
112
130
  await Promise.resolve();
113
131
  const tabs = [...el.querySelectorAll<BdsTab>('bds-tab')];
114
132
  tabs[2].disabled = true; // ensure disabled is set
115
- el.dispatchEvent(new KeyboardEvent('keydown', { key: 'End', bubbles: true }));
133
+ tabs[0].dispatchEvent(new KeyboardEvent('keydown', { key: 'End', bubbles: true }));
116
134
  // Last enabled tab is index 1 (tab 3 is disabled)
117
135
  expect(tabs[1].selected).toBe(true);
118
136
  cleanup(el);
119
137
  });
138
+
139
+ it('does not hijack Arrow/Home/End keys typed outside a <bds-tab> (e.g. host-level dispatch)', async () => {
140
+ const el = await fixture(html);
141
+ await Promise.resolve();
142
+ const tabs = [...el.querySelectorAll<BdsTab>('bds-tab')];
143
+ // Dispatched directly on the <bds-tabs> host — not on a <bds-tab> — must be ignored.
144
+ el.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowRight', bubbles: true }));
145
+ await Promise.resolve();
146
+ expect(tabs[0].selected).toBe(true);
147
+ expect(tabs[1].selected).toBe(false);
148
+ cleanup(el);
149
+ });
150
+
151
+ it('does not hijack ArrowLeft pressed inside a tab-panel input (caret movement stays with the input)', async () => {
152
+ const el = await fixture(`
153
+ <bds-tabs>
154
+ <bds-tab slot="tab">Tab 1</bds-tab>
155
+ <bds-tab slot="tab">Tab 2</bds-tab>
156
+ <bds-tab-panel slot="panel"><input type="text" /></bds-tab-panel>
157
+ <bds-tab-panel slot="panel">Panel 2</bds-tab-panel>
158
+ </bds-tabs>
159
+ `);
160
+ await Promise.resolve();
161
+ const tabs = [...el.querySelectorAll<BdsTab>('bds-tab')];
162
+ const input = el.querySelector('input')!;
163
+ input.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowLeft', bubbles: true }));
164
+ await Promise.resolve();
165
+ expect(tabs[0].selected).toBe(true);
166
+ expect(tabs[1].selected).toBe(false);
167
+ cleanup(el);
168
+ });
169
+
170
+ it('wires role/id/aria-controls on tabs and role/id/aria-labelledby on panels', async () => {
171
+ const el = await fixture(html);
172
+ await Promise.resolve();
173
+ const tabs = [...el.querySelectorAll<BdsTab>('bds-tab')];
174
+ const panels = [...el.querySelectorAll<BdsTabPanel>('bds-tab-panel')];
175
+
176
+ tabs.forEach((tab, i) => {
177
+ expect(tab.getAttribute('role')).toBe('tab');
178
+ expect(tab.id).toBeTruthy();
179
+ expect(tab.getAttribute('aria-controls')).toBe(panels[i].id);
180
+ });
181
+
182
+ panels.forEach((panel, i) => {
183
+ expect(panel.getAttribute('role')).toBe('tabpanel');
184
+ expect(panel.id).toBeTruthy();
185
+ expect(panel.getAttribute('aria-labelledby')).toBe(tabs[i].id);
186
+ });
187
+
188
+ cleanup(el);
189
+ });
190
+
191
+ it('preserves a consumer-supplied id instead of overwriting it', async () => {
192
+ const el = await fixture(`
193
+ <bds-tabs>
194
+ <bds-tab slot="tab" id="custom-tab-id">Tab 1</bds-tab>
195
+ <bds-tab-panel slot="panel" id="custom-panel-id">Panel 1</bds-tab-panel>
196
+ </bds-tabs>
197
+ `);
198
+ await Promise.resolve();
199
+ const tab = el.querySelector<BdsTab>('bds-tab')!;
200
+ const panel = el.querySelector<BdsTabPanel>('bds-tab-panel')!;
201
+ expect(tab.id).toBe('custom-tab-id');
202
+ expect(panel.id).toBe('custom-panel-id');
203
+ expect(tab.getAttribute('aria-controls')).toBe('custom-panel-id');
204
+ expect(panel.getAttribute('aria-labelledby')).toBe('custom-tab-id');
205
+ cleanup(el);
206
+ });
120
207
  });
@@ -26,6 +26,16 @@ import type { BdsTabPanel } from './bds-tab-panel';
26
26
  */
27
27
  export class BdsTabs extends LitElement {
28
28
  static styles = css`
29
+ /* Shadow DOM does not inherit the global box-sizing reset, so set it
30
+ here; otherwise elements with an explicit size + padding size as
31
+ content-box and layouts drift from the React (light-DOM) versions. */
32
+ :host,
33
+ *,
34
+ *::before,
35
+ *::after {
36
+ box-sizing: border-box;
37
+ }
38
+
29
39
  :host {
30
40
  display: flex;
31
41
  flex-direction: column;
@@ -40,6 +50,7 @@ export class BdsTabs extends LitElement {
40
50
 
41
51
  private _activeIndex = 0;
42
52
  private _mo: MutationObserver | null = null;
53
+ private readonly _uid = Math.random().toString(36).slice(2, 8);
43
54
 
44
55
  connectedCallback() {
45
56
  super.connectedCallback();
@@ -70,7 +81,10 @@ export class BdsTabs extends LitElement {
70
81
  private get _enabledIndexes(): number[] {
71
82
  return this._tabs
72
83
  .map((tab, i) => ({ tab, i }))
73
- .filter(({ tab }) => !tab.disabled)
84
+ // Check the attribute too: on first render the reflected `disabled`
85
+ // property may not be set yet when _applyState runs, but the authored
86
+ // `disabled` attribute is already present.
87
+ .filter(({ tab }) => !tab.disabled && !tab.hasAttribute('disabled'))
74
88
  .map(({ i }) => i);
75
89
  }
76
90
 
@@ -83,8 +97,28 @@ export class BdsTabs extends LitElement {
83
97
  this._activeIndex = Math.max(0, tabs.length - 1);
84
98
  }
85
99
 
100
+ // A disabled tab must never be the active one. If the current active index
101
+ // is not an enabled tab (e.g. the default index-0 tab is <bds-tab disabled>),
102
+ // move selection to the first enabled tab — matching the React Tabs behaviour.
103
+ if (this._enabledIndexes.length && !this._enabledIndexes.includes(this._activeIndex)) {
104
+ this._activeIndex = this._enabledIndexes[0];
105
+ }
106
+
107
+ // Assign role/id/aria-* on the light-DOM host elements (not the shadow-internal
108
+ // button/slot) — <bds-tab> and <bds-tab-panel> share the light-DOM tree with
109
+ // <bds-tabs>, so id-based aria-controls/aria-labelledby references resolve.
110
+ // Shadow-internal ids would not be valid IDREF targets from outside their root.
86
111
  tabs.forEach((tab, i) => {
112
+ const panel = panels[i];
87
113
  tab.selected = (i === this._activeIndex);
114
+ tab.setAttribute('role', 'tab');
115
+ if (!tab.id) tab.id = `bds-tabs-${this._uid}-tab-${i}`;
116
+ if (panel) {
117
+ if (!panel.id) panel.id = `bds-tabs-${this._uid}-panel-${i}`;
118
+ tab.setAttribute('aria-controls', panel.id);
119
+ panel.setAttribute('role', 'tabpanel');
120
+ panel.setAttribute('aria-labelledby', tab.id);
121
+ }
88
122
  });
89
123
 
90
124
  panels.forEach((panel, i) => {
@@ -106,6 +140,13 @@ export class BdsTabs extends LitElement {
106
140
  };
107
141
 
108
142
  private _handleKeydown = (e: KeyboardEvent) => {
143
+ // Only handle Arrow/Home/End when the key originates from a <bds-tab> (i.e. a
144
+ // tab button has focus). Without this guard the host-level listener hijacked
145
+ // these keys anywhere in the light DOM, including tab-panel content such as
146
+ // text inputs, sliders, or carousels.
147
+ const origin = e.target as Element | null;
148
+ if (!origin?.closest('bds-tab')) return;
149
+
109
150
  const enabled = this._enabledIndexes;
110
151
  if (!enabled.length) return;
111
152
 
@@ -119,4 +119,47 @@ describe('bds-toast-provider', () => {
119
119
  expect(el.shadowRoot!.querySelectorAll('.toast').length).toBe(2);
120
120
  cleanup(el);
121
121
  });
122
+
123
+ it('updated() does not throw when showPopover() reports an already-open popover (regression)', async () => {
124
+ // jsdom does not implement the Popover API, so showPopover/hidePopover are
125
+ // undefined on real elements in tests — mock them to reproduce the real-browser
126
+ // InvalidStateError that fires when showPopover() is called on an already-open
127
+ // popover (e.g. a 2nd/3rd toast joining the queue while the popover is showing).
128
+ const el = await fixture('<bds-toast-provider></bds-toast-provider>') as BdsToastProvider;
129
+ el.showToast('First', 'info');
130
+ await el.updateComplete;
131
+ const container = el.shadowRoot!.querySelector('[popover="manual"]') as HTMLElement & {
132
+ showPopover?: () => void;
133
+ };
134
+ container.showPopover = vi.fn(() => {
135
+ throw new DOMException('Invalid state', 'InvalidStateError');
136
+ });
137
+ expect(() => (el as unknown as { updated: () => void }).updated()).not.toThrow();
138
+ expect(container.showPopover).toHaveBeenCalledTimes(1);
139
+ cleanup(el);
140
+ });
141
+
142
+ it('variant rules write --toast_color--variant, not the public --toast_color hook (cascade parity)', () => {
143
+ const cssText = BdsToastProvider.styles.cssText;
144
+ // Variants must only set the inner slot so a consumer-set --toast_color still
145
+ // wins the cascade (element-level declarations otherwise beat inherited values).
146
+ expect(cssText).toMatch(/\.toast\.--variant_error\s*{[^}]*--toast_color--variant:\s*var\(--toast_color--error, var\(--bds-color_error\)\)/);
147
+ expect(cssText).not.toMatch(/\.toast\.--variant_error\s*{[^}]*--toast_color:\s*var\(--bds-color_error\)/);
148
+ expect(cssText).toMatch(/background-color:\s*var\(--toast_color,\s*var\(--toast_color--variant,\s*var\(--bds-color_bg--strong,\s*var\(--bds-color_bg\)\)\)\);/);
149
+ });
150
+
151
+ it('close button expands its hit area to >=44px via the ::after pseudo-element (touch target)', () => {
152
+ const cssText = BdsToastProvider.styles.cssText;
153
+ expect(cssText).toMatch(/\.close::after\s*{[^}]*inset:\s*-0\.75rem;/);
154
+ });
155
+
156
+ it('container/toast/close use logical properties, not physical ones', () => {
157
+ const cssText = BdsToastProvider.styles.cssText;
158
+ expect(cssText).toMatch(/inset-block-end:\s*var\(--bds-space_xl,\s*2rem\);/);
159
+ expect(cssText).toMatch(/inset-inline-end:\s*var\(--bds-space_xl,\s*2rem\);/);
160
+ expect(cssText).not.toMatch(/\n\s*bottom:/);
161
+ expect(cssText).not.toMatch(/\n\s*right:/);
162
+ expect(cssText).not.toMatch(/\bwidth:\s*1\.25rem/);
163
+ expect(cssText).not.toMatch(/\bheight:\s*1\.25rem/);
164
+ });
122
165
  });
@@ -38,6 +38,16 @@ interface ToastEntry {
38
38
  */
39
39
  export class BdsToastProvider extends LitElement {
40
40
  static styles = css`
41
+ /* Shadow DOM does not inherit the global box-sizing reset, so set it
42
+ here; otherwise elements with an explicit size + padding size as
43
+ content-box and layouts drift from the React (light-DOM) versions. */
44
+ :host,
45
+ *,
46
+ *::before,
47
+ *::after {
48
+ box-sizing: border-box;
49
+ }
50
+
41
51
  :host {
42
52
  display: contents;
43
53
  }
@@ -46,8 +56,8 @@ export class BdsToastProvider extends LitElement {
46
56
  /* Reset UA popover defaults */
47
57
  position: fixed;
48
58
  inset: unset;
49
- bottom: var(--bds-space_xl, 2rem);
50
- right: var(--bds-space_xl, 2rem);
59
+ inset-block-end: var(--bds-space_xl, 2rem);
60
+ inset-inline-end: var(--bds-space_xl, 2rem);
51
61
  display: flex;
52
62
  flex-direction: column;
53
63
  gap: var(--bds-space_m, 1rem);
@@ -58,34 +68,36 @@ export class BdsToastProvider extends LitElement {
58
68
 
59
69
  .toast {
60
70
  padding: var(--bds-space_m) var(--bds-space_l);
61
- background-color: var(--toast_color, var(--bds-color_bg));
62
- color: var(--toast_on-color, var(--bds-color_on-bg));
63
- border-radius: var(--bds-border_radius--s);
64
- box-shadow: var(--bds-shadow_s);
71
+ /* Layered cascade: public overrides (--toast_color, --toast_on-color) win
72
+ over per-variant defaults. Variants write to the inner --toast_*--variant slot. */
73
+ background-color: var(--toast_color, var(--toast_color--variant, var(--bds-color_bg--strong, var(--bds-color_bg))));
74
+ color: var(--toast_on-color, var(--toast_on-color--variant, var(--bds-color_on-bg)));
75
+ border-radius: var(--toast_radius, var(--bds-border_radius--s));
76
+ box-shadow: var(--toast_shadow, var(--bds-shadow_s));
65
77
  display: flex;
66
78
  align-items: center;
67
79
  gap: var(--bds-space_m);
68
- min-width: 300px;
80
+ min-inline-size: min(300px, calc(100svw - 2 * var(--bds-space_xl)));
69
81
  }
70
82
 
71
83
  .toast.--variant_success {
72
- --toast_color: var(--bds-color_success);
73
- --toast_on-color: var(--bds-color_on-success);
84
+ --toast_color--variant: var(--toast_color--success, var(--bds-color_success));
85
+ --toast_on-color--variant: var(--toast_on-color--success, var(--bds-color_on-success));
74
86
  }
75
87
 
76
88
  .toast.--variant_warning {
77
- --toast_color: var(--bds-color_warning);
78
- --toast_on-color: var(--bds-color_on-warning);
89
+ --toast_color--variant: var(--toast_color--warning, var(--bds-color_warning));
90
+ --toast_on-color--variant: var(--toast_on-color--warning, var(--bds-color_on-warning));
79
91
  }
80
92
 
81
93
  .toast.--variant_info {
82
- --toast_color: var(--bds-color_bg--subtle);
83
- --toast_on-color: var(--bds-color_on-bg--subtle);
94
+ --toast_color--variant: var(--toast_color--info, var(--bds-color_bg--subtle));
95
+ --toast_on-color--variant: var(--toast_on-color--info, var(--bds-color_on-bg--subtle));
84
96
  }
85
97
 
86
98
  .toast.--variant_error {
87
- --toast_color: var(--bds-color_error);
88
- --toast_on-color: var(--bds-color_on-error);
99
+ --toast_color--variant: var(--toast_color--error, var(--bds-color_error));
100
+ --toast_on-color--variant: var(--toast_on-color--error, var(--bds-color_on-error));
89
101
  }
90
102
 
91
103
  .message {
@@ -93,22 +105,35 @@ export class BdsToastProvider extends LitElement {
93
105
  }
94
106
 
95
107
  .close {
108
+ position: relative;
96
109
  display: flex;
97
110
  align-items: center;
98
111
  justify-content: center;
99
112
  flex-shrink: 0;
100
- width: 1.25rem;
101
- height: 1.25rem;
113
+ inline-size: 1.25rem;
114
+ block-size: 1.25rem;
102
115
  padding: 0;
103
116
  background: none;
104
117
  border: none;
105
118
  cursor: pointer;
106
- color: var(--toast_on-color);
119
+ color: currentcolor;
120
+ }
121
+
122
+ /* Expands the hit area to >=44px (WCAG 2.5.5) without growing the visible icon. */
123
+ .close::after {
124
+ content: '';
125
+ position: absolute;
126
+ inset: -0.75rem;
127
+ }
128
+
129
+ .close:focus-visible {
130
+ outline: var(--bds-outline_default);
131
+ outline-offset: var(--bds-outline_offset);
107
132
  }
108
133
 
109
134
  .close svg {
110
- width: 1rem;
111
- height: 1rem;
135
+ inline-size: 1rem;
136
+ block-size: 1rem;
112
137
  }
113
138
  `;
114
139
 
@@ -135,6 +160,10 @@ export class BdsToastProvider extends LitElement {
135
160
 
136
161
  // Sync the popover's top-layer visibility with the toast queue —
137
162
  // mirrors Toast.tsx's useEffect([toasts.length]).
163
+ // Both showPopover() and hidePopover() throw an InvalidStateError when called
164
+ // in a redundant state (e.g. showPopover() while a 2nd/3rd toast is queued and
165
+ // the popover is already open, or hidePopover() before any toast has shown) —
166
+ // catch silently in both directions.
138
167
  updated() {
139
168
  const container = this.shadowRoot?.querySelector<HTMLElement & {
140
169
  showPopover?: () => void;
@@ -142,7 +171,7 @@ export class BdsToastProvider extends LitElement {
142
171
  }>('[popover]');
143
172
  if (!container) return;
144
173
  if (this._toasts.length > 0) {
145
- container.showPopover?.();
174
+ try { container.showPopover?.(); } catch { /* already open */ }
146
175
  } else {
147
176
  try { container.hidePopover?.(); } catch { /* already hidden on initial mount */ }
148
177
  }
@@ -46,4 +46,75 @@ describe('bds-tooltip', () => {
46
46
  expect(el.querySelector('button')!.textContent).toBe('Help');
47
47
  cleanup(el);
48
48
  });
49
+
50
+ it('associates the trigger with the tooltip content via aria-describedby', async () => {
51
+ const el = await fixture('<bds-tooltip content="Helpful text"><button type="button">?</button></bds-tooltip>');
52
+ // Wait for the deferred connectedCallback wiring (Promise.resolve().then(...)).
53
+ await Promise.resolve();
54
+ await Promise.resolve();
55
+
56
+ const trigger = el.querySelector('button')!;
57
+ const describedById = trigger.getAttribute('aria-describedby');
58
+ expect(describedById).toBeTruthy();
59
+
60
+ const descEl = el.querySelector(`#${describedById}`);
61
+ expect(descEl).not.toBeNull();
62
+ expect(descEl!.textContent).toBe('Helpful text');
63
+ // The description node must live in the light DOM (same tree scope as the
64
+ // trigger) — aria-describedby cannot reference an id inside the shadow root.
65
+ expect(descEl!.getRootNode()).toBe(document);
66
+ cleanup(el);
67
+ });
68
+
69
+ it('keeps a consumer-provided aria-describedby alongside the generated one', async () => {
70
+ const el = await fixture(
71
+ '<bds-tooltip content="Tip"><button type="button" aria-describedby="external-hint">?</button></bds-tooltip>',
72
+ );
73
+ await Promise.resolve();
74
+ await Promise.resolve();
75
+
76
+ const trigger = el.querySelector('button')!;
77
+ const ids = trigger.getAttribute('aria-describedby')!.split(/\s+/);
78
+ expect(ids).toContain('external-hint');
79
+ expect(ids.length).toBe(2);
80
+ cleanup(el);
81
+ });
82
+
83
+ it('updates the hidden description text when content changes', async () => {
84
+ const el = await fixture('<bds-tooltip content="First"><button type="button">?</button></bds-tooltip>') as BdsTooltip;
85
+ await Promise.resolve();
86
+ await Promise.resolve();
87
+
88
+ el.content = 'Second';
89
+ await el.updateComplete;
90
+
91
+ const trigger = el.querySelector('button')!;
92
+ const describedById = trigger.getAttribute('aria-describedby')!;
93
+ const descEl = el.querySelector(`#${describedById}`);
94
+ expect(descEl!.textContent).toBe('Second');
95
+ cleanup(el);
96
+ });
97
+
98
+ it('does not add aria-describedby when content is empty', async () => {
99
+ const el = await fixture('<bds-tooltip><button type="button">?</button></bds-tooltip>');
100
+ await Promise.resolve();
101
+ await Promise.resolve();
102
+
103
+ const trigger = el.querySelector('button')!;
104
+ expect(trigger.hasAttribute('aria-describedby')).toBe(false);
105
+ cleanup(el);
106
+ });
107
+
108
+ it('hides the shadow-DOM tooltip bubble from assistive technology', async () => {
109
+ const el = await fixture('<bds-tooltip content="Helpful text"><button type="button">?</button></bds-tooltip>');
110
+ const tooltip = el.shadowRoot!.querySelector('[role="tooltip"]')!;
111
+ expect(tooltip.getAttribute('aria-hidden')).toBe('true');
112
+ cleanup(el);
113
+ });
114
+
115
+ it('does not hardcode a z-index fallback (token parity with React Tooltip)', () => {
116
+ const cssText = BdsTooltip.styles.cssText;
117
+ expect(cssText).toMatch(/z-index:\s*var\(--bds-z-index_popover\);/);
118
+ expect(cssText).not.toContain('200');
119
+ });
49
120
  });