@boostdev/design-system-components 2.15.0 → 2.17.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 (299) hide show
  1. package/AGENTS.md +22 -15
  2. package/dist/client.cjs +271 -205
  3. package/dist/client.css +813 -650
  4. package/dist/client.d.cts +19 -4
  5. package/dist/client.d.ts +19 -4
  6. package/dist/client.js +206 -139
  7. package/dist/index.cjs +271 -205
  8. package/dist/index.css +813 -650
  9. package/dist/index.d.cts +19 -4
  10. package/dist/index.d.ts +19 -4
  11. package/dist/index.js +206 -139
  12. package/dist/web-components/chunk-2DHW2WJZ.js +154 -0
  13. package/dist/web-components/{chunk-3WAV6MDN.js → chunk-3FSGP35V.js} +1 -0
  14. package/dist/web-components/{chunk-SYNLFKD3.js → chunk-3LQKFSMR.js} +6 -0
  15. package/dist/web-components/{chunk-KA3VPKMY.js → chunk-4MB2ICSK.js} +1 -0
  16. package/dist/web-components/{chunk-6G22I2CK.js → chunk-5ATTKUCP.js} +33 -3
  17. package/dist/web-components/{chunk-IDSM74LM.js → chunk-6XL5P76D.js} +3 -3
  18. package/dist/web-components/{chunk-P24JYC5V.js → chunk-7VXRMCAL.js} +10 -4
  19. package/dist/web-components/{chunk-CUKQ2L5B.js → chunk-AGI6YQRC.js} +9 -16
  20. package/dist/web-components/chunk-BDRV452N.js +51 -0
  21. package/dist/web-components/{chunk-3AY2YKCM.js → chunk-CKCPV347.js} +1 -0
  22. package/dist/web-components/{chunk-HBLJ4SLY.js → chunk-DD3OUXNG.js} +5 -5
  23. package/dist/web-components/{chunk-RVF7W653.js → chunk-DGOCPKHI.js} +30 -10
  24. package/dist/web-components/{chunk-2OLVQUBU.js → chunk-EYCW7TKB.js} +8 -15
  25. package/dist/web-components/{chunk-VANAKB6D.js → chunk-GPJWLAKU.js} +33 -16
  26. package/dist/web-components/{chunk-VED2DFJ6.js → chunk-GQNQBEYR.js} +8 -15
  27. package/dist/web-components/{chunk-WFVKU4GX.js → chunk-IKAJLROF.js} +49 -4
  28. package/dist/web-components/{chunk-RSZ3BWBK.js → chunk-KSK4RZZQ.js} +30 -7
  29. package/dist/web-components/{chunk-FEDABOR5.js → chunk-LHFUXZ52.js} +7 -15
  30. package/dist/web-components/{chunk-M3ECULRH.js → chunk-RBF7WPLI.js} +10 -8
  31. package/dist/web-components/{chunk-BPYKZVDK.js → chunk-SJLMW2VR.js} +2 -2
  32. package/dist/web-components/chunk-SRKQ6GST.js +40 -0
  33. package/dist/web-components/{chunk-5HUAFCU6.js → chunk-TJV7UIXC.js} +7 -0
  34. package/dist/web-components/{chunk-LDIPCTRN.js → chunk-WWWJCSXN.js} +50 -4
  35. package/dist/web-components/{chunk-J3HVUIUH.js → chunk-XI2U6U26.js} +8 -15
  36. package/dist/web-components/{chunk-JH6LQKLK.js → chunk-XJU7KITO.js} +8 -15
  37. package/dist/web-components/{chunk-JV5QT2OU.js → chunk-YLDQOESI.js} +27 -13
  38. package/dist/web-components/globals.js +1 -1
  39. package/dist/web-components/index.d.ts +1 -0
  40. package/dist/web-components/index.js +35 -30
  41. package/dist/web-components/interaction/bds-dropdown-menu-group.d.ts +41 -0
  42. package/dist/web-components/interaction/bds-dropdown-menu-group.js +7 -0
  43. package/dist/web-components/interaction/bds-dropdown-menu-item.d.ts +14 -1
  44. package/dist/web-components/interaction/bds-dropdown-menu-item.js +1 -1
  45. package/dist/web-components/interaction/bds-dropdown-menu.d.ts +2 -1
  46. package/dist/web-components/interaction/bds-dropdown-menu.js +1 -1
  47. package/dist/web-components/interaction/bds-tab.d.ts +5 -0
  48. package/dist/web-components/interaction/bds-tab.js +1 -1
  49. package/dist/web-components/interaction/bds-tooltip.js +1 -1
  50. package/dist/web-components/interaction/form/bds-checkbox-group.d.ts +6 -0
  51. package/dist/web-components/interaction/form/bds-checkbox-group.js +2 -1
  52. package/dist/web-components/interaction/form/bds-checkbox.js +1 -1
  53. package/dist/web-components/interaction/form/bds-combobox.js +2 -1
  54. package/dist/web-components/interaction/form/bds-form-input.js +2 -1
  55. package/dist/web-components/interaction/form/bds-number-input.js +2 -1
  56. package/dist/web-components/interaction/form/bds-radio-group.d.ts +5 -0
  57. package/dist/web-components/interaction/form/bds-radio-group.js +2 -1
  58. package/dist/web-components/interaction/form/bds-radio.js +1 -1
  59. package/dist/web-components/interaction/form/bds-select.js +2 -1
  60. package/dist/web-components/interaction/form/bds-slider.js +2 -1
  61. package/dist/web-components/interaction/form/bds-switch.js +1 -1
  62. package/dist/web-components/interaction/form/bds-textarea.js +2 -1
  63. package/dist/web-components/ui/bds-alert.d.ts +8 -1
  64. package/dist/web-components/ui/bds-alert.js +1 -1
  65. package/dist/web-components/ui/bds-avatar.d.ts +11 -0
  66. package/dist/web-components/ui/bds-avatar.js +1 -1
  67. package/dist/web-components/ui/bds-badge.js +1 -1
  68. package/dist/web-components/ui/bds-notification-banner.d.ts +14 -1
  69. package/dist/web-components/ui/bds-notification-banner.js +1 -1
  70. package/dist/web-components/ui/bds-rating.js +1 -1
  71. package/dist/web-components/ui/bds-section-header.d.ts +6 -0
  72. package/dist/web-components/ui/bds-section-header.js +1 -1
  73. package/dist/web-components/ui/bds-separator.js +1 -1
  74. package/dist/web-components/ui/bds-table.js +1 -1
  75. package/package.json +6 -2
  76. package/src/components/interaction/DropdownMenu/DropdownMenu.mdx +35 -4
  77. package/src/components/interaction/DropdownMenu/DropdownMenu.module.css +58 -10
  78. package/src/components/interaction/DropdownMenu/DropdownMenu.spec.tsx +114 -1
  79. package/src/components/interaction/DropdownMenu/DropdownMenu.stories.tsx +25 -0
  80. package/src/components/interaction/DropdownMenu/DropdownMenu.tsx +69 -17
  81. package/src/components/interaction/Rating/Rating.mdx +4 -1
  82. package/src/components/interaction/Rating/Rating.module.css +9 -0
  83. package/src/components/interaction/Rating/Rating.spec.tsx +9 -0
  84. package/src/components/interaction/form/Checkbox/Checkbox.module.css +1 -0
  85. package/src/components/interaction/form/Checkbox/Checkbox.spec.tsx +7 -0
  86. package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.mdx +2 -1
  87. package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.module.css +8 -1
  88. package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.spec.tsx +27 -0
  89. package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.tsx +1 -1
  90. package/src/components/interaction/form/Combobox/Combobox.module.css +1 -0
  91. package/src/components/interaction/form/Combobox/Combobox.spec.tsx +7 -0
  92. package/src/components/interaction/form/FormInput/FormInput.mdx +9 -0
  93. package/src/components/interaction/form/FormInput/FormInput.module.css +1 -0
  94. package/src/components/interaction/form/FormInput/FormInput.spec.tsx +7 -0
  95. package/src/components/interaction/form/NumberInput/NumberInput.module.css +1 -0
  96. package/src/components/interaction/form/NumberInput/NumberInput.spec.tsx +7 -0
  97. package/src/components/interaction/form/Radio/Radio.module.css +1 -0
  98. package/src/components/interaction/form/Radio/Radio.spec.tsx +7 -0
  99. package/src/components/interaction/form/RadioGroup/RadioGroup.mdx +2 -1
  100. package/src/components/interaction/form/RadioGroup/RadioGroup.module.css +8 -1
  101. package/src/components/interaction/form/RadioGroup/RadioGroup.spec.tsx +27 -0
  102. package/src/components/interaction/form/RadioGroup/RadioGroup.tsx +1 -1
  103. package/src/components/interaction/form/Select/Select.module.css +1 -0
  104. package/src/components/interaction/form/Select/Select.spec.tsx +7 -0
  105. package/src/components/interaction/form/Switch/Switch.module.css +1 -0
  106. package/src/components/interaction/form/Switch/Switch.spec.tsx +7 -0
  107. package/src/components/interaction/form/Textarea/Textarea.module.css +1 -0
  108. package/src/components/interaction/form/Textarea/Textarea.spec.tsx +7 -0
  109. package/src/components/interaction/form/atoms/Message.module.css +14 -3
  110. package/src/components/interaction/form/atoms/Message.spec.tsx +22 -0
  111. package/src/components/interaction/form/atoms/Message.tsx +5 -0
  112. package/src/components/layout/SectionHeader/SectionHeader.mdx +18 -5
  113. package/src/components/layout/SectionHeader/SectionHeader.module.css +35 -14
  114. package/src/components/layout/SectionHeader/SectionHeader.spec.tsx +44 -0
  115. package/src/components/layout/SectionHeader/SectionHeader.stories.tsx +5 -0
  116. package/src/components/layout/SectionHeader/SectionHeader.tsx +3 -1
  117. package/src/components/ui/Alert/Alert.mdx +12 -1
  118. package/src/components/ui/Alert/Alert.module.css +32 -3
  119. package/src/components/ui/Alert/Alert.spec.tsx +27 -0
  120. package/src/components/ui/Alert/Alert.stories.tsx +20 -0
  121. package/src/components/ui/Alert/Alert.tsx +8 -1
  122. package/src/components/ui/Avatar/Avatar.mdx +22 -2
  123. package/src/components/ui/Avatar/Avatar.module.css +29 -2
  124. package/src/components/ui/Avatar/Avatar.spec.tsx +26 -0
  125. package/src/components/ui/Avatar/Avatar.stories.tsx +23 -0
  126. package/src/components/ui/Avatar/Avatar.tsx +4 -2
  127. package/src/components/ui/Avatar/avatarTone.spec.ts +41 -0
  128. package/src/components/ui/Avatar/avatarTone.ts +22 -0
  129. package/src/components/ui/Badge/Badge.mdx +1 -1
  130. package/src/components/ui/Badge/Badge.module.css +2 -2
  131. package/src/components/ui/Badge/Badge.spec.tsx +8 -0
  132. package/src/components/ui/Collapsible/Collapsible.module.css +1 -2
  133. package/src/components/ui/NotificationBanner/NotificationBanner.mdx +27 -1
  134. package/src/components/ui/NotificationBanner/NotificationBanner.module.css +33 -3
  135. package/src/components/ui/NotificationBanner/NotificationBanner.spec.tsx +35 -0
  136. package/src/components/ui/NotificationBanner/NotificationBanner.stories.tsx +25 -0
  137. package/src/components/ui/NotificationBanner/NotificationBanner.tsx +15 -1
  138. package/src/components/ui/Separator/Separator.mdx +1 -0
  139. package/src/components/ui/Separator/Separator.module.css +6 -0
  140. package/src/components/ui/Separator/Separator.spec.tsx +19 -0
  141. package/src/components/ui/Separator/Separator.stories.tsx +15 -0
  142. package/src/components/ui/Table/Table.mdx +4 -1
  143. package/src/components/ui/Table/Table.module.css +7 -7
  144. package/src/components/ui/Table/Table.spec.tsx +11 -0
  145. package/src/components/ui/Tabs/Tabs.mdx +11 -5
  146. package/src/components/ui/Tabs/Tabs.module.css +23 -5
  147. package/src/components/ui/Tabs/Tabs.spec.tsx +39 -0
  148. package/src/components/ui/Tabs/Tabs.tsx +2 -1
  149. package/src/components/ui/Tabs/getNodeText.spec.tsx +23 -0
  150. package/src/components/ui/Tabs/getNodeText.ts +13 -0
  151. package/src/components/ui/Tooltip/Tooltip.mdx +6 -3
  152. package/src/components/ui/Tooltip/Tooltip.module.css +6 -2
  153. package/src/components/ui/Tooltip/Tooltip.spec.tsx +10 -0
  154. package/src/components/ui/Tooltip/Tooltip.stories.tsx +13 -0
  155. package/src/css/bdc.css +5 -2
  156. package/src/css/bdc.spec.ts +65 -0
  157. package/src/stories/DesignSystem/Borders.mdx +17 -9
  158. package/src/test/token-contract.spec.ts +1 -0
  159. package/src/web-components/globals.ts +10 -4
  160. package/src/web-components/index.ts +1 -0
  161. package/src/web-components/interaction/BdsAccordion.mdx +1 -1
  162. package/src/web-components/interaction/BdsAccordion.stories.tsx +1 -1
  163. package/src/web-components/interaction/BdsButton.mdx +1 -1
  164. package/src/web-components/interaction/BdsButton.stories.tsx +1 -1
  165. package/src/web-components/interaction/BdsCollapsible.mdx +1 -1
  166. package/src/web-components/interaction/BdsCollapsible.stories.tsx +1 -1
  167. package/src/web-components/interaction/BdsDialog.mdx +1 -1
  168. package/src/web-components/interaction/BdsDialog.stories.tsx +1 -1
  169. package/src/web-components/interaction/BdsDrawer.mdx +1 -1
  170. package/src/web-components/interaction/BdsDrawer.stories.tsx +1 -1
  171. package/src/web-components/interaction/BdsDropdownMenu.mdx +62 -6
  172. package/src/web-components/interaction/BdsDropdownMenu.stories.tsx +32 -7
  173. package/src/web-components/interaction/BdsPopover.mdx +1 -1
  174. package/src/web-components/interaction/BdsPopover.stories.tsx +1 -1
  175. package/src/web-components/interaction/BdsSkipLink.mdx +1 -1
  176. package/src/web-components/interaction/BdsSkipLink.stories.tsx +1 -1
  177. package/src/web-components/interaction/BdsTabs.mdx +10 -1
  178. package/src/web-components/interaction/BdsTabs.stories.tsx +1 -1
  179. package/src/web-components/interaction/BdsToastProvider.mdx +1 -1
  180. package/src/web-components/interaction/BdsToastProvider.stories.tsx +1 -1
  181. package/src/web-components/interaction/BdsTooltip.mdx +13 -5
  182. package/src/web-components/interaction/BdsTooltip.stories.tsx +12 -12
  183. package/src/web-components/interaction/bds-dropdown-menu-group.ts +72 -0
  184. package/src/web-components/interaction/bds-dropdown-menu-item.ts +65 -17
  185. package/src/web-components/interaction/bds-dropdown-menu.spec.ts +135 -0
  186. package/src/web-components/interaction/bds-dropdown-menu.ts +5 -4
  187. package/src/web-components/interaction/bds-tab.spec.ts +34 -2
  188. package/src/web-components/interaction/bds-tab.ts +31 -6
  189. package/src/web-components/interaction/bds-tooltip.spec.ts +16 -0
  190. package/src/web-components/interaction/bds-tooltip.ts +10 -8
  191. package/src/web-components/interaction/form/BdsCheckbox.mdx +5 -1
  192. package/src/web-components/interaction/form/BdsCheckbox.stories.tsx +1 -1
  193. package/src/web-components/interaction/form/BdsCheckboxGroup.mdx +5 -1
  194. package/src/web-components/interaction/form/BdsCheckboxGroup.stories.tsx +1 -1
  195. package/src/web-components/interaction/form/BdsCombobox.mdx +5 -1
  196. package/src/web-components/interaction/form/BdsCombobox.stories.tsx +1 -1
  197. package/src/web-components/interaction/form/BdsFieldGroup.stories.tsx +1 -1
  198. package/src/web-components/interaction/form/BdsFileInput.mdx +1 -1
  199. package/src/web-components/interaction/form/BdsFileInput.stories.tsx +1 -1
  200. package/src/web-components/interaction/form/BdsFormInput.mdx +8 -1
  201. package/src/web-components/interaction/form/BdsFormInput.stories.tsx +1 -1
  202. package/src/web-components/interaction/form/BdsNumberInput.mdx +5 -1
  203. package/src/web-components/interaction/form/BdsNumberInput.stories.tsx +1 -1
  204. package/src/web-components/interaction/form/BdsRadio.mdx +5 -1
  205. package/src/web-components/interaction/form/BdsRadio.stories.tsx +1 -1
  206. package/src/web-components/interaction/form/BdsRadioGroup.mdx +5 -1
  207. package/src/web-components/interaction/form/BdsRadioGroup.stories.tsx +1 -1
  208. package/src/web-components/interaction/form/BdsSegmentedControl.mdx +1 -1
  209. package/src/web-components/interaction/form/BdsSegmentedControl.stories.tsx +1 -1
  210. package/src/web-components/interaction/form/BdsSelect.mdx +5 -1
  211. package/src/web-components/interaction/form/BdsSelect.stories.tsx +1 -1
  212. package/src/web-components/interaction/form/BdsSlider.mdx +5 -1
  213. package/src/web-components/interaction/form/BdsSlider.stories.tsx +1 -1
  214. package/src/web-components/interaction/form/BdsSwitch.mdx +5 -1
  215. package/src/web-components/interaction/form/BdsSwitch.stories.tsx +1 -1
  216. package/src/web-components/interaction/form/BdsTextarea.mdx +5 -1
  217. package/src/web-components/interaction/form/BdsTextarea.stories.tsx +1 -1
  218. package/src/web-components/interaction/form/bds-checkbox-group.spec.ts +32 -3
  219. package/src/web-components/interaction/form/bds-checkbox-group.ts +33 -17
  220. package/src/web-components/interaction/form/bds-checkbox.ts +1 -0
  221. package/src/web-components/interaction/form/bds-combobox.ts +6 -16
  222. package/src/web-components/interaction/form/bds-form-input.ts +6 -16
  223. package/src/web-components/interaction/form/bds-number-input.ts +6 -16
  224. package/src/web-components/interaction/form/bds-radio-group.spec.ts +32 -3
  225. package/src/web-components/interaction/form/bds-radio-group.ts +26 -14
  226. package/src/web-components/interaction/form/bds-radio.ts +1 -0
  227. package/src/web-components/interaction/form/bds-select.ts +6 -16
  228. package/src/web-components/interaction/form/bds-slider.ts +5 -16
  229. package/src/web-components/interaction/form/bds-switch.ts +1 -0
  230. package/src/web-components/interaction/form/bds-textarea.ts +6 -16
  231. package/src/web-components/interaction/form/field-message.spec.ts +62 -0
  232. package/src/web-components/interaction/form/field-message.ts +55 -0
  233. package/src/web-components/layout/BdsGrid.mdx +1 -1
  234. package/src/web-components/layout/BdsGrid.stories.tsx +1 -1
  235. package/src/web-components/layout/BdsGridItem.mdx +1 -1
  236. package/src/web-components/layout/BdsGridItem.stories.tsx +1 -1
  237. package/src/web-components/ui/BdsAlert.mdx +20 -1
  238. package/src/web-components/ui/BdsAlert.stories.tsx +29 -3
  239. package/src/web-components/ui/BdsAvatar.mdx +20 -3
  240. package/src/web-components/ui/BdsAvatar.stories.tsx +25 -2
  241. package/src/web-components/ui/BdsBadge.mdx +2 -1
  242. package/src/web-components/ui/BdsBadge.stories.tsx +1 -1
  243. package/src/web-components/ui/BdsBreadcrumb.mdx +1 -1
  244. package/src/web-components/ui/BdsBreadcrumb.stories.tsx +1 -1
  245. package/src/web-components/ui/BdsButtonContainer.mdx +1 -1
  246. package/src/web-components/ui/BdsButtonContainer.stories.tsx +1 -1
  247. package/src/web-components/ui/BdsCalendar.mdx +1 -1
  248. package/src/web-components/ui/BdsCalendar.stories.tsx +1 -1
  249. package/src/web-components/ui/BdsCalendarRange.mdx +1 -1
  250. package/src/web-components/ui/BdsCalendarRange.stories.tsx +1 -1
  251. package/src/web-components/ui/BdsCard.mdx +1 -1
  252. package/src/web-components/ui/BdsCard.stories.tsx +1 -1
  253. package/src/web-components/ui/BdsCarousel.mdx +1 -1
  254. package/src/web-components/ui/BdsCarousel.stories.tsx +1 -1
  255. package/src/web-components/ui/BdsDescriptionList.mdx +1 -1
  256. package/src/web-components/ui/BdsDescriptionList.stories.tsx +1 -1
  257. package/src/web-components/ui/BdsIconWrapper.mdx +1 -1
  258. package/src/web-components/ui/BdsIconWrapper.stories.tsx +1 -1
  259. package/src/web-components/ui/BdsLink.mdx +1 -1
  260. package/src/web-components/ui/BdsLink.stories.tsx +1 -1
  261. package/src/web-components/ui/BdsLoading.mdx +1 -1
  262. package/src/web-components/ui/BdsLoading.stories.tsx +1 -1
  263. package/src/web-components/ui/BdsNotificationBanner.mdx +11 -2
  264. package/src/web-components/ui/BdsNotificationBanner.stories.tsx +29 -2
  265. package/src/web-components/ui/BdsPagination.mdx +1 -1
  266. package/src/web-components/ui/BdsPagination.stories.tsx +1 -1
  267. package/src/web-components/ui/BdsProgress.mdx +1 -1
  268. package/src/web-components/ui/BdsProgress.stories.tsx +1 -1
  269. package/src/web-components/ui/BdsProgressCircle.mdx +1 -1
  270. package/src/web-components/ui/BdsProgressCircle.stories.tsx +1 -1
  271. package/src/web-components/ui/BdsRating.mdx +5 -2
  272. package/src/web-components/ui/BdsRating.stories.tsx +1 -1
  273. package/src/web-components/ui/BdsSectionHeader.mdx +18 -6
  274. package/src/web-components/ui/BdsSectionHeader.stories.tsx +10 -2
  275. package/src/web-components/ui/BdsSeparator.mdx +2 -1
  276. package/src/web-components/ui/BdsSeparator.stories.tsx +13 -1
  277. package/src/web-components/ui/BdsSkeleton.mdx +1 -1
  278. package/src/web-components/ui/BdsSkeleton.stories.tsx +1 -1
  279. package/src/web-components/ui/BdsTable.mdx +5 -1
  280. package/src/web-components/ui/BdsTable.stories.tsx +1 -1
  281. package/src/web-components/ui/BdsTypography.mdx +1 -1
  282. package/src/web-components/ui/BdsTypography.stories.tsx +1 -1
  283. package/src/web-components/ui/bds-alert.spec.ts +34 -0
  284. package/src/web-components/ui/bds-alert.ts +36 -3
  285. package/src/web-components/ui/bds-avatar.spec.ts +47 -0
  286. package/src/web-components/ui/bds-avatar.ts +36 -3
  287. package/src/web-components/ui/bds-badge.spec.ts +6 -0
  288. package/src/web-components/ui/bds-badge.ts +2 -2
  289. package/src/web-components/ui/bds-notification-banner.spec.ts +52 -0
  290. package/src/web-components/ui/bds-notification-banner.ts +55 -3
  291. package/src/web-components/ui/bds-rating.spec.ts +7 -0
  292. package/src/web-components/ui/bds-rating.ts +6 -0
  293. package/src/web-components/ui/bds-section-header.spec.ts +36 -3
  294. package/src/web-components/ui/bds-section-header.ts +32 -10
  295. package/src/web-components/ui/bds-separator.spec.ts +8 -0
  296. package/src/web-components/ui/bds-separator.ts +7 -0
  297. package/src/web-components/ui/bds-table.spec.ts +11 -0
  298. package/src/web-components/ui/bds-table.ts +5 -5
  299. package/dist/web-components/chunk-QZAIRJ75.js +0 -111
