@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
  const FOCUSABLE = 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])';
4
4
 
@@ -13,6 +13,7 @@ export type DrawerSide = 'left' | 'right';
13
13
  * Attributes:
14
14
  * open — boolean; controlled open state
15
15
  * side — "left" | "right" (default: "right")
16
+ * aria-label — optional; overrides the default accessible name (the title slot)
16
17
  *
17
18
  * Slots:
18
19
  * title — drawer title text
@@ -27,10 +28,20 @@ export type DrawerSide = 'left' | 'right';
27
28
  * <span slot="title">Settings</span>
28
29
  * <p>Drawer content</p>
29
30
  * </bds-drawer>
30
- * <button commandfor="my-drawer" command="show-modal">Open</button>
31
+ * <button commandfor="my-drawer" command="--show-modal">Open</button>
31
32
  */
32
33
  export class BdsDrawer extends LitElement {
33
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
+
34
45
  :host {
35
46
  display: contents;
36
47
  }
@@ -59,6 +70,13 @@ export class BdsDrawer extends LitElement {
59
70
  overlay var(--bds-animation_transition-duration) var(--bds-animation_easing) allow-discrete;
60
71
  }
61
72
 
73
+ /* Closed native <dialog> must be display:none — the flex layout above would
74
+ otherwise keep it rendered (off-screen, focusable, causing overflow). The
75
+ display/overlay allow-discrete transitions above animate the none↔flex. */
76
+ .drawer:not([open]) {
77
+ display: none;
78
+ }
79
+
62
80
  :host([side='left']) .drawer {
63
81
  inset-inline: 0 auto;
64
82
  translate: -100% 0;
@@ -84,8 +102,8 @@ export class BdsDrawer extends LitElement {
84
102
  opacity: 0;
85
103
  transition:
86
104
  opacity var(--bds-animation_transition-duration) var(--bds-animation_easing),
87
- display var(--bds-animation_transition-duration) allow-discrete,
88
- overlay var(--bds-animation_transition-duration) allow-discrete;
105
+ display var(--bds-animation_transition-duration) var(--bds-animation_easing) allow-discrete,
106
+ overlay var(--bds-animation_transition-duration) var(--bds-animation_easing) allow-discrete;
89
107
  }
90
108
 
91
109
  .drawer[open]::backdrop {
@@ -117,8 +135,8 @@ export class BdsDrawer extends LitElement {
117
135
  display: flex;
118
136
  align-items: center;
119
137
  justify-content: center;
120
- inline-size: 2rem;
121
- block-size: 2rem;
138
+ inline-size: 2.75rem;
139
+ block-size: 2.75rem;
122
140
  border-radius: var(--drawer_close-radius, var(--bds-border_radius--circle));
123
141
  cursor: pointer;
124
142
  transition: var(--bds-animation_transition);
@@ -159,10 +177,12 @@ export class BdsDrawer extends LitElement {
159
177
  static properties = {
160
178
  open: { type: Boolean, reflect: true },
161
179
  side: { type: String, reflect: true },
180
+ ariaLabel: { type: String, attribute: 'aria-label' },
162
181
  };
163
182
 
164
183
  declare open: boolean;
165
184
  declare side: DrawerSide;
185
+ declare ariaLabel: string | null;
166
186
 
167
187
  private _triggerEl: Element | null = null;
168
188
 
@@ -170,6 +190,7 @@ export class BdsDrawer extends LitElement {
170
190
  super();
171
191
  this.open = false;
172
192
  this.side = 'right';
193
+ this.ariaLabel = null;
173
194
  }
174
195
 
175
196
  connectedCallback() {
@@ -180,6 +201,7 @@ export class BdsDrawer extends LitElement {
180
201
  disconnectedCallback() {
181
202
  super.disconnectedCallback();
182
203
  this.removeEventListener('command', this._onCommand);
204
+ if (this.open) document.body.style.overflow = '';
183
205
  }
184
206
 
185
207
  updated(changed: Map<string, unknown>) {
@@ -206,8 +228,8 @@ export class BdsDrawer extends LitElement {
206
228
 
207
229
  private _onCommand = (e: Event) => {
208
230
  const command = (e as CommandEvent).command;
209
- if (command === 'show-modal') this._openDrawer();
210
- else if (command === 'close') this._closeDrawer();
231
+ if (command === '--show-modal') this._openDrawer();
232
+ else if (command === '--close') this._closeDrawer();
211
233
  };
212
234
 
213
235
  private _openDrawer() {
@@ -223,14 +245,12 @@ export class BdsDrawer extends LitElement {
223
245
  this.dispatchEvent(new CustomEvent('bds-close', { bubbles: true, composed: true }));
224
246
  }
225
247
 
248
+ // Close on backdrop click. The dialog element's own box is only the visible
249
+ // panel — clicking the ::backdrop dispatches with e.target === the dialog
250
+ // itself, so this correctly ignores clicks (including keyboard-activated
251
+ // synthetic clicks at 0,0) on controls inside the panel.
226
252
  private _handleBackdropClick(e: MouseEvent) {
227
- const dialog = this._dialog;
228
- if (!dialog) return;
229
- const rect = dialog.getBoundingClientRect();
230
- const outside =
231
- e.clientX < rect.left || e.clientX > rect.right ||
232
- e.clientY < rect.top || e.clientY > rect.bottom;
233
- if (outside) this._closeDrawer();
253
+ if (e.target === this._dialog) this._closeDrawer();
234
254
  }
235
255
 
236
256
  private _handleCancel(e: Event) {
@@ -243,13 +263,24 @@ export class BdsDrawer extends LitElement {
243
263
  const dialog = this._dialog;
244
264
  if (!dialog) return;
245
265
  const focusable = Array.from(dialog.querySelectorAll<HTMLElement>(FOCUSABLE));
246
- if (focusable.length === 0) return;
247
- const first = focusable[0];
248
- const last = focusable[focusable.length - 1];
266
+ // Also include slotted elements from light DOM via the title + default slots
267
+ const slots = Array.from(dialog.querySelectorAll<HTMLSlotElement>('slot'));
268
+ const slottedFocusable = slots.flatMap(slot =>
269
+ slot.assignedElements({ flatten: true })
270
+ .flatMap(el => [
271
+ ...(el.matches(FOCUSABLE) ? [el as HTMLElement] : []),
272
+ ...Array.from(el.querySelectorAll<HTMLElement>(FOCUSABLE)),
273
+ ]),
274
+ );
275
+ const all = [...focusable, ...slottedFocusable];
276
+ if (all.length === 0) return;
277
+ const first = all[0];
278
+ const last = all[all.length - 1];
279
+ const active = this.shadowRoot?.activeElement ?? document.activeElement;
249
280
  if (e.shiftKey) {
250
- if (document.activeElement === first) { e.preventDefault(); last.focus(); }
281
+ if (active === first) { e.preventDefault(); last.focus(); }
251
282
  } else {
252
- if (document.activeElement === last) { e.preventDefault(); first.focus(); }
283
+ if (active === last) { e.preventDefault(); first.focus(); }
253
284
  }
254
285
  }
255
286
 
@@ -258,12 +289,14 @@ export class BdsDrawer extends LitElement {
258
289
  <dialog
259
290
  class="drawer"
260
291
  aria-modal="true"
292
+ aria-label=${this.ariaLabel ?? nothing}
293
+ aria-labelledby=${this.ariaLabel ? nothing : 'title'}
261
294
  @click=${this._handleBackdropClick}
262
295
  @cancel=${this._handleCancel}
263
296
  @keydown=${this._handleKeydown}
264
297
  >
265
298
  <div class="header">
266
- <span class="title"><slot name="title"></slot></span>
299
+ <span class="title" id="title"><slot name="title"></slot></span>
267
300
  <button
268
301
  type="button"
269
302
  class="close-button"
@@ -19,6 +19,16 @@ import { LitElement, css, html } from 'lit';
19
19
  */
20
20
  export class BdsDropdownMenuItem extends LitElement {
21
21
  static styles = css`
22
+ /* Shadow DOM does not inherit the global box-sizing reset, so set it
23
+ here; otherwise elements with an explicit size + padding size as
24
+ content-box and layouts drift from the React (light-DOM) versions. */
25
+ :host,
26
+ *,
27
+ *::before,
28
+ *::after {
29
+ box-sizing: border-box;
30
+ }
31
+
22
32
  :host {
23
33
  display: block;
24
34
  }
@@ -51,7 +61,8 @@ export class BdsDropdownMenuItem extends LitElement {
51
61
 
52
62
  @media (hover: hover) and (pointer: fine) {
53
63
  .item:hover {
54
- background-color: var(--bds-color_bg--subtle);
64
+ background-color: var(--dropdown_item-bg--hover, var(--bds-color_bg--subtle));
65
+ color: var(--dropdown_item-color--hover, var(--bds-color_interactive_on-bg));
55
66
  }
56
67
 
57
68
  :host([destructive]) .item:hover {
@@ -66,6 +66,69 @@ describe('bds-dropdown-menu', () => {
66
66
  expect(el.open).toBe(false);
67
67
  cleanup(el);
68
68
  });
69
+
70
+ it('wires aria-haspopup, aria-controls and aria-expanded onto the slotted trigger', async () => {
71
+ const el = await fixture(`
72
+ <bds-dropdown-menu>
73
+ <button slot="trigger" type="button">Options</button>
74
+ <bds-dropdown-menu-item value="edit">Edit</bds-dropdown-menu-item>
75
+ </bds-dropdown-menu>
76
+ `) as BdsDropdownMenu;
77
+ await new Promise(r => requestAnimationFrame(() => r(null)));
78
+ const trigger = el.querySelector('button[slot="trigger"]')!;
79
+ const panel = el.shadowRoot!.querySelector('.panel')!;
80
+
81
+ expect(trigger.getAttribute('aria-haspopup')).toBe('menu');
82
+ expect(trigger.getAttribute('aria-controls')).toBe(panel.id);
83
+ expect(panel.id).not.toBe('');
84
+ expect(trigger.getAttribute('aria-expanded')).toBe('false');
85
+
86
+ cleanup(el);
87
+ });
88
+
89
+ it('keeps aria-expanded on the trigger in sync with open/close', async () => {
90
+ const el = await fixture(`
91
+ <bds-dropdown-menu>
92
+ <button slot="trigger" type="button">Options</button>
93
+ <bds-dropdown-menu-item value="edit">Edit</bds-dropdown-menu-item>
94
+ </bds-dropdown-menu>
95
+ `) as BdsDropdownMenu;
96
+ await new Promise(r => requestAnimationFrame(() => r(null)));
97
+ const trigger = el.querySelector('button[slot="trigger"]')!;
98
+
99
+ el._open();
100
+ expect(trigger.getAttribute('aria-expanded')).toBe('true');
101
+
102
+ el._close();
103
+ expect(trigger.getAttribute('aria-expanded')).toBe('false');
104
+
105
+ cleanup(el);
106
+ });
107
+
108
+ it('focuses the first item on Home and the last item on End', async () => {
109
+ const el = await fixture(`
110
+ <bds-dropdown-menu>
111
+ <button slot="trigger" type="button">Options</button>
112
+ <bds-dropdown-menu-item value="a">A</bds-dropdown-menu-item>
113
+ <bds-dropdown-menu-item value="b">B</bds-dropdown-menu-item>
114
+ <bds-dropdown-menu-item value="c">C</bds-dropdown-menu-item>
115
+ </bds-dropdown-menu>
116
+ `) as BdsDropdownMenu;
117
+ const items = [...el.querySelectorAll('bds-dropdown-menu-item')] as BdsDropdownMenuItem[];
118
+ el._open();
119
+ await Promise.all(items.map(item => item.updateComplete));
120
+
121
+ const buttons = items.map(item => item.shadowRoot!.querySelector<HTMLButtonElement>('button')!);
122
+ const focusSpies = buttons.map(btn => vi.spyOn(btn, 'focus'));
123
+
124
+ el.dispatchEvent(new KeyboardEvent('keydown', { key: 'End', bubbles: true }));
125
+ expect(focusSpies[2]).toHaveBeenCalled();
126
+
127
+ el.dispatchEvent(new KeyboardEvent('keydown', { key: 'Home', bubbles: true }));
128
+ expect(focusSpies[0]).toHaveBeenCalled();
129
+
130
+ cleanup(el);
131
+ });
69
132
  });
70
133
 
71
134
  describe('bds-dropdown-menu-item', () => {
@@ -6,9 +6,12 @@ export type DropdownMenuPlacement = 'bottom-start' | 'bottom-end' | 'top-start'
6
6
  /**
7
7
  * `<bds-dropdown-menu>` — anchored dropdown menu with keyboard navigation.
8
8
  *
9
- * Uses the native Popover API for the floating panel (light-dismiss, top-layer).
10
- * The trigger slot element controls open/close. The component handles keyboard
11
- * navigation (Arrow keys, Escape, Tab) and focus management.
9
+ * The panel is an absolutely-positioned element inside the shadow root (not
10
+ * the native Popover API / top layer) it can be clipped by an ancestor's
11
+ * `overflow` or stacking context. Light-dismiss is implemented via a
12
+ * document-level `click` listener. The trigger slot element controls
13
+ * open/close. The component handles keyboard navigation (Arrow keys, Home,
14
+ * End, Escape, Tab) and focus management.
12
15
  *
13
16
  * Attributes:
14
17
  * open — controls open/closed state (reflected)
@@ -31,6 +34,16 @@ export type DropdownMenuPlacement = 'bottom-start' | 'bottom-end' | 'top-start'
31
34
  */
32
35
  export class BdsDropdownMenu extends LitElement {
33
36
  static styles = css`
37
+ /* Shadow DOM does not inherit the global box-sizing reset, so set it
38
+ here; otherwise elements with an explicit size + padding size as
39
+ content-box and layouts drift from the React (light-DOM) versions. */
40
+ :host,
41
+ *,
42
+ *::before,
43
+ *::after {
44
+ box-sizing: border-box;
45
+ }
46
+
34
47
  :host {
35
48
  display: inline-block;
36
49
  position: relative;
@@ -41,11 +54,17 @@ export class BdsDropdownMenu extends LitElement {
41
54
  inset-block-start: calc(100% + var(--bds-space_xxs));
42
55
  inset-inline-start: 0;
43
56
  min-inline-size: 10rem;
44
- background-color: var(--bds-color_bg);
45
- border-radius: var(--bds-border_radius--s);
46
- box-shadow: var(--bds-shadow_m);
57
+ border: var(--dropdown_border, none);
58
+ --bdc_color: currentcolor;
59
+ --bdc-outline_radius: var(--bds-border_radius--s);
60
+
61
+ border-radius: var(--dropdown_radius, var(--bdc-outline_radius));
62
+ background-color: var(--dropdown_color, var(--bds-color_bg));
63
+ color: var(--dropdown_on-color, var(--bds-color_on-bg));
64
+ box-shadow: inset 0 0 0 var(--bdc-outline_width) var(--bdc_color),
65
+ var(--dropdown_shadow, var(--bds-shadow_m));
47
66
  padding: var(--bds-space_xxs);
48
- z-index: var(--bds-z-index_dropdown, 200);
67
+ z-index: var(--bds-z-index_dropdown);
49
68
  display: none;
50
69
  flex-direction: column;
51
70
  }
@@ -81,6 +100,13 @@ export class BdsDropdownMenu extends LitElement {
81
100
  declare open: boolean;
82
101
  declare placement: DropdownMenuPlacement;
83
102
 
103
+ // Stable id for aria-controls wiring from the slotted trigger to the panel
104
+ private readonly _uid = Math.random().toString(36).slice(2, 8);
105
+
106
+ private get _panelId(): string {
107
+ return `bds-dropdown-panel-${this._uid}`;
108
+ }
109
+
84
110
  constructor() {
85
111
  super();
86
112
  this.open = false;
@@ -115,6 +141,7 @@ export class BdsDropdownMenu extends LitElement {
115
141
  _open() {
116
142
  if (this.open) return;
117
143
  this.open = true;
144
+ this._trigger?.setAttribute('aria-expanded', 'true');
118
145
  this.dispatchEvent(new CustomEvent('bds-open', { bubbles: true, composed: true }));
119
146
  // Focus first item after render
120
147
  this.updateComplete.then(() => {
@@ -125,6 +152,7 @@ export class BdsDropdownMenu extends LitElement {
125
152
  _close() {
126
153
  if (!this.open) return;
127
154
  this.open = false;
155
+ this._trigger?.setAttribute('aria-expanded', 'false');
128
156
  this.dispatchEvent(new CustomEvent('bds-close', { bubbles: true, composed: true }));
129
157
  this._trigger?.focus();
130
158
  }
@@ -160,6 +188,12 @@ export class BdsDropdownMenu extends LitElement {
160
188
  e.preventDefault();
161
189
  const prev = (focused - 1 + items.length) % items.length;
162
190
  items[prev]?.shadowRoot?.querySelector<HTMLElement>('button')?.focus();
191
+ } else if (e.key === 'Home') {
192
+ e.preventDefault();
193
+ items[0]?.shadowRoot?.querySelector<HTMLElement>('button')?.focus();
194
+ } else if (e.key === 'End') {
195
+ e.preventDefault();
196
+ items[items.length - 1]?.shadowRoot?.querySelector<HTMLElement>('button')?.focus();
163
197
  } else if (e.key === 'Tab') {
164
198
  this._close();
165
199
  }
@@ -174,6 +208,9 @@ export class BdsDropdownMenu extends LitElement {
174
208
  if (trigger) {
175
209
  trigger.removeEventListener('click', this._handleTriggerClick);
176
210
  trigger.addEventListener('click', this._handleTriggerClick);
211
+ trigger.setAttribute('aria-haspopup', 'menu');
212
+ trigger.setAttribute('aria-controls', this._panelId);
213
+ trigger.setAttribute('aria-expanded', String(this.open));
177
214
  }
178
215
  }
179
216
 
@@ -181,6 +218,7 @@ export class BdsDropdownMenu extends LitElement {
181
218
  return html`
182
219
  <slot name="trigger" @slotchange=${this._onTriggerSlotChange}></slot>
183
220
  <div
221
+ id=${this._panelId}
184
222
  class="panel"
185
223
  role="menu"
186
224
  aria-hidden=${!this.open ? 'true' : 'false'}
@@ -101,19 +101,93 @@ describe('bds-popover', () => {
101
101
 
102
102
  it('injects a unique anchor-name CSS custom property on :host', async () => {
103
103
  const el = await fixture('<bds-popover><button slot="trigger">Open</button></bds-popover>');
104
- const anchorValue = el.style.getPropertyValue('--bds-popover-anchor');
105
- expect(anchorValue).toMatch(/^--bds-popover-[a-z0-9]+$/);
104
+ const anchorValue = el.style.getPropertyValue('--popover-anchor');
105
+ expect(anchorValue).toMatch(/^--popover-[a-z0-9]+$/);
106
106
  cleanup(el);
107
107
  });
108
108
 
109
- it('panel has role="region" and aria-label="Popover"', async () => {
109
+ it('panel omits role/aria-label by default (no aria-label attribute)', async () => {
110
110
  const el = await fixture('<bds-popover><button slot="trigger">Open</button></bds-popover>');
111
111
  const panel = el.shadowRoot!.querySelector('.panel');
112
+ expect(panel!.hasAttribute('role')).toBe(false);
113
+ expect(panel!.hasAttribute('aria-label')).toBe(false);
114
+ cleanup(el);
115
+ });
116
+
117
+ it('forwards host aria-label to the panel and sets role="region"', async () => {
118
+ const el = await fixture(
119
+ '<bds-popover aria-label="Notifications"><button slot="trigger">Open</button></bds-popover>',
120
+ );
121
+ const panel = el.shadowRoot!.querySelector('.panel');
112
122
  expect(panel!.getAttribute('role')).toBe('region');
113
- expect(panel!.getAttribute('aria-label')).toBe('Popover');
123
+ expect(panel!.getAttribute('aria-label')).toBe('Notifications');
114
124
  cleanup(el);
115
125
  });
116
126
 
127
+ describe('trigger ARIA wiring', () => {
128
+ it('sets aria-haspopup and aria-controls on the slotted trigger', async () => {
129
+ const el = await fixture('<bds-popover><button slot="trigger">Open</button></bds-popover>');
130
+ await new Promise(r => requestAnimationFrame(() => r(null)));
131
+ const trigger = el.querySelector('button')!;
132
+ expect(trigger.getAttribute('aria-haspopup')).toBe('true');
133
+ expect(trigger.getAttribute('aria-controls')).toBeTruthy();
134
+ const panel = el.shadowRoot!.querySelector('.panel')!;
135
+ expect(trigger.getAttribute('aria-controls')).toBe(panel.id);
136
+ cleanup(el);
137
+ });
138
+
139
+ it('sets aria-expanded="false" on the trigger by default', async () => {
140
+ const el = await fixture('<bds-popover><button slot="trigger">Open</button></bds-popover>');
141
+ await new Promise(r => requestAnimationFrame(() => r(null)));
142
+ const trigger = el.querySelector('button')!;
143
+ expect(trigger.getAttribute('aria-expanded')).toBe('false');
144
+ cleanup(el);
145
+ });
146
+
147
+ it('flips the trigger aria-expanded to "true" when opened', async () => {
148
+ const el = await fixture('<bds-popover><button slot="trigger">Open</button></bds-popover>') as BdsPopover;
149
+ await new Promise(r => requestAnimationFrame(() => r(null)));
150
+ const trigger = el.querySelector('button')!;
151
+ el.shadowRoot!.querySelector('slot[name="trigger"]')!
152
+ .dispatchEvent(new MouseEvent('click', { bubbles: true, composed: true }));
153
+ await el.updateComplete;
154
+ expect(trigger.getAttribute('aria-expanded')).toBe('true');
155
+ cleanup(el);
156
+ });
157
+ });
158
+
159
+ describe('focus restoration on close', () => {
160
+ it('restores focus to the trigger when Escape closes with focus inside the panel', async () => {
161
+ const el = await fixture(
162
+ '<bds-popover open><button slot="trigger">Open</button></bds-popover>',
163
+ ) as BdsPopover;
164
+ await new Promise(r => requestAnimationFrame(() => r(null)));
165
+ const trigger = el.querySelector('button[slot="trigger"]') as HTMLElement;
166
+ // Focus is inside the popover (on the trigger itself) when Escape fires.
167
+ trigger.focus();
168
+ expect(document.activeElement).toBe(trigger);
169
+ const focusSpy = vi.spyOn(trigger, 'focus');
170
+ document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }));
171
+ await el.updateComplete;
172
+ expect(focusSpy).toHaveBeenCalled();
173
+ cleanup(el);
174
+ });
175
+
176
+ it('does not steal focus when outside click closes the panel', async () => {
177
+ const outside = document.createElement('button');
178
+ document.body.appendChild(outside);
179
+ const el = await fixture('<bds-popover open><button slot="trigger">Open</button></bds-popover>') as BdsPopover;
180
+ await new Promise(r => requestAnimationFrame(() => r(null)));
181
+ outside.focus();
182
+ expect(document.activeElement).toBe(outside);
183
+ document.body.dispatchEvent(new MouseEvent('mousedown', { bubbles: true }));
184
+ await el.updateComplete;
185
+ expect(document.activeElement).toBe(outside);
186
+ cleanup(el);
187
+ outside.remove();
188
+ });
189
+ });
190
+
117
191
  describe('Invoker Commands API (command event on host)', () => {
118
192
  it('opens on --open command', async () => {
119
193
  const el = await fixture('<bds-popover id="p1"><button slot="trigger">T</button></bds-popover>') as BdsPopover;
@@ -165,8 +239,8 @@ describe('bds-popover', () => {
165
239
  it('two instances get different anchor names', async () => {
166
240
  const a = await fixture('<bds-popover><button slot="trigger">A</button></bds-popover>');
167
241
  const b = await fixture('<bds-popover><button slot="trigger">B</button></bds-popover>');
168
- const anchorA = a.style.getPropertyValue('--bds-popover-anchor');
169
- const anchorB = b.style.getPropertyValue('--bds-popover-anchor');
242
+ const anchorA = a.style.getPropertyValue('--popover-anchor');
243
+ const anchorB = b.style.getPropertyValue('--popover-anchor');
170
244
  expect(anchorA).not.toBe(anchorB);
171
245
  cleanup(a);
172
246
  cleanup(b);