@boostdev/design-system-components 2.15.0 → 2.16.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 (284) hide show
  1. package/AGENTS.md +19 -14
  2. package/dist/client.cjs +271 -205
  3. package/dist/client.css +801 -642
  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 +801 -642
  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-LDIPCTRN.js → chunk-2MJTO2IW.js} +48 -2
  14. package/dist/web-components/{chunk-3WAV6MDN.js → chunk-3FSGP35V.js} +1 -0
  15. package/dist/web-components/{chunk-KA3VPKMY.js → chunk-4MB2ICSK.js} +1 -0
  16. package/dist/web-components/{chunk-IDSM74LM.js → chunk-6XL5P76D.js} +3 -3
  17. package/dist/web-components/{chunk-P24JYC5V.js → chunk-7VXRMCAL.js} +10 -4
  18. package/dist/web-components/{chunk-CUKQ2L5B.js → chunk-AGI6YQRC.js} +9 -16
  19. package/dist/web-components/chunk-BDRV452N.js +51 -0
  20. package/dist/web-components/{chunk-3AY2YKCM.js → chunk-CKCPV347.js} +1 -0
  21. package/dist/web-components/{chunk-HBLJ4SLY.js → chunk-DD3OUXNG.js} +5 -5
  22. package/dist/web-components/{chunk-RVF7W653.js → chunk-DGOCPKHI.js} +30 -10
  23. package/dist/web-components/{chunk-2OLVQUBU.js → chunk-EYCW7TKB.js} +8 -15
  24. package/dist/web-components/{chunk-VANAKB6D.js → chunk-GPJWLAKU.js} +33 -16
  25. package/dist/web-components/{chunk-VED2DFJ6.js → chunk-GQNQBEYR.js} +8 -15
  26. package/dist/web-components/{chunk-WFVKU4GX.js → chunk-IKAJLROF.js} +49 -4
  27. package/dist/web-components/{chunk-RSZ3BWBK.js → chunk-KSK4RZZQ.js} +30 -7
  28. package/dist/web-components/{chunk-FEDABOR5.js → chunk-LHFUXZ52.js} +7 -15
  29. package/dist/web-components/{chunk-M3ECULRH.js → chunk-RBF7WPLI.js} +10 -8
  30. package/dist/web-components/{chunk-6G22I2CK.js → chunk-RZH5IVB5.js} +31 -1
  31. package/dist/web-components/chunk-SRKQ6GST.js +40 -0
  32. package/dist/web-components/{chunk-5HUAFCU6.js → chunk-TJV7UIXC.js} +7 -0
  33. package/dist/web-components/{chunk-J3HVUIUH.js → chunk-XI2U6U26.js} +8 -15
  34. package/dist/web-components/{chunk-JH6LQKLK.js → chunk-XJU7KITO.js} +8 -15
  35. package/dist/web-components/{chunk-JV5QT2OU.js → chunk-YLDQOESI.js} +27 -13
  36. package/dist/web-components/globals.js +1 -1
  37. package/dist/web-components/index.d.ts +1 -0
  38. package/dist/web-components/index.js +33 -28
  39. package/dist/web-components/interaction/bds-dropdown-menu-group.d.ts +41 -0
  40. package/dist/web-components/interaction/bds-dropdown-menu-group.js +7 -0
  41. package/dist/web-components/interaction/bds-dropdown-menu-item.d.ts +14 -1
  42. package/dist/web-components/interaction/bds-dropdown-menu-item.js +1 -1
  43. package/dist/web-components/interaction/bds-dropdown-menu.d.ts +2 -1
  44. package/dist/web-components/interaction/bds-dropdown-menu.js +1 -1
  45. package/dist/web-components/interaction/bds-tab.d.ts +5 -0
  46. package/dist/web-components/interaction/bds-tab.js +1 -1
  47. package/dist/web-components/interaction/bds-tooltip.js +1 -1
  48. package/dist/web-components/interaction/form/bds-checkbox-group.d.ts +6 -0
  49. package/dist/web-components/interaction/form/bds-checkbox-group.js +2 -1
  50. package/dist/web-components/interaction/form/bds-checkbox.js +1 -1
  51. package/dist/web-components/interaction/form/bds-combobox.js +2 -1
  52. package/dist/web-components/interaction/form/bds-form-input.js +2 -1
  53. package/dist/web-components/interaction/form/bds-number-input.js +2 -1
  54. package/dist/web-components/interaction/form/bds-radio-group.d.ts +5 -0
  55. package/dist/web-components/interaction/form/bds-radio-group.js +2 -1
  56. package/dist/web-components/interaction/form/bds-radio.js +1 -1
  57. package/dist/web-components/interaction/form/bds-select.js +2 -1
  58. package/dist/web-components/interaction/form/bds-slider.js +2 -1
  59. package/dist/web-components/interaction/form/bds-switch.js +1 -1
  60. package/dist/web-components/interaction/form/bds-textarea.js +2 -1
  61. package/dist/web-components/ui/bds-alert.d.ts +8 -1
  62. package/dist/web-components/ui/bds-alert.js +1 -1
  63. package/dist/web-components/ui/bds-avatar.d.ts +11 -0
  64. package/dist/web-components/ui/bds-avatar.js +1 -1
  65. package/dist/web-components/ui/bds-notification-banner.d.ts +14 -1
  66. package/dist/web-components/ui/bds-notification-banner.js +1 -1
  67. package/dist/web-components/ui/bds-section-header.d.ts +6 -0
  68. package/dist/web-components/ui/bds-section-header.js +1 -1
  69. package/dist/web-components/ui/bds-separator.js +1 -1
  70. package/dist/web-components/ui/bds-table.js +1 -1
  71. package/package.json +6 -2
  72. package/src/components/interaction/DropdownMenu/DropdownMenu.mdx +35 -4
  73. package/src/components/interaction/DropdownMenu/DropdownMenu.module.css +58 -10
  74. package/src/components/interaction/DropdownMenu/DropdownMenu.spec.tsx +114 -1
  75. package/src/components/interaction/DropdownMenu/DropdownMenu.stories.tsx +25 -0
  76. package/src/components/interaction/DropdownMenu/DropdownMenu.tsx +69 -17
  77. package/src/components/interaction/form/Checkbox/Checkbox.module.css +1 -0
  78. package/src/components/interaction/form/Checkbox/Checkbox.spec.tsx +7 -0
  79. package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.mdx +1 -0
  80. package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.module.css +7 -0
  81. package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.spec.tsx +22 -0
  82. package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.tsx +1 -1
  83. package/src/components/interaction/form/Combobox/Combobox.module.css +1 -0
  84. package/src/components/interaction/form/Combobox/Combobox.spec.tsx +7 -0
  85. package/src/components/interaction/form/FormInput/FormInput.mdx +9 -0
  86. package/src/components/interaction/form/FormInput/FormInput.module.css +1 -0
  87. package/src/components/interaction/form/FormInput/FormInput.spec.tsx +7 -0
  88. package/src/components/interaction/form/NumberInput/NumberInput.module.css +1 -0
  89. package/src/components/interaction/form/NumberInput/NumberInput.spec.tsx +7 -0
  90. package/src/components/interaction/form/Radio/Radio.module.css +1 -0
  91. package/src/components/interaction/form/Radio/Radio.spec.tsx +7 -0
  92. package/src/components/interaction/form/RadioGroup/RadioGroup.mdx +1 -0
  93. package/src/components/interaction/form/RadioGroup/RadioGroup.module.css +7 -0
  94. package/src/components/interaction/form/RadioGroup/RadioGroup.spec.tsx +22 -0
  95. package/src/components/interaction/form/RadioGroup/RadioGroup.tsx +1 -1
  96. package/src/components/interaction/form/Select/Select.module.css +1 -0
  97. package/src/components/interaction/form/Select/Select.spec.tsx +7 -0
  98. package/src/components/interaction/form/Switch/Switch.module.css +1 -0
  99. package/src/components/interaction/form/Switch/Switch.spec.tsx +7 -0
  100. package/src/components/interaction/form/Textarea/Textarea.module.css +1 -0
  101. package/src/components/interaction/form/Textarea/Textarea.spec.tsx +7 -0
  102. package/src/components/interaction/form/atoms/Message.module.css +14 -3
  103. package/src/components/interaction/form/atoms/Message.spec.tsx +22 -0
  104. package/src/components/interaction/form/atoms/Message.tsx +5 -0
  105. package/src/components/layout/SectionHeader/SectionHeader.mdx +18 -5
  106. package/src/components/layout/SectionHeader/SectionHeader.module.css +35 -14
  107. package/src/components/layout/SectionHeader/SectionHeader.spec.tsx +44 -0
  108. package/src/components/layout/SectionHeader/SectionHeader.stories.tsx +5 -0
  109. package/src/components/layout/SectionHeader/SectionHeader.tsx +3 -1
  110. package/src/components/ui/Alert/Alert.mdx +11 -0
  111. package/src/components/ui/Alert/Alert.module.css +30 -1
  112. package/src/components/ui/Alert/Alert.spec.tsx +21 -0
  113. package/src/components/ui/Alert/Alert.stories.tsx +20 -0
  114. package/src/components/ui/Alert/Alert.tsx +8 -1
  115. package/src/components/ui/Avatar/Avatar.mdx +22 -2
  116. package/src/components/ui/Avatar/Avatar.module.css +29 -2
  117. package/src/components/ui/Avatar/Avatar.spec.tsx +26 -0
  118. package/src/components/ui/Avatar/Avatar.stories.tsx +23 -0
  119. package/src/components/ui/Avatar/Avatar.tsx +4 -2
  120. package/src/components/ui/Avatar/avatarTone.spec.ts +41 -0
  121. package/src/components/ui/Avatar/avatarTone.ts +22 -0
  122. package/src/components/ui/Collapsible/Collapsible.module.css +1 -2
  123. package/src/components/ui/NotificationBanner/NotificationBanner.mdx +14 -0
  124. package/src/components/ui/NotificationBanner/NotificationBanner.module.css +31 -1
  125. package/src/components/ui/NotificationBanner/NotificationBanner.spec.tsx +29 -0
  126. package/src/components/ui/NotificationBanner/NotificationBanner.stories.tsx +25 -0
  127. package/src/components/ui/NotificationBanner/NotificationBanner.tsx +15 -1
  128. package/src/components/ui/Separator/Separator.mdx +1 -0
  129. package/src/components/ui/Separator/Separator.module.css +6 -0
  130. package/src/components/ui/Separator/Separator.spec.tsx +19 -0
  131. package/src/components/ui/Separator/Separator.stories.tsx +15 -0
  132. package/src/components/ui/Table/Table.mdx +4 -1
  133. package/src/components/ui/Table/Table.module.css +7 -7
  134. package/src/components/ui/Table/Table.spec.tsx +11 -0
  135. package/src/components/ui/Tabs/Tabs.mdx +11 -5
  136. package/src/components/ui/Tabs/Tabs.module.css +23 -5
  137. package/src/components/ui/Tabs/Tabs.spec.tsx +39 -0
  138. package/src/components/ui/Tabs/Tabs.tsx +2 -1
  139. package/src/components/ui/Tabs/getNodeText.spec.tsx +23 -0
  140. package/src/components/ui/Tabs/getNodeText.ts +13 -0
  141. package/src/components/ui/Tooltip/Tooltip.mdx +6 -3
  142. package/src/components/ui/Tooltip/Tooltip.module.css +6 -2
  143. package/src/components/ui/Tooltip/Tooltip.spec.tsx +10 -0
  144. package/src/components/ui/Tooltip/Tooltip.stories.tsx +13 -0
  145. package/src/css/bdc.css +5 -2
  146. package/src/css/bdc.spec.ts +65 -0
  147. package/src/stories/DesignSystem/Borders.mdx +17 -9
  148. package/src/web-components/globals.ts +10 -4
  149. package/src/web-components/index.ts +1 -0
  150. package/src/web-components/interaction/BdsAccordion.mdx +1 -1
  151. package/src/web-components/interaction/BdsAccordion.stories.tsx +1 -1
  152. package/src/web-components/interaction/BdsButton.mdx +1 -1
  153. package/src/web-components/interaction/BdsButton.stories.tsx +1 -1
  154. package/src/web-components/interaction/BdsCollapsible.mdx +1 -1
  155. package/src/web-components/interaction/BdsCollapsible.stories.tsx +1 -1
  156. package/src/web-components/interaction/BdsDialog.mdx +1 -1
  157. package/src/web-components/interaction/BdsDialog.stories.tsx +1 -1
  158. package/src/web-components/interaction/BdsDrawer.mdx +1 -1
  159. package/src/web-components/interaction/BdsDrawer.stories.tsx +1 -1
  160. package/src/web-components/interaction/BdsDropdownMenu.mdx +62 -6
  161. package/src/web-components/interaction/BdsDropdownMenu.stories.tsx +32 -7
  162. package/src/web-components/interaction/BdsPopover.mdx +1 -1
  163. package/src/web-components/interaction/BdsPopover.stories.tsx +1 -1
  164. package/src/web-components/interaction/BdsSkipLink.mdx +1 -1
  165. package/src/web-components/interaction/BdsSkipLink.stories.tsx +1 -1
  166. package/src/web-components/interaction/BdsTabs.mdx +10 -1
  167. package/src/web-components/interaction/BdsTabs.stories.tsx +1 -1
  168. package/src/web-components/interaction/BdsToastProvider.mdx +1 -1
  169. package/src/web-components/interaction/BdsToastProvider.stories.tsx +1 -1
  170. package/src/web-components/interaction/BdsTooltip.mdx +13 -5
  171. package/src/web-components/interaction/BdsTooltip.stories.tsx +12 -12
  172. package/src/web-components/interaction/bds-dropdown-menu-group.ts +72 -0
  173. package/src/web-components/interaction/bds-dropdown-menu-item.ts +65 -17
  174. package/src/web-components/interaction/bds-dropdown-menu.spec.ts +135 -0
  175. package/src/web-components/interaction/bds-dropdown-menu.ts +5 -4
  176. package/src/web-components/interaction/bds-tab.spec.ts +34 -2
  177. package/src/web-components/interaction/bds-tab.ts +31 -6
  178. package/src/web-components/interaction/bds-tooltip.spec.ts +16 -0
  179. package/src/web-components/interaction/bds-tooltip.ts +10 -8
  180. package/src/web-components/interaction/form/BdsCheckbox.mdx +5 -1
  181. package/src/web-components/interaction/form/BdsCheckbox.stories.tsx +1 -1
  182. package/src/web-components/interaction/form/BdsCheckboxGroup.mdx +5 -1
  183. package/src/web-components/interaction/form/BdsCheckboxGroup.stories.tsx +1 -1
  184. package/src/web-components/interaction/form/BdsCombobox.mdx +5 -1
  185. package/src/web-components/interaction/form/BdsCombobox.stories.tsx +1 -1
  186. package/src/web-components/interaction/form/BdsFieldGroup.stories.tsx +1 -1
  187. package/src/web-components/interaction/form/BdsFileInput.mdx +1 -1
  188. package/src/web-components/interaction/form/BdsFileInput.stories.tsx +1 -1
  189. package/src/web-components/interaction/form/BdsFormInput.mdx +8 -1
  190. package/src/web-components/interaction/form/BdsFormInput.stories.tsx +1 -1
  191. package/src/web-components/interaction/form/BdsNumberInput.mdx +5 -1
  192. package/src/web-components/interaction/form/BdsNumberInput.stories.tsx +1 -1
  193. package/src/web-components/interaction/form/BdsRadio.mdx +5 -1
  194. package/src/web-components/interaction/form/BdsRadio.stories.tsx +1 -1
  195. package/src/web-components/interaction/form/BdsRadioGroup.mdx +5 -1
  196. package/src/web-components/interaction/form/BdsRadioGroup.stories.tsx +1 -1
  197. package/src/web-components/interaction/form/BdsSegmentedControl.mdx +1 -1
  198. package/src/web-components/interaction/form/BdsSegmentedControl.stories.tsx +1 -1
  199. package/src/web-components/interaction/form/BdsSelect.mdx +5 -1
  200. package/src/web-components/interaction/form/BdsSelect.stories.tsx +1 -1
  201. package/src/web-components/interaction/form/BdsSlider.mdx +5 -1
  202. package/src/web-components/interaction/form/BdsSlider.stories.tsx +1 -1
  203. package/src/web-components/interaction/form/BdsSwitch.mdx +5 -1
  204. package/src/web-components/interaction/form/BdsSwitch.stories.tsx +1 -1
  205. package/src/web-components/interaction/form/BdsTextarea.mdx +5 -1
  206. package/src/web-components/interaction/form/BdsTextarea.stories.tsx +1 -1
  207. package/src/web-components/interaction/form/bds-checkbox-group.spec.ts +32 -3
  208. package/src/web-components/interaction/form/bds-checkbox-group.ts +33 -17
  209. package/src/web-components/interaction/form/bds-checkbox.ts +1 -0
  210. package/src/web-components/interaction/form/bds-combobox.ts +6 -16
  211. package/src/web-components/interaction/form/bds-form-input.ts +6 -16
  212. package/src/web-components/interaction/form/bds-number-input.ts +6 -16
  213. package/src/web-components/interaction/form/bds-radio-group.spec.ts +32 -3
  214. package/src/web-components/interaction/form/bds-radio-group.ts +26 -14
  215. package/src/web-components/interaction/form/bds-radio.ts +1 -0
  216. package/src/web-components/interaction/form/bds-select.ts +6 -16
  217. package/src/web-components/interaction/form/bds-slider.ts +5 -16
  218. package/src/web-components/interaction/form/bds-switch.ts +1 -0
  219. package/src/web-components/interaction/form/bds-textarea.ts +6 -16
  220. package/src/web-components/interaction/form/field-message.spec.ts +62 -0
  221. package/src/web-components/interaction/form/field-message.ts +55 -0
  222. package/src/web-components/layout/BdsGrid.mdx +1 -1
  223. package/src/web-components/layout/BdsGrid.stories.tsx +1 -1
  224. package/src/web-components/layout/BdsGridItem.mdx +1 -1
  225. package/src/web-components/layout/BdsGridItem.stories.tsx +1 -1
  226. package/src/web-components/ui/BdsAlert.mdx +19 -1
  227. package/src/web-components/ui/BdsAlert.stories.tsx +29 -3
  228. package/src/web-components/ui/BdsAvatar.mdx +20 -3
  229. package/src/web-components/ui/BdsAvatar.stories.tsx +25 -2
  230. package/src/web-components/ui/BdsBadge.mdx +1 -1
  231. package/src/web-components/ui/BdsBadge.stories.tsx +1 -1
  232. package/src/web-components/ui/BdsBreadcrumb.mdx +1 -1
  233. package/src/web-components/ui/BdsBreadcrumb.stories.tsx +1 -1
  234. package/src/web-components/ui/BdsButtonContainer.mdx +1 -1
  235. package/src/web-components/ui/BdsButtonContainer.stories.tsx +1 -1
  236. package/src/web-components/ui/BdsCalendar.mdx +1 -1
  237. package/src/web-components/ui/BdsCalendar.stories.tsx +1 -1
  238. package/src/web-components/ui/BdsCalendarRange.mdx +1 -1
  239. package/src/web-components/ui/BdsCalendarRange.stories.tsx +1 -1
  240. package/src/web-components/ui/BdsCard.mdx +1 -1
  241. package/src/web-components/ui/BdsCard.stories.tsx +1 -1
  242. package/src/web-components/ui/BdsCarousel.mdx +1 -1
  243. package/src/web-components/ui/BdsCarousel.stories.tsx +1 -1
  244. package/src/web-components/ui/BdsDescriptionList.mdx +1 -1
  245. package/src/web-components/ui/BdsDescriptionList.stories.tsx +1 -1
  246. package/src/web-components/ui/BdsIconWrapper.mdx +1 -1
  247. package/src/web-components/ui/BdsIconWrapper.stories.tsx +1 -1
  248. package/src/web-components/ui/BdsLink.mdx +1 -1
  249. package/src/web-components/ui/BdsLink.stories.tsx +1 -1
  250. package/src/web-components/ui/BdsLoading.mdx +1 -1
  251. package/src/web-components/ui/BdsLoading.stories.tsx +1 -1
  252. package/src/web-components/ui/BdsNotificationBanner.mdx +10 -1
  253. package/src/web-components/ui/BdsNotificationBanner.stories.tsx +29 -2
  254. package/src/web-components/ui/BdsPagination.mdx +1 -1
  255. package/src/web-components/ui/BdsPagination.stories.tsx +1 -1
  256. package/src/web-components/ui/BdsProgress.mdx +1 -1
  257. package/src/web-components/ui/BdsProgress.stories.tsx +1 -1
  258. package/src/web-components/ui/BdsProgressCircle.mdx +1 -1
  259. package/src/web-components/ui/BdsProgressCircle.stories.tsx +1 -1
  260. package/src/web-components/ui/BdsRating.mdx +1 -1
  261. package/src/web-components/ui/BdsRating.stories.tsx +1 -1
  262. package/src/web-components/ui/BdsSectionHeader.mdx +18 -6
  263. package/src/web-components/ui/BdsSectionHeader.stories.tsx +10 -2
  264. package/src/web-components/ui/BdsSeparator.mdx +2 -1
  265. package/src/web-components/ui/BdsSeparator.stories.tsx +13 -1
  266. package/src/web-components/ui/BdsSkeleton.mdx +1 -1
  267. package/src/web-components/ui/BdsSkeleton.stories.tsx +1 -1
  268. package/src/web-components/ui/BdsTable.mdx +5 -1
  269. package/src/web-components/ui/BdsTable.stories.tsx +1 -1
  270. package/src/web-components/ui/BdsTypography.mdx +1 -1
  271. package/src/web-components/ui/BdsTypography.stories.tsx +1 -1
  272. package/src/web-components/ui/bds-alert.spec.ts +27 -0
  273. package/src/web-components/ui/bds-alert.ts +34 -1
  274. package/src/web-components/ui/bds-avatar.spec.ts +47 -0
  275. package/src/web-components/ui/bds-avatar.ts +36 -3
  276. package/src/web-components/ui/bds-notification-banner.spec.ts +45 -0
  277. package/src/web-components/ui/bds-notification-banner.ts +53 -1
  278. package/src/web-components/ui/bds-section-header.spec.ts +36 -3
  279. package/src/web-components/ui/bds-section-header.ts +32 -10
  280. package/src/web-components/ui/bds-separator.spec.ts +8 -0
  281. package/src/web-components/ui/bds-separator.ts +7 -0
  282. package/src/web-components/ui/bds-table.spec.ts +11 -0
  283. package/src/web-components/ui/bds-table.ts +5 -5
  284. package/dist/web-components/chunk-QZAIRJ75.js +0 -111
@@ -48,6 +48,8 @@ The override surface is **layered**. Setting `--tab_color` / `--tab_border-color
48
48
  <tbody>
49
49
  <tr><td>`--tab_color`</td><td>per state</td><td>Tab text colour. Set to theme every state at once.</td></tr>
50
50
  <tr><td>`--tab_border-color`</td><td>per state</td><td>Tab block-end border colour.</td></tr>
51
+ <tr><td>`--tab_font-weight`</td><td>per state</td><td>Tab font weight. Set to theme every state at once.</td></tr>
52
+ <tr><td>`--tab_indicator-width`</td><td>`3px`</td><td>Thickness of the block-end indicator line.</td></tr>
51
53
  </tbody>
52
54
  </table>
53
55
 
@@ -55,16 +57,16 @@ The override surface is **layered**. Setting `--tab_color` / `--tab_border-color
55
57
 
56
58
  <table>
57
59
  <thead>
58
- <tr><th>State</th><th>Text</th><th>Border</th></tr>
60
+ <tr><th>State</th><th>Text</th><th>Border</th><th>Font weight</th></tr>
59
61
  </thead>
60
62
  <tbody>
61
- <tr><td>resting</td><td>(`var(--bds-color_on-bg)`)</td><td>(`transparent`)</td></tr>
62
- <tr><td>hover</td><td>`--tab_color--hover`</td><td>—</td></tr>
63
- <tr><td>active</td><td>`--tab_color--active`</td><td>`--tab_border-color--active`</td></tr>
63
+ <tr><td>resting</td><td>`--tab_color--inactive`</td><td>(`transparent`)</td><td>`--tab_font-weight--inactive`</td></tr>
64
+ <tr><td>hover</td><td>`--tab_color--hover`</td><td>—</td><td>—</td></tr>
65
+ <tr><td>active</td><td>`--tab_color--active`</td><td>`--tab_border-color--active`</td><td>`--tab_font-weight--active`</td></tr>
64
66
  </tbody>
65
67
  </table>
66
68
 
67
- Defaults: hover/active text resolves to `--bds-color_interactive_on-bg`; active border to `--bds-color_interactive`.
69
+ Defaults: resting text is `--bds-color_on-bg--muted` (falls back to `--bds-color_on-bg`) at `--bds-font_weight--medium`; hover and active text are `--bds-color_on-bg`; active is `--bds-font_weight--bold` with a `--bds-color_interactive` indicator.
68
70
 
69
71
  ### Spacing tokens
70
72
 
@@ -80,6 +82,10 @@ Defaults: hover/active text resolves to `--bds-color_interactive_on-bg`; active
80
82
  </tbody>
81
83
  </table>
82
84
 
85
+ ## Layout stability
86
+
87
+ The label sits in a `<span data-label>` with a hidden `::after` that repeats the text at the active weight (`--tab_font-weight--active`), so the tab keeps its bold width and selecting a tab does not shift the row. The text comes from `TabItem.label` (strings, numbers and nested elements); the hidden copy is invisible and not read by screen readers.
88
+
83
89
  ## Accessibility
84
90
 
85
91
  - Implements ARIA tabs pattern: `role="tablist"`, `role="tab"`, `role="tabpanel"`
@@ -17,19 +17,37 @@
17
17
  padding: var(--tab_padding, var(--bds-space_s) var(--bds-space_m));
18
18
  font-family: var(--bds-font_family--body);
19
19
  font-size: var(--bds-font_size--body);
20
- font-weight: var(--bds-font_weight--semibold);
20
+ font-weight: var(--tab_font-weight, var(--tab_font-weight--state, var(--tab_font-weight--inactive, var(--bds-font_weight--medium))));
21
21
 
22
22
  /* Layered cascade: public overrides (--tab_color, --tab_border-color) win over
23
23
  per-state defaults. Active/hover write to the inner --tab_*--state slot. */
24
- color: var(--tab_color, var(--tab_color--state, var(--bds-color_on-bg)));
25
- border-block-end: 2px solid var(--tab_border-color, var(--tab_border-color--state, transparent));
24
+ color: var(--tab_color, var(--tab_color--state, var(--tab_color--inactive, var(--bds-color_on-bg--muted, var(--bds-color_on-bg)))));
25
+ border-block-end: var(--tab_indicator-width, 3px) solid var(--tab_border-color, var(--tab_border-color--state, transparent));
26
26
  margin-block-end: -1px;
27
27
  cursor: pointer;
28
28
  transition: var(--bds-animation_transition);
29
29
  }
30
30
 
31
+ /* Reserves the width of the bold label so selecting a tab does not shift the row.
32
+ The hidden ::after repeats the label at the active weight in the same grid cell:
33
+ it adds width but no height and stays out of the accessibility tree. */
34
+ .label {
35
+ display: inline-grid;
36
+ }
37
+
38
+ .label::after {
39
+ content: attr(data-label);
40
+ grid-area: 1 / 1;
41
+ font-weight: var(--tab_font-weight, var(--tab_font-weight--active, var(--bds-font_weight--bold)));
42
+ visibility: hidden;
43
+ pointer-events: none;
44
+ block-size: 0;
45
+ overflow: hidden;
46
+ }
47
+
31
48
  .tab.--active {
32
- --tab_color--state: var(--tab_color--active, var(--bds-color_interactive_on-bg));
49
+ --tab_color--state: var(--tab_color--active, var(--bds-color_on-bg));
50
+ --tab_font-weight--state: var(--tab_font-weight--active, var(--bds-font_weight--bold));
33
51
  --tab_border-color--state: var(--tab_border-color--active, var(--bds-color_interactive));
34
52
  }
35
53
 
@@ -46,7 +64,7 @@
46
64
 
47
65
  @media (hover: hover) and (pointer: fine) {
48
66
  .tab:not(:disabled, .--active):hover {
49
- --tab_color--state: var(--tab_color--hover, var(--bds-color_interactive_on-bg));
67
+ --tab_color--state: var(--tab_color--hover, var(--bds-color_on-bg));
50
68
  }
51
69
  }
52
70
 
@@ -1,3 +1,5 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { resolve } from 'node:path';
1
3
  import { render, screen } from '@testing-library/react';
2
4
  import userEvent from '@testing-library/user-event';
3
5
  import { Tabs } from './Tabs';
@@ -108,4 +110,41 @@ describe('Tabs', () => {
108
110
  render(<Tabs tabs={tabs} />);
109
111
  expect(screen.getByText('First panel').closest('[role="tabpanel"]')).toHaveAttribute('tabindex', '0');
110
112
  });
113
+
114
+ it('wraps the label with a data-label that reserves the bold width', () => {
115
+ render(<Tabs tabs={[{ id: 'a', label: <>Inbox <em>4</em></>, content: null }]} />);
116
+ const label = screen.getByRole('tab').querySelector('span');
117
+ expect(label).toHaveAttribute('data-label', 'Inbox 4');
118
+ expect(label).toHaveTextContent('Inbox 4');
119
+ });
120
+
121
+ describe('styling hooks', () => {
122
+ it('reserves the active font weight through a hidden ::after', () => {
123
+ const rules = readFileSync(resolve(process.cwd(), 'src/components/ui/Tabs/Tabs.module.css'), 'utf8');
124
+ expect(rules).toMatch(/\.label\s*\{\s*display:\s*inline-grid;/);
125
+ expect(rules).toMatch(/\.label::after\s*\{[^}]*content:\s*attr\(data-label\)/);
126
+ expect(rules).toMatch(/\.label::after\s*\{[^}]*font-weight:\s*var\(--tab_font-weight,\s*var\(--tab_font-weight--active,\s*var\(--bds-font_weight--bold\)\)\)/);
127
+ expect(rules).toMatch(/\.label::after\s*\{[^}]*visibility:\s*hidden/);
128
+ });
129
+
130
+ const css = readFileSync(resolve(process.cwd(), 'src/components/ui/Tabs/Tabs.module.css'), 'utf8');
131
+
132
+ it('styles the resting tab muted and medium', () => {
133
+ expect(css).toMatch(/color:\s*var\(--tab_color,\s*var\(--tab_color--state,\s*var\(--tab_color--inactive,\s*var\(--bds-color_on-bg--muted,\s*var\(--bds-color_on-bg\)\)\)\)\)/);
134
+ expect(css).toMatch(/font-weight:\s*var\(--tab_font-weight,\s*var\(--tab_font-weight--state,\s*var\(--tab_font-weight--inactive,\s*var\(--bds-font_weight--medium\)\)\)\)/);
135
+ });
136
+
137
+ it('styles the active tab in the full text colour and bold', () => {
138
+ expect(css).toMatch(/--tab_color--state:\s*var\(--tab_color--active,\s*var\(--bds-color_on-bg\)\)/);
139
+ expect(css).toMatch(/--tab_font-weight--state:\s*var\(--tab_font-weight--active,\s*var\(--bds-font_weight--bold\)\)/);
140
+ });
141
+
142
+ it('sizes the indicator through --tab_indicator-width', () => {
143
+ expect(css).toMatch(/border-block-end:\s*var\(--tab_indicator-width,\s*3px\) solid/);
144
+ });
145
+
146
+ it('shows the full text colour on hover', () => {
147
+ expect(css).toMatch(/--tab_color--state:\s*var\(--tab_color--hover,\s*var\(--bds-color_on-bg\)\)/);
148
+ });
149
+ });
111
150
  });
@@ -2,6 +2,7 @@ import { HTMLAttributes, KeyboardEvent, ReactNode, useId, useRef, useState } fro
2
2
  import css from './Tabs.module.css';
3
3
  import { cn } from '@boostdev/design-system-foundation';
4
4
  import type { WithClassName } from '../../../types';
5
+ import { getNodeText } from './getNodeText';
5
6
 
6
7
  export interface TabItem {
7
8
  id: string;
@@ -74,7 +75,7 @@ export function Tabs({ tabs, defaultTab, className, ...rest }: Readonly<TabsProp
74
75
  onClick={() => setActiveTab(tab.id)}
75
76
  onKeyDown={e => handleKeyDown(e, i)}
76
77
  >
77
- {tab.label}
78
+ <span className={css.label} data-label={getNodeText(tab.label)}>{tab.label}</span>
78
79
  </button>
79
80
  );
80
81
  })}
@@ -0,0 +1,23 @@
1
+ import { getNodeText } from './getNodeText';
2
+
3
+ describe('getNodeText', () => {
4
+ it('returns strings and numbers as text', () => {
5
+ expect(getNodeText('Overview')).toBe('Overview');
6
+ expect(getNodeText(3)).toBe('3');
7
+ });
8
+
9
+ it('ignores booleans, null and undefined', () => {
10
+ expect(getNodeText(null)).toBe('');
11
+ expect(getNodeText(undefined)).toBe('');
12
+ expect(getNodeText(false)).toBe('');
13
+ expect(getNodeText(true)).toBe('');
14
+ });
15
+
16
+ it('joins arrays', () => {
17
+ expect(getNodeText(['Inbox ', 4, false])).toBe('Inbox 4');
18
+ });
19
+
20
+ it('reads element children recursively', () => {
21
+ expect(getNodeText(<span>Inbox <strong>(<em>4</em>)</strong></span>)).toBe('Inbox (4)');
22
+ });
23
+ });
@@ -0,0 +1,13 @@
1
+ import { isValidElement } from 'react';
2
+ import type { ReactNode } from 'react';
3
+
4
+ /**
5
+ * Plain text of a ReactNode: strings and numbers as written, arrays and element
6
+ * children joined, booleans/null/undefined ignored. Pure, so it also runs on the server.
7
+ */
8
+ export function getNodeText(node: ReactNode): string {
9
+ if (typeof node === 'string' || typeof node === 'number') return String(node);
10
+ if (Array.isArray(node)) return node.map(getNodeText).join('');
11
+ if (isValidElement<{ children?: ReactNode }>(node)) return getNodeText(node.props.children);
12
+ return '';
13
+ }
@@ -29,6 +29,9 @@ Short contextual label that appears on hover or focus. Use to supplement icon bu
29
29
  ### Right
30
30
  <Canvas of={Stories.Right} />
31
31
 
32
+ ### Long text
33
+ <Canvas of={Stories.LongText} />
34
+
32
35
  ### All placements
33
36
  <Canvas of={Stories.AllPlacements} />
34
37
 
@@ -48,11 +51,11 @@ Short contextual label that appears on hover or focus. Use to supplement icon bu
48
51
  <tbody>
49
52
  <tr><td>`--tooltip_bg`</td><td>`var(--bds-color_on-bg)`</td><td>Tooltip background colour</td></tr>
50
53
  <tr><td>`--tooltip_text`</td><td>`var(--bds-color_bg)`</td><td>Tooltip text colour</td></tr>
51
- <tr><td>`--tooltip_radius`</td><td>`var(--bds-border_radius--full)`</td><td>Tooltip corner radius</td></tr>
52
- <tr><td>`--tooltip_padding`</td><td>`var(--bds-space_xxs) var(--bds-space_xs)`</td><td>Tooltip padding</td></tr>
54
+ <tr><td>`--tooltip_radius`</td><td>`var(--bds-border_radius--xs)`</td><td>Tooltip corner radius</td></tr>
55
+ <tr><td>`--tooltip_padding`</td><td>`var(--bds-space_xxs) var(--bds-space_s)`</td><td>Tooltip padding</td></tr>
53
56
  <tr><td>`--tooltip_font-size`</td><td>`var(--bds-font_size--body--s)`</td><td>Tooltip text size</td></tr>
54
57
  <tr><td>`--tooltip_offset`</td><td>`var(--bds-space_xs)`</td><td>Gap between the trigger and the tooltip. Set to `0` to close the gap so the pointer can travel from the trigger onto the tooltip without a dead zone.</td></tr>
55
- <tr><td>`--tooltip_max-inline-size`</td><td>`20rem`</td><td>Maximum inline size before content wraps</td></tr>
58
+ <tr><td>`--tooltip_max-inline-size`</td><td>`20rem`</td><td>Maximum inline size before content wraps. The tooltip is as wide as its text (`max-content`) up to this value</td></tr>
56
59
  </tbody>
57
60
  </table>
58
61
 
@@ -17,12 +17,16 @@
17
17
  display: block;
18
18
  position: absolute;
19
19
  z-index: var(--bds-z-index_popover);
20
- padding: var(--tooltip_padding, var(--bds-space_xxs) var(--bds-space_xs));
21
- border-radius: var(--tooltip_radius, var(--bds-border_radius--full));
20
+ padding: var(--tooltip_padding, var(--bds-space_xxs) var(--bds-space_s));
21
+ border-radius: var(--tooltip_radius, var(--bds-border_radius--xs));
22
22
  background-color: var(--tooltip_bg, var(--bds-color_on-bg));
23
23
  color: var(--tooltip_text, var(--bds-color_bg));
24
24
  font-size: var(--tooltip_font-size, var(--bds-font_size--body--s));
25
25
  line-height: var(--bds-font_line-height--body);
26
+
27
+ /* Size to the text, not to the (possibly narrow) trigger wrapper the
28
+ tooltip is absolutely positioned in; wrap only at the max width. */
29
+ inline-size: max-content;
26
30
  max-inline-size: var(--tooltip_max-inline-size, 20rem);
27
31
  white-space: normal;
28
32
  pointer-events: none;
@@ -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 {
@@ -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'] },