@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
@@ -1,4 +1,4 @@
1
- import { LitElement, css, html } from 'lit';
1
+ import { LitElement, css, html, nothing } from 'lit';
2
2
 
3
3
  export type PopoverPlacement = 'bottom' | 'top' | 'left' | 'right';
4
4
 
@@ -10,11 +10,14 @@ export type PopoverPlacement = 'bottom' | 'top' | 'left' | 'right';
10
10
  * overflow the viewport (`@position-try` fallbacks).
11
11
  *
12
12
  * Attributes:
13
- * placement — "bottom" (default) | "top" | "left" | "right"
14
- * open — boolean; reflects whether the panel is visible
13
+ * placement — "bottom" (default) | "top" | "left" | "right"
14
+ * open — boolean; reflects whether the panel is visible
15
+ * aria-label — accessible name for the panel; when present the panel gets
16
+ * `role="region"` (mirrors the React implementation)
15
17
  *
16
18
  * Slots:
17
- * trigger — the element that opens/closes the panel on click
19
+ * trigger — the element that opens/closes the panel on click. Receives
20
+ * `aria-haspopup`, `aria-controls` and `aria-expanded` wiring.
18
21
  * (default) — panel content
19
22
  *
20
23
  * Events:
@@ -29,6 +32,16 @@ export type PopoverPlacement = 'bottom' | 'top' | 'left' | 'right';
29
32
  */
30
33
  export class BdsPopover extends LitElement {
31
34
  static styles = css`
35
+ /* Shadow DOM does not inherit the global box-sizing reset, so set it
36
+ here; otherwise elements with an explicit size + padding size as
37
+ content-box and layouts drift from the React (light-DOM) versions. */
38
+ :host,
39
+ *,
40
+ *::before,
41
+ *::after {
42
+ box-sizing: border-box;
43
+ }
44
+
32
45
  :host {
33
46
  display: inline-flex;
34
47
  position: relative;
@@ -39,19 +52,23 @@ export class BdsPopover extends LitElement {
39
52
  gets its own unique name without colliding with siblings. */
40
53
  .wrapper {
41
54
  display: inline-flex;
42
- anchor-name: var(--bds-popover-anchor);
55
+ anchor-name: var(--popover-anchor);
43
56
  }
44
57
 
45
58
  .panel {
46
59
  display: none;
47
- position: absolute;
48
- position-anchor: var(--bds-popover-anchor);
60
+
61
+ /* position: fixed (not absolute) — containing block is the viewport,
62
+ so the panel escapes ancestor overflow:hidden/scroll clipping and
63
+ stacking contexts, matching the React implementation. */
64
+ position: fixed;
65
+ position-anchor: var(--popover-anchor);
49
66
  margin: 0;
50
- overflow-y: auto;
67
+ overflow-block: auto;
51
68
  z-index: var(--popover_z-index, 100);
52
- min-width: 12rem;
53
- max-width: var(--popover_max-width, 20rem);
54
- max-height: var(--popover_max-height, 80dvh);
69
+ min-inline-size: 12rem;
70
+ max-inline-size: var(--popover_max-width, 20rem);
71
+ max-block-size: var(--popover_max-height, 80dvh);
55
72
  padding: var(--bds-space_m);
56
73
  border: var(--popover_border, none);
57
74
  --bdc_color: currentcolor;
@@ -72,86 +89,94 @@ export class BdsPopover extends LitElement {
72
89
  .panel[data-placement='bottom'] {
73
90
  top: anchor(bottom);
74
91
  left: anchor(left);
75
- margin-top: var(--bds-space_xs, 8px);
76
- position-try-fallbacks: --bds-popover-top, --bds-popover-right, --bds-popover-left;
92
+ margin-block-start: var(--bds-space_xs, 8px);
93
+ position-try-fallbacks: --popover-top, --popover-right, --popover-left;
77
94
  }
78
95
 
79
96
  .panel[data-placement='top'] {
80
97
  bottom: anchor(top);
81
98
  left: anchor(left);
82
- margin-bottom: var(--bds-space_xs, 8px);
83
- position-try-fallbacks: --bds-popover-bottom, --bds-popover-right, --bds-popover-left;
99
+ margin-block-end: var(--bds-space_xs, 8px);
100
+ position-try-fallbacks: --popover-bottom, --popover-right, --popover-left;
84
101
  }
85
102
 
86
103
  .panel[data-placement='right'] {
87
104
  top: anchor(top);
88
105
  left: anchor(right);
89
- margin-left: var(--bds-space_xs, 8px);
90
- position-try-fallbacks: --bds-popover-left, --bds-popover-bottom, --bds-popover-top;
106
+ margin-inline-start: var(--bds-space_xs, 8px);
107
+ position-try-fallbacks: --popover-left, --popover-bottom, --popover-top;
91
108
  }
92
109
 
93
110
  .panel[data-placement='left'] {
94
111
  top: anchor(top);
95
112
  right: anchor(left);
96
- margin-right: var(--bds-space_xs, 8px);
97
- position-try-fallbacks: --bds-popover-right, --bds-popover-bottom, --bds-popover-top;
113
+ margin-inline-end: var(--bds-space_xs, 8px);
114
+ position-try-fallbacks: --popover-right, --popover-bottom, --popover-top;
98
115
  }
99
116
 
100
117
  /* Fallback placements */
101
118
 
102
- @position-try --bds-popover-bottom {
119
+ @position-try --popover-bottom {
103
120
  top: anchor(bottom);
104
121
  right: unset;
105
122
  bottom: unset;
106
123
  left: anchor(left);
107
124
  margin: 0;
108
- margin-top: var(--bds-space_xs, 8px);
125
+ margin-block-start: var(--bds-space_xs, 8px);
109
126
  }
110
127
 
111
- @position-try --bds-popover-top {
128
+ @position-try --popover-top {
112
129
  top: unset;
113
130
  right: unset;
114
131
  bottom: anchor(top);
115
132
  left: anchor(left);
116
133
  margin: 0;
117
- margin-bottom: var(--bds-space_xs, 8px);
134
+ margin-block-end: var(--bds-space_xs, 8px);
118
135
  }
119
136
 
120
- @position-try --bds-popover-right {
137
+ @position-try --popover-right {
121
138
  top: anchor(top);
122
139
  right: unset;
123
140
  bottom: unset;
124
141
  left: anchor(right);
125
142
  margin: 0;
126
- margin-left: var(--bds-space_xs, 8px);
143
+ margin-inline-start: var(--bds-space_xs, 8px);
127
144
  }
128
145
 
129
- @position-try --bds-popover-left {
146
+ @position-try --popover-left {
130
147
  top: anchor(top);
131
148
  right: anchor(left);
132
149
  bottom: unset;
133
150
  left: unset;
134
151
  margin: 0;
135
- margin-right: var(--bds-space_xs, 8px);
152
+ margin-inline-end: var(--bds-space_xs, 8px);
136
153
  }
137
154
  `;
138
155
 
139
156
  static properties = {
140
157
  placement: { type: String, reflect: true },
141
158
  open: { type: Boolean, reflect: true },
159
+ ariaLabel: { type: String, attribute: 'aria-label' },
142
160
  };
143
161
 
144
162
  declare placement: PopoverPlacement;
145
163
  declare open: boolean;
164
+ declare ariaLabel: string | null;
146
165
 
147
166
  private _anchorName: string;
167
+ private _panelId: string;
168
+ private _triggerEl: HTMLElement | null = null;
148
169
 
149
170
  constructor() {
150
171
  super();
151
172
  this.placement = 'bottom';
152
173
  this.open = false;
174
+ this.ariaLabel = null;
153
175
  const uid = Math.random().toString(36).slice(2, 8);
154
- this._anchorName = `--bds-popover-${uid}`;
176
+ // Non-`--bds-` prefixed — these are internal coordination idents, not
177
+ // foundation-owned tokens, so they must not squat the `--bds-` namespace.
178
+ this._anchorName = `--popover-${uid}`;
179
+ this._panelId = `bds-popover-panel-${uid}`;
155
180
  }
156
181
 
157
182
  connectedCallback() {
@@ -159,7 +184,7 @@ export class BdsPopover extends LitElement {
159
184
  // Inject the unique anchor-name as a CSS custom property so both
160
185
  // `.wrapper` (anchor-name) and `.panel` (position-anchor) reference
161
186
  // the same value without hard-coding it in the shared static styles.
162
- this.style.setProperty('--bds-popover-anchor', this._anchorName);
187
+ this.style.setProperty('--popover-anchor', this._anchorName);
163
188
  document.addEventListener('keydown', this._onKeydown);
164
189
  document.addEventListener('mousedown', this._onOutsideClick);
165
190
  // Invoker Commands API — host is in light DOM so commandfor can reference its id.
@@ -199,25 +224,51 @@ export class BdsPopover extends LitElement {
199
224
  private _open() {
200
225
  if (this.open) return;
201
226
  this.open = true;
227
+ this._triggerEl?.setAttribute('aria-expanded', 'true');
202
228
  this.dispatchEvent(new CustomEvent('bds-open', { bubbles: true, composed: true }));
203
229
  }
204
230
 
205
231
  private _close() {
206
232
  if (!this.open) return;
207
233
  this.open = false;
234
+ this._triggerEl?.setAttribute('aria-expanded', 'false');
208
235
  this.dispatchEvent(new CustomEvent('bds-close', { bubbles: true, composed: true }));
236
+ // Restore focus to the trigger only if it was inside this popover (panel
237
+ // content or the trigger itself) — an outside click that closes the
238
+ // panel has already moved focus elsewhere and should not be overridden.
239
+ if (this.contains(document.activeElement)) {
240
+ this._triggerEl?.focus();
241
+ }
242
+ }
243
+
244
+ // Track the slotted trigger so aria-expanded/haspopup/controls can be kept
245
+ // in sync and focus can be restored on close (mirrors the React
246
+ // cloneElement wiring and bds-dropdown-menu's trigger-tracking pattern).
247
+ private _onTriggerSlotChange(e: Event) {
248
+ const slot = e.target as HTMLSlotElement;
249
+ this._triggerEl = (slot.assignedElements()[0] as HTMLElement) ?? null;
250
+ if (this._triggerEl) {
251
+ this._triggerEl.setAttribute('aria-haspopup', 'true');
252
+ this._triggerEl.setAttribute('aria-controls', this._panelId);
253
+ this._triggerEl.setAttribute('aria-expanded', String(this.open));
254
+ }
209
255
  }
210
256
 
211
257
  render() {
212
258
  return html`
213
259
  <span class="wrapper">
214
- <slot name="trigger" @click=${this._toggle}></slot>
260
+ <slot
261
+ name="trigger"
262
+ @click=${this._toggle}
263
+ @slotchange=${this._onTriggerSlotChange}
264
+ ></slot>
215
265
  </span>
216
266
  <div
217
267
  class="panel ${this.open ? 'open' : ''}"
218
268
  data-placement=${this.placement}
219
- role="region"
220
- aria-label="Popover"
269
+ id=${this._panelId}
270
+ role=${this.ariaLabel ? 'region' : nothing}
271
+ aria-label=${this.ariaLabel ?? nothing}
221
272
  >
222
273
  <slot></slot>
223
274
  </div>
@@ -39,4 +39,22 @@ describe('bds-skip-link', () => {
39
39
  expect(el.textContent?.trim()).toBe('Go to main');
40
40
  cleanup(el);
41
41
  });
42
+
43
+ it('uses a themeable z-index token with a fallback instead of a hardcoded value', () => {
44
+ const cssText = BdsSkipLink.styles.cssText;
45
+ expect(cssText).toContain('z-index: var(--skip-link_z-index, var(--bds-z-index_xl))');
46
+ expect(cssText).not.toContain('z-index: 9999');
47
+ });
48
+
49
+ it('exposes the --skip-link_border hook and the bdc inset focus-border chain', () => {
50
+ const cssText = BdsSkipLink.styles.cssText;
51
+ expect(cssText).toContain('border: var(--skip-link_border, none)');
52
+ expect(cssText).toMatch(/box-shadow:\s*inset 0 0 0 var\(--bdc-outline_width\) var\(--bdc_color\)/);
53
+ expect(cssText).toContain('var(--skip-link_shadow, var(--bdc-outline_shadow))');
54
+ });
55
+
56
+ it('guards the slide-in transition with prefers-reduced-motion', () => {
57
+ const cssText = BdsSkipLink.styles.cssText;
58
+ expect(cssText).toMatch(/@media \(prefers-reduced-motion: reduce\)\s*{\s*\.skip-link\s*{\s*transition:\s*none;/);
59
+ });
42
60
  });
@@ -17,24 +17,39 @@ import { LitElement, css, html } from 'lit';
17
17
  */
18
18
  export class BdsSkipLink 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: block;
22
32
  }
23
33
 
24
34
  .skip-link {
25
35
  position: absolute;
26
- inset-block-start: var(--bds-space_s);
27
- inset-inline-start: var(--bds-space_s);
28
- z-index: 9999;
29
- padding: var(--bds-space_xs) var(--bds-space_m);
36
+ inset-block-start: var(--skip-link_inset, var(--bds-space_s));
37
+ inset-inline-start: var(--skip-link_inset, var(--bds-space_s));
38
+ z-index: var(--skip-link_z-index, var(--bds-z-index_xl));
39
+ padding: var(--skip-link_padding, var(--bds-space_xs) var(--bds-space_m));
30
40
  background-color: var(--bds-color_bg);
31
41
  color: var(--bds-color_on-bg);
32
- border-radius: var(--bds-border_radius--s);
42
+ border-radius: var(--skip-link_radius, var(--bds-border_radius--s));
33
43
  font-weight: var(--bds-font_weight--semibold);
34
- font-size: var(--bds-font_size--body);
44
+ font-size: var(--skip-link_font-size, var(--bds-font_size--body));
35
45
  text-decoration: none;
36
- box-shadow: var(--bds-shadow_m);
37
- transform: translateY(calc(-100% - var(--bds-space_s)));
46
+
47
+ --bdc_color: var(--color_focus, var(--bds-color_interactive));
48
+
49
+ border: var(--skip-link_border, none);
50
+ box-shadow: inset 0 0 0 var(--bdc-outline_width) var(--bdc_color),
51
+ var(--skip-link_shadow, var(--bdc-outline_shadow));
52
+ transform: translateY(calc(-100% - var(--skip-link_inset, var(--bds-space_s))));
38
53
  transition: transform var(--bds-animation_transition-duration) var(--bds-animation_easing);
39
54
  }
40
55
 
@@ -43,6 +58,12 @@ export class BdsSkipLink extends LitElement {
43
58
  outline: var(--bds-outline_default);
44
59
  outline-offset: var(--bds-outline_offset);
45
60
  }
61
+
62
+ @media (prefers-reduced-motion: reduce) {
63
+ .skip-link {
64
+ transition: none;
65
+ }
66
+ }
46
67
  `;
47
68
 
48
69
  static properties = {
@@ -14,6 +14,16 @@ import { LitElement, css, html } from 'lit';
14
14
  */
15
15
  export class BdsTabPanel extends LitElement {
16
16
  static styles = css`
17
+ /* Shadow DOM does not inherit the global box-sizing reset, so set it
18
+ here; otherwise elements with an explicit size + padding size as
19
+ content-box and layouts drift from the React (light-DOM) versions. */
20
+ :host,
21
+ *,
22
+ *::before,
23
+ *::after {
24
+ box-sizing: border-box;
25
+ }
26
+
17
27
  :host {
18
28
  display: block;
19
29
  padding-block-start: var(--bds-space_m);
@@ -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