@@ -1,5 +1,7 @@
1
1
  import { render, screen } from '@testing-library/react';
2
2
  import userEvent from '@testing-library/user-event';
3
+ import { readFileSync } from 'node:fs';
4
+ import { resolve } from 'node:path';
3
5
  import { Tooltip } from './Tooltip';
4
6
 
5
7
  describe('Tooltip', () => {
@@ -99,4 +101,12 @@ describe('Tooltip', () => {
99
101
  await user.unhover(tooltip);
100
102
  expect(tooltip).not.toBeVisible();
101
103
  });
104
+
105
+ it('sizes the tooltip to its text and uses the xs radius hook default', () => {
106
+ const css = readFileSync(resolve(process.cwd(), 'src/components/ui/Tooltip/Tooltip.module.css'), 'utf8');
107
+ expect(css).toMatch(/inline-size:\s*max-content;/);
108
+ expect(css).toMatch(/max-inline-size:\s*var\(--tooltip_max-inline-size,\s*20rem\);/);
109
+ expect(css).toContain('var(--tooltip_radius, var(--bds-border_radius--xs))');
110
+ expect(css).toContain('var(--tooltip_padding, var(--bds-space_xxs) var(--bds-space_s))');
111
+ });
102
112
  });
@@ -56,6 +56,19 @@ export const Right: Story = {
56
56
  ),
57
57
  };
58
58
 
59
+ export const LongText: Story = {
60
+ args: {
61
+ content:
62
+ 'Longer explanation that wraps onto a second line once it reaches the maximum width of the tooltip.',
63
+ placement: 'bottom',
64
+ },
65
+ render: args => (
66
+ <Tooltip {...args}>
67
+ <Button>Long tooltip</Button>
68
+ </Tooltip>
69
+ ),
70
+ };
71
+
59
72
  export const AllPlacements: Story = {
60
73
  render: () => (
61
74
  <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: '3rem' }}>
package/src/css/bdc.css CHANGED
@@ -9,6 +9,8 @@
9
9
  * --bdc-outline_* — tokens that directly map to CSS outline sub-properties
10
10
  *
11
11
  * @property declarations must be top-level (not inside @layer).
12
+ * The :root defaults live in boostdev.tokens.semantic so a consumer can override them in
13
+ * boostdev.tokens.override. --bdc-outline_width inherits so a :root value reaches components.
12
14
  * --bdc_color uses inherits: false so each element owns its own colour instance,
13
15
  * enabling per-element transition: --bdc_color for focus/error state animations.
14
16
  * ─────────────────────────────────────────────────────────────────────────────── */
@@ -22,7 +24,7 @@
22
24
 
23
25
  @property --bdc-outline_width {
24
26
  syntax: '<length>';
25
- inherits: false;
27
+ inherits: true;
26
28
  initial-value: 1px;
27
29
  }
28
30
 
@@ -46,7 +48,7 @@
46
48
  initial-value: 0 0 0 0 transparent;
47
49
  }
48
50
 
49
- @layer boostdev.component {
51
+ @layer boostdev.tokens.semantic {
50
52
  :root {
51
53
  /* border: none by default — outline provides the visual edge */
52
54
  --bdc-outline_border: none;
@@ -66,6 +68,7 @@
66
68
 
67
69
  /* Outline geometry */
68
70
  --bdc-outline_width: 1px;
71
+ --bdc-outline_width--error: 2px;
69
72
  --bdc-outline_offset: -1px; /* available for consumer use; bdc borders now use inset box-shadow */
70
73
  --bdc-outline_radius: var(--bds-border_radius--xs);
71
74
  --bdc-outline_radius--l: 1.5em;
@@ -0,0 +1,65 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { resolve } from 'node:path';
3
+ import { describe, expect, it } from 'vitest';
4
+
5
+ const read = (path: string): string => readFileSync(resolve(__dirname, path), 'utf8');
6
+
7
+ const sources = {
8
+ 'bdc.css': read('./bdc.css'),
9
+ 'globals.ts': read('../web-components/globals.ts'),
10
+ } as const;
11
+
12
+ /** Returns the text between the braces of `@layer boostdev.tokens.semantic { ... }`. */
13
+ const semanticLayerBody = (source: string): string | undefined => {
14
+ const start = source.indexOf('@layer boostdev.tokens.semantic');
15
+ if (start === -1) return undefined;
16
+ const open = source.indexOf('{', start);
17
+ const body = [...source.slice(open)].reduce<{ depth: number; end: number }>(
18
+ (acc, ch, i) => {
19
+ if (acc.end !== -1) return acc;
20
+ const depth = acc.depth + (ch === '{' ? 1 : ch === '}' ? -1 : 0);
21
+ return { depth, end: depth === 0 ? i : -1 };
22
+ },
23
+ { depth: 0, end: -1 },
24
+ );
25
+ return source.slice(open + 1, open + body.end);
26
+ };
27
+
28
+ const rootDeclarations = (source: string): string[] =>
29
+ [...(semanticLayerBody(source) ?? '').matchAll(/^\s*(--[\w-]+)\s*:/gm)].map((m) => m[1] ?? '');
30
+
31
+ describe.each(Object.entries(sources))('%s', (_name, source) => {
32
+ it('puts the :root defaults in boostdev.tokens.semantic', () => {
33
+ const body = semanticLayerBody(source);
34
+ expect(body).toBeDefined();
35
+ expect(body).toContain(':root');
36
+ expect(body).toContain('--bdc-color_active:');
37
+ expect(body).toContain('--bdc_color--error:');
38
+ });
39
+
40
+ it('does not put the :root defaults in boostdev.component', () => {
41
+ expect(source).not.toContain('@layer boostdev.component');
42
+ });
43
+
44
+ it('registers --bdc-outline_width as inheriting', () => {
45
+ expect(source).toMatch(/@property --bdc-outline_width\s*\{[^}]*inherits:\s*true/);
46
+ });
47
+
48
+ it('keeps the per-element tokens non-inheriting', () => {
49
+ ['--bdc_color', '--bdc-outline_offset', '--bdc-outline_radius', '--bdc-outline_shadow'].forEach((token) => {
50
+ expect(source).toMatch(new RegExp(`@property ${token}\\s*\\{[^}]*inherits:\\s*false`));
51
+ });
52
+ });
53
+
54
+ it('declares the error outline width', () => {
55
+ expect(source).toContain('--bdc-outline_width--error: 2px;');
56
+ });
57
+ });
58
+
59
+ describe('bdc.css and globals.ts', () => {
60
+ it('declare the same set of :root custom properties', () => {
61
+ expect([...rootDeclarations(sources['globals.ts'])].sort()).toEqual(
62
+ [...rootDeclarations(sources['bdc.css'])].sort(),
63
+ );
64
+ });
65
+ });
@@ -123,23 +123,31 @@ See `src/components/ui/Accordion/Accordion.module.css` for a shipped example of
123
123
 
124
124
  ## Consumer overrides
125
125
 
126
- Override a component's border colour for a specific context by reassigning `--bdc_color`:
126
+ The `:root` defaults of the `bdc` tokens (`--bdc_color--focus`, `--bdc_color--error`, `--bdc-color_active*`, `--bdc-color_on-active*`, `--bdc-outline_width`, `--bdc-outline_width--error`, `--bds-outline_default`, `--bds-outline_offset`) live in `@layer boostdev.tokens.semantic`, so they can be set in `@layer boostdev.tokens.override`:
127
127
 
128
128
  ```css
129
- /* Scoped to a single component instance */
130
- .my-context .my-input {
131
- --bdc_color: var(--bds-color_warning);
132
- }
133
-
134
- /* Override globally via the token layer */
135
129
  @layer boostdev.tokens.override {
136
130
  :root {
137
- --bdc_color: var(--bds-color_green);
131
+ --bdc-color_active: var(--bds-color_green);
132
+ --bdc_color--focus: var(--bds-color_green);
133
+ --bdc-outline_width: 2px;
138
134
  }
139
135
  }
140
136
  ```
141
137
 
142
- To change width or radius independently:
138
+ The `bdc` defaults now share the `boostdev.tokens.semantic` layer with the foundation, so load the component stylesheet after the foundation stylesheet for the solid focus ring to win (the documented import order already does this). `--bdc-outline_radius` is registered with `inherits: false` and set by each component itself, so it cannot be set on `:root`.
139
+
140
+ `--bdc-outline_width` is registered with `inherits: true`, so a value on `:root` or on a wrapper reaches the components inside it.
141
+
142
+ `--bdc_color` is per element by design (`inherits: false`): every component owns its own instance so its state colour can transition. Do not set it on `:root`; that has no effect. Change a component's rest border colour through the component's own hook instead:
143
+
144
+ ```css
145
+ .my-menu {
146
+ --dropdown_border-color: var(--bds-color_warning);
147
+ }
148
+ ```
149
+
150
+ To change width or radius for one element:
143
151
 
144
152
  ```css
145
153
  .my-card {
@@ -96,6 +96,7 @@ const NON_TEXT_MARKS: { file: string; rule: string }[] = [
96
96
  { file: 'components/ui/Accordion/Accordion.module.css', rule: '.item' },
97
97
  { file: 'components/ui/Tabs/Tabs.module.css', rule: '.tabList' },
98
98
  { file: 'components/ui/Table/Table.module.css', rule: '.th' },
99
+ { file: 'components/interaction/Rating/Rating.module.css', rule: '.star' },
99
100
  ];
100
101
 
101
102
  describe('non-text marks use the as-surface member of the colour set', () => {
@@ -14,7 +14,7 @@ const bdcCss = `
14
14
 
15
15
  @property --bdc-outline_width {
16
16
  syntax: '<length>';
17
- inherits: false;
17
+ inherits: true;
18
18
  initial-value: 1px;
19
19
  }
20
20
 
@@ -36,7 +36,7 @@ const bdcCss = `
36
36
  initial-value: 0 0 0 0 transparent;
37
37
  }
38
38
 
39
- @layer boostdev.component {
39
+ @layer boostdev.tokens.semantic {
40
40
  :root {
41
41
  --bdc-outline_border: none;
42
42
 
@@ -47,14 +47,20 @@ const bdcCss = `
47
47
  /* Active / selected state colours — override these to theme all filled form controls globally */
48
48
  --bdc-color_active: var(--bds-color_interactive);
49
49
  --bdc-color_on-active: var(--bds-color_on-interactive);
50
- --bdc-color_active--subtle: var(--bds-color_blue--subtle);
51
- --bdc-color_active--strong: var(--bds-color_interactive_on-bg);
50
+ --bdc-color_active--subtle: var(--bds-color_blue--subtle);
51
+ --bdc-color_on-active--subtle: var(--bds-color_on-blue--subtle);
52
+ --bdc-color_active--strong: var(--bds-color_interactive_on-bg);
53
+ --bdc-color_on-active--strong: var(--bds-color_on-blue--strong);
52
54
 
53
55
  --bdc-outline_width: 1px;
56
+ --bdc-outline_width--error: 2px;
54
57
  --bdc-outline_offset: -1px; /* available for consumer use; bdc borders now use inset box-shadow */
55
58
  --bdc-outline_radius: var(--bds-border_radius--xs);
56
59
  --bdc-outline_radius--l: 1.5em;
57
60
  --bdc-outline_shadow: 0 0 0 0 transparent;
61
+
62
+ --bds-outline_default: 2px solid var(--bds-color_interactive);
63
+ --bds-outline_offset: 2px;
58
64
  }
59
65
  }
60
66
  `;
@@ -77,3 +77,4 @@ export { BdsCalendar } from './ui/bds-calendar';
77
77
  export { BdsCalendarRange } from './ui/bds-calendar-range';
78
78
  export { BdsDropdownMenu } from './interaction/bds-dropdown-menu';
79
79
  export { BdsDropdownMenuItem } from './interaction/bds-dropdown-menu-item';
80
+ export { BdsDropdownMenuGroup } from './interaction/bds-dropdown-menu-group';
@@ -7,7 +7,7 @@ import * as Stories from './BdsAccordion.stories';
7
7
 
8
8
  Framework-agnostic Accordion custom element. Coordinates open/closed state across `<bds-accordion-item>` children; by default only one item is open at a time.
9
9
 
10
- > **Status: experimental** — API may change before stable release.
10
+ > **Status: alpha** — API may change before stable release.
11
11
 
12
12
  ## Installation
13
13
 
@@ -61,7 +61,7 @@ function BdsAccordionStory({
61
61
  const meta = {
62
62
  title: 'Web Components/UI/Accordion',
63
63
  component: BdsAccordionStory,
64
- tags: ['!stable', 'experimental'],
64
+ tags: ['!stable', 'alpha'],
65
65
  parameters: { layout: 'padded' },
66
66
  argTypes: {
67
67
  allowMultiple: { control: 'boolean' },
@@ -7,7 +7,7 @@ import * as Stories from './BdsButton.stories';
7
7
 
8
8
  Framework-agnostic button custom element. Renders as `<button>` or `<a>` depending on whether `href` is set. Matches the React `Button` component in variants, sizes, and theming.
9
9
 
10
- > **Status: experimental** — API may change before stable release.
10
+ > **Status: alpha** — API may change before stable release.
11
11
 
12
12
  ## Installation
13
13
 
@@ -101,7 +101,7 @@ type BdsButtonStoryArgs = Omit<BdsButtonProps, 'iconStart' | 'iconEnd'> & {
101
101
  const meta: Meta<BdsButtonStoryArgs> = {
102
102
  title: 'Web Components/Interaction/Button',
103
103
  component: BdsButton,
104
- tags: ['!stable', 'experimental'],
104
+ tags: ['!stable', 'alpha'],
105
105
  parameters: { layout: 'centered' },
106
106
  argTypes: {
107
107
  variant: {
@@ -7,7 +7,7 @@ import * as Stories from './BdsCollapsible.stories';
7
7
 
8
8
  Framework-agnostic Collapsible custom element. Wraps a native `<details>`/`<summary>` pair for built-in toggle behaviour with design-system styling and a `bds-toggle` event.
9
9
 
10
- > **Status: experimental** — API may change before stable release.
10
+ > **Status: alpha** — API may change before stable release.
11
11
 
12
12
  ## Installation
13
13
 
@@ -25,7 +25,7 @@ function BdsCollapsible({
25
25
  const meta = {
26
26
  title: 'Web Components/UI/Collapsible',
27
27
  component: BdsCollapsible,
28
- tags: ['!stable', 'experimental'],
28
+ tags: ['!stable', 'alpha'],
29
29
  parameters: { layout: 'padded' },
30
30
  argTypes: {
31
31
  open: { control: 'boolean' },
@@ -7,7 +7,7 @@ import * as Stories from './BdsDialog.stories';
7
7
 
8
8
  Framework-agnostic Dialog custom element. Wraps a native `<dialog>` element with `showModal()` / `close()` lifecycle, backdrop-click to dismiss, Escape key handling, Tab focus trapping, and the Invoker Commands API (custom commands).
9
9
 
10
- > **Status: experimental** — API may change before stable release.
10
+ > **Status: alpha** — API may change before stable release.
11
11
 
12
12
  ## Installation
13
13
 
@@ -53,7 +53,7 @@ function BdsDialog({
53
53
  const meta = {
54
54
  title: 'Web Components/Interaction/Dialog',
55
55
  component: BdsDialog,
56
- tags: ['!stable', 'experimental'],
56
+ tags: ['!stable', 'alpha'],
57
57
  parameters: { layout: 'centered' },
58
58
  argTypes: {
59
59
  triggerLabel: { control: 'text' },
@@ -7,7 +7,7 @@ import * as Stories from './BdsDrawer.stories';
7
7
 
8
8
  Framework-agnostic Drawer (slide-in panel) custom element. Same modal infrastructure as `<bds-dialog>` but positioned as a side panel that slides in from either side of the viewport.
9
9
 
10
- > **Status: experimental** — API may change before stable release.
10
+ > **Status: alpha** — API may change before stable release.
11
11
 
12
12
  ## Installation
13
13
 
@@ -54,7 +54,7 @@ function BdsDrawer({
54
54
  const meta = {
55
55
  title: 'Web Components/Interaction/Drawer',
56
56
  component: BdsDrawer,
57
- tags: ['!stable', 'experimental'],
57
+ tags: ['!stable', 'alpha'],
58
58
  parameters: { layout: 'centered' },
59
59
  argTypes: {
60
60
  side: { control: 'select', options: ['left', 'right'] },
@@ -5,9 +5,9 @@ import * as Stories from './BdsDropdownMenu.stories';
5
5
 
6
6
  # &lt;bds-dropdown-menu&gt;
7
7
 
8
- Framework-agnostic Dropdown Menu custom element. A trigger-anchored menu panel with keyboard navigation, light-dismiss, and support for disabled and destructive items.
8
+ Framework-agnostic Dropdown Menu custom element. A trigger-anchored menu panel with keyboard navigation, light-dismiss, and support for disabled and destructive items, shortcut hints and labelled groups.
9
9
 
10
- > **Status: experimental** — API may change before stable release.
10
+ > **Status: alpha** — API may change before stable release.
11
11
 
12
12
  ## Installation
13
13
 
@@ -45,6 +45,9 @@ Or in HTML without a bundler:
45
45
  ### With disabled item
46
46
  <Canvas of={Stories.WithDisabledItem} />
47
47
 
48
+ ### With groups
49
+ <Canvas of={Stories.WithGroups} />
50
+
48
51
  ### All placements
49
52
  <Canvas of={Stories.AllPlacements} />
50
53
 
@@ -57,17 +60,37 @@ Or in HTML without a bundler:
57
60
  | Property | Default | Description |
58
61
  |----------|---------|-------------|
59
62
  | `--dropdown_border` | `none` | Real CSS `border` on the panel (in addition to the bdc inset outline) |
63
+ | `--dropdown_padding` | `--bds-space_xxs` | Panel padding on all sides |
64
+ | `--dropdown_border-color` | `--bds-color_on-bg--as-surface` | Panel outline colour (the bdc inset outline) |
60
65
  | `--dropdown_radius` | `--bdc-outline_radius` (`--bds-border_radius--s`) | Panel corner radius |
61
66
  | `--dropdown_color` | `--bds-color_bg` | Panel background colour |
62
67
  | `--dropdown_on-color` | `--bds-color_on-bg` | Panel text colour |
63
- | `--dropdown_shadow` | `--bds-shadow_m` | Panel elevation shadow, layered behind the inset border |
68
+ | `--dropdown_shadow` | `--bds-shadow_l` | Panel elevation shadow, layered behind the inset border |
64
69
 
65
70
  ## CSS Custom Properties — `<bds-dropdown-menu-item>`
66
71
 
67
72
  | Property | Default | Description |
68
73
  |----------|---------|-------------|
69
- | `--dropdown_item-bg--hover` | `--bds-color_bg--subtle` | Item background colour on hover |
70
- | `--dropdown_item-color--hover` | `--bds-color_interactive_on-bg` | Item text colour on hover |
74
+ | `--dropdown_item-padding` | `--bds-space_xs --bds-space_s` | Item padding |
75
+ | `--dropdown_item-radius` | `--bds-border_radius--xs` | Item corner radius |
76
+ | `--dropdown_item-font-size` | `--bds-font_size--body` | Item font size |
77
+ | `--dropdown_item-bg--hover` | `--bds-color_primary--subtle` | Item background on hover and keyboard focus |
78
+ | `--dropdown_item-color--hover` | `--bds-color_on-primary--subtle` | Item text colour on hover and keyboard focus |
79
+ | `--dropdown_item-opacity--disabled` | `0.4` | Opacity of a disabled item |
80
+ | `--dropdown_item-color--destructive` | `--bds-color_error_on-bg` | Destructive item text colour |
81
+ | `--dropdown_item-bg--destructive-hover` | `--bds-color_error--subtle` | Destructive item background on hover and focus |
82
+ | `--dropdown_item-color--destructive-hover` | `--bds-color_on-error--subtle` | Destructive item text colour on hover and focus |
83
+ | `--dropdown_shortcut-color` | `--bds-color_on-bg--muted` | Shortcut hint colour |
84
+ | `--dropdown_shortcut-font-size` | `--bds-font_size--body--s` | Shortcut hint font size |
85
+
86
+ ## CSS Custom Properties — `<bds-dropdown-menu-group>`
87
+
88
+ | Property | Default | Description |
89
+ |----------|---------|-------------|
90
+ | `--dropdown_group-label-font-size` | `--bds-font_size--body--s` | Group label font size |
91
+ | `--dropdown_group-label-font-weight` | `--bds-font_weight--bold` | Group label font weight |
92
+ | `--dropdown_group-label-color` | `--bds-color_on-bg--muted` | Group label colour |
93
+ | `--dropdown_group-label-padding` | `--bds-space_xs --bds-space_s --bds-space_xxs` | Group label padding |
71
94
 
72
95
  ## Attributes — `<bds-dropdown-menu>`
73
96
 
@@ -83,20 +106,34 @@ Or in HTML without a bundler:
83
106
  | `value` | string | `""` | Value emitted in `bds-select` event detail |
84
107
  | `disabled` | boolean | `false` | Prevents interaction; item is excluded from keyboard navigation |
85
108
  | `destructive` | boolean | `false` | Renders the item in a destructive (error colour) style |
109
+ | `shortcut` | string | `""` | Shortcut as display text at the inline end; `aria-hidden`, the consumer wires the actual key |
110
+
111
+ ## Attributes — `<bds-dropdown-menu-group>`
112
+
113
+ | Attribute | Type | Default | Description |
114
+ |-----------|------|---------|-------------|
115
+ | `label` | string | `""` | Visible group label and accessible name of the group |
86
116
 
87
117
  ## Slots — `<bds-dropdown-menu>`
88
118
 
89
119
  | Slot | Description |
90
120
  |------|-------------|
91
121
  | `trigger` | The activating element (typically a `<button>`) |
92
- | `(default)` | `<bds-dropdown-menu-item>` elements |
122
+ | `(default)` | `<bds-dropdown-menu-item>` or `<bds-dropdown-menu-group>` elements |
93
123
 
94
124
  ## Slots — `<bds-dropdown-menu-item>`
95
125
 
96
126
  | Slot | Description |
97
127
  |------|-------------|
128
+ | `icon` | Optional decorative icon before the label |
98
129
  | `(default)` | Item label text |
99
130
 
131
+ ## Slots — `<bds-dropdown-menu-group>`
132
+
133
+ | Slot | Description |
134
+ |------|-------------|
135
+ | `(default)` | `<bds-dropdown-menu-item>` elements |
136
+
100
137
  ## Events
101
138
 
102
139
  | Event | Fired by | Bubbles | Detail | Description |
@@ -116,6 +153,23 @@ Or in HTML without a bundler:
116
153
  </bds-dropdown-menu>
117
154
  ```
118
155
 
156
+ ## Usage with groups
157
+
158
+ ```html
159
+ <bds-dropdown-menu>
160
+ <bds-button slot="trigger" variant="outline">Acties</bds-button>
161
+ <bds-dropdown-menu-group label="Bewerken">
162
+ <bds-dropdown-menu-item value="edit" shortcut="⌘E">
163
+ <span slot="icon">✎</span>Bewerken
164
+ </bds-dropdown-menu-item>
165
+ <bds-dropdown-menu-item value="duplicate">Dupliceren</bds-dropdown-menu-item>
166
+ </bds-dropdown-menu-group>
167
+ <bds-dropdown-menu-group label="Gevaarlijk">
168
+ <bds-dropdown-menu-item value="delete" destructive>Verwijderen</bds-dropdown-menu-item>
169
+ </bds-dropdown-menu-group>
170
+ </bds-dropdown-menu>
171
+ ```
172
+
119
173
  ## Accessibility
120
174
 
121
175
  - The slotted trigger receives `aria-haspopup="menu"`, `aria-controls` (pointing at the panel's id), and `aria-expanded` kept in sync with open/close state
@@ -125,3 +179,5 @@ Or in HTML without a bundler:
125
179
  - Disabled items are excluded from keyboard navigation
126
180
  - Focus returns to the trigger element on close
127
181
  - The panel is an absolutely-positioned shadow-DOM element (not the native Popover API), so it can be clipped by an ancestor's `overflow` or stacking context
182
+ - `<bds-dropdown-menu-group>` renders a `role="group"` in its shadow root named by its visible label (`aria-labelledby` within the same shadow root); the label is not focusable and keyboard navigation skips it
183
+ - The item `shortcut` is `aria-hidden`; the consumer wires the actual key
@@ -16,7 +16,7 @@ function BdsDropdownMenu({
16
16
  return React.createElement(
17
17
  'bds-dropdown-menu',
18
18
  { placement },
19
- React.createElement('button', { slot: 'trigger', type: 'button' }, triggerLabel),
19
+ React.createElement('bds-button', { slot: 'trigger', variant: 'outline' }, triggerLabel),
20
20
  children ?? [
21
21
  React.createElement('bds-dropdown-menu-item', { key: 'edit', value: 'edit' }, 'Edit'),
22
22
  React.createElement('bds-dropdown-menu-item', { key: 'duplicate', value: 'duplicate' }, 'Duplicate'),
@@ -28,7 +28,7 @@ function BdsDropdownMenu({
28
28
  const meta = {
29
29
  title: 'Web Components/Interaction/DropdownMenu',
30
30
  component: BdsDropdownMenu,
31
- tags: ['!stable', 'experimental'],
31
+ tags: ['!stable', 'alpha'],
32
32
  parameters: { layout: 'centered' },
33
33
  argTypes: {
34
34
  placement: {
@@ -51,10 +51,10 @@ export const WithDestructiveItem: Story = {
51
51
  React.createElement(
52
52
  'bds-dropdown-menu',
53
53
  { placement: 'bottom-start' },
54
- React.createElement('button', { slot: 'trigger', type: 'button' }, 'Manage'),
54
+ React.createElement('bds-button', { slot: 'trigger', variant: 'outline' }, 'Manage'),
55
55
  React.createElement('bds-dropdown-menu-item', { value: 'edit' }, 'Edit'),
56
56
  React.createElement('bds-dropdown-menu-item', { value: 'duplicate' }, 'Duplicate'),
57
- React.createElement('bds-dropdown-menu-item', { value: 'delete', destructive: '' }, 'Delete'),
57
+ React.createElement('bds-dropdown-menu-item', { value: 'delete', destructive: true }, 'Delete'),
58
58
  ),
59
59
  };
60
60
 
@@ -63,13 +63,38 @@ export const WithDisabledItem: Story = {
63
63
  React.createElement(
64
64
  'bds-dropdown-menu',
65
65
  { placement: 'bottom-start' },
66
- React.createElement('button', { slot: 'trigger', type: 'button' }, 'Actions'),
66
+ React.createElement('bds-button', { slot: 'trigger', variant: 'outline' }, 'Actions'),
67
67
  React.createElement('bds-dropdown-menu-item', { value: 'view' }, 'View'),
68
- React.createElement('bds-dropdown-menu-item', { value: 'export', disabled: '' }, 'Export (unavailable)'),
68
+ React.createElement('bds-dropdown-menu-item', { value: 'export', disabled: true }, 'Export (unavailable)'),
69
69
  React.createElement('bds-dropdown-menu-item', { value: 'share' }, 'Share'),
70
70
  ),
71
71
  };
72
72
 
73
+ export const WithGroups: Story = {
74
+ render: () =>
75
+ React.createElement(
76
+ 'bds-dropdown-menu',
77
+ { placement: 'bottom-start' },
78
+ React.createElement('bds-button', { slot: 'trigger', variant: 'outline' }, 'Acties'),
79
+ React.createElement(
80
+ 'bds-dropdown-menu-group',
81
+ { label: 'Bewerken' },
82
+ React.createElement(
83
+ 'bds-dropdown-menu-item',
84
+ { value: 'edit', shortcut: '⌘E' },
85
+ React.createElement('span', { slot: 'icon' }, '✎'),
86
+ 'Bewerken',
87
+ ),
88
+ React.createElement('bds-dropdown-menu-item', { value: 'duplicate', shortcut: '⌘D' }, 'Dupliceren'),
89
+ ),
90
+ React.createElement(
91
+ 'bds-dropdown-menu-group',
92
+ { label: 'Gevaarlijk' },
93
+ React.createElement('bds-dropdown-menu-item', { value: 'delete', destructive: true }, 'Verwijderen'),
94
+ ),
95
+ ),
96
+ };
97
+
73
98
  export const AllPlacements: Story = {
74
99
  render: () => (
75
100
  <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, auto)', gap: '6rem', padding: '5rem' }}>
@@ -80,7 +105,7 @@ export const AllPlacements: Story = {
80
105
  React.createElement(
81
106
  'bds-dropdown-menu',
82
107
  { placement: p },
83
- React.createElement('button', { slot: 'trigger', type: 'button' }, p),
108
+ React.createElement('bds-button', { slot: 'trigger', variant: 'outline' }, p),
84
109
  React.createElement('bds-dropdown-menu-item', { value: 'a' }, 'Item A'),
85
110
  React.createElement('bds-dropdown-menu-item', { value: 'b' }, 'Item B'),
86
111
  ),
@@ -7,7 +7,7 @@ import * as Stories from './BdsPopover.stories';
7
7
 
8
8
  Framework-agnostic popover custom element. A non-modal floating panel anchored to a trigger element. Uses CSS Anchor Positioning for automatic repositioning when near viewport edges.
9
9
 
10
- > **Status: experimental** — API may change before stable release.
10
+ > **Status: alpha** — API may change before stable release.
11
11
 
12
12
  ## Installation
13
13
 
@@ -24,7 +24,7 @@ function BdsPopover({
24
24
  const meta = {
25
25
  title: 'Web Components/Interaction/Popover',
26
26
  component: BdsPopover,
27
- tags: ['!stable', 'experimental'],
27
+ tags: ['!stable', 'alpha'],
28
28
  parameters: { layout: 'centered' },
29
29
  argTypes: {
30
30
  placement: { control: 'select', options: ['bottom', 'top', 'left', 'right'] },
@@ -7,7 +7,7 @@ import * as Stories from './BdsSkipLink.stories';
7
7
 
8
8
  Framework-agnostic Skip Navigation Link custom element. Visually hidden until focused, allowing keyboard users to jump directly to the main content area and bypass repeated navigation.
9
9
 
10
- > **Status: experimental** — API may change before stable release.
10
+ > **Status: alpha** — API may change before stable release.
11
11
 
12
12
  ## Installation
13
13
 
@@ -20,7 +20,7 @@ function BdsSkipLink({
20
20
  const meta = {
21
21
  title: 'Web Components/UI/SkipLink',
22
22
  component: BdsSkipLink,
23
- tags: ['!stable', 'experimental'],
23
+ tags: ['!stable', 'alpha'],
24
24
  parameters: { layout: 'padded' },
25
25
  argTypes: {
26
26
  href: { control: 'text' },
@@ -7,7 +7,7 @@ import * as Stories from './BdsTabs.stories';
7
7
 
8
8
  Framework-agnostic Tabs custom element. Coordinates `<bds-tab>` and `<bds-tab-panel>` children by DOM order, with full keyboard navigation.
9
9
 
10
- > **Status: experimental** — API may change before stable release.
10
+ > **Status: alpha** — API may change before stable release.
11
11
 
12
12
  ## Installation
13
13
 
@@ -102,6 +102,11 @@ across every state; set `--tab_color--active` to theme only the selected tab.
102
102
  | `--tab_color--active` | Text colour override for the selected tab |
103
103
  | `--tab_border-color--active` | Bottom-border colour override for the selected tab |
104
104
  | `--tab_color--hover` | Text colour override on hover (unselected, enabled tabs) |
105
+ | `--tab_color--inactive` | Text colour override for unselected tabs (default: `--bds-color_on-bg--muted`) |
106
+ | `--tab_font-weight` | Tab font weight override (all states) |
107
+ | `--tab_font-weight--inactive` | Font weight override for unselected tabs (default: `--bds-font_weight--medium`) |
108
+ | `--tab_font-weight--active` | Font weight override for the selected tab (default: `--bds-font_weight--bold`) |
109
+ | `--tab_indicator-width` | Thickness of the bottom indicator line (default: `3px`) |
105
110
 
106
111
  ## Usage in plain HTML
107
112
 
@@ -125,6 +130,10 @@ Tabs and panels are matched by DOM order (first tab → first panel, etc.):
125
130
  </bds-tabs>
126
131
  ```
127
132
 
133
+ ## Layout stability
134
+
135
+ The slotted label is mirrored into a `data-label` attribute on an inner wrapper, and a hidden `::after` repeats it at the active weight (`--tab_font-weight--active`). The tab keeps its bold width, so selecting a tab does not shift the row. The copy is invisible and not read by screen readers.
136
+
128
137
  ## Accessibility
129
138
 
130
139
  - The tab list container has `role="tablist"`
@@ -29,7 +29,7 @@ function BdsTabs({
29
29
  const meta = {
30
30
  title: 'Web Components/UI/Tabs',
31
31
  component: BdsTabs,
32
- tags: ['!stable', 'experimental'],
32
+ tags: ['!stable', 'alpha'],
33
33
  parameters: { layout: 'padded' },
34
34
  } satisfies Meta<typeof BdsTabs>;
35
35
 
@@ -7,7 +7,7 @@ import * as Stories from './BdsToastProvider.stories';
7
7
 
8
8
  Framework-agnostic toast notification provider. Wrap your page content in `<bds-toast-provider>` to enable toast notifications that render in the browser top layer (above fixed/sticky elements). Auto-dismisses after 5 seconds.
9
9
 
10
- > **Status: experimental** — API may change before stable release.
10
+ > **Status: alpha** — API may change before stable release.
11
11
 
12
12
  ## Installation
13
13