@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
@@ -5,9 +5,9 @@ import * as Stories from './BdsDropdownMenu.stories';
5
5
 
6
6
  # <bds-dropdown-menu>
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
 
@@ -37,7 +37,7 @@ function ToastDemo() {
37
37
  const meta = {
38
38
  title: 'Web Components/Interaction/ToastProvider',
39
39
  component: ToastDemo,
40
- tags: ['!stable', 'experimental'],
40
+ tags: ['!stable', 'alpha'],
41
41
  parameters: { layout: 'centered' },
42
42
  } satisfies Meta<typeof ToastDemo>;
43
43
 
@@ -7,7 +7,7 @@ import * as Stories from './BdsTooltip.stories';
7
7
 
8
8
  Framework-agnostic Tooltip custom element. Displays a small informational label on hover and keyboard focus using CSS-only visibility — no JavaScript positioning required.
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
 
@@ -52,6 +52,9 @@ Or in HTML without a bundler:
52
52
  ### Right placement
53
53
  <Canvas of={Stories.Right} />
54
54
 
55
+ ### Long text
56
+ <Canvas of={Stories.LongText} />
57
+
55
58
  ### All placements
56
59
  <Canvas of={Stories.AllPlacements} />
57
60
 
@@ -74,10 +77,15 @@ Or in HTML without a bundler:
74
77
 
75
78
  ## CSS Custom Properties
76
79
 
77
- | Property | Description |
78
- |----------|-------------|
79
- | `--tooltip_bg` | Tooltip background colour (default: `var(--bds-color_on-bg)`) |
80
- | `--tooltip_text` | Tooltip text colour (default: `var(--bds-color_bg)`) |
80
+ | Property | Default | Description |
81
+ |----------|---------|-------------|
82
+ | `--tooltip_bg` | `var(--bds-color_on-bg)` | Tooltip background colour |
83
+ | `--tooltip_text` | `var(--bds-color_bg)` | Tooltip text colour |
84
+ | `--tooltip_radius` | `var(--bds-border_radius--xs)` | Tooltip corner radius |
85
+ | `--tooltip_padding` | `var(--bds-space_xxs) var(--bds-space_s)` | Tooltip padding |
86
+ | `--tooltip_font-size` | `var(--bds-font_size--body--s)` | Tooltip text size |
87
+ | `--tooltip_offset` | `var(--bds-space_xs)` | Gap between the trigger and the tooltip |
88
+ | `--tooltip_max-inline-size` | `20rem` | Maximum inline size before content wraps. The tooltip is as wide as its text (`max-content`) up to this value |
81
89
 
82
90
  ## Usage in plain HTML
83
91
 
@@ -16,14 +16,14 @@ function BdsTooltip({
16
16
  return React.createElement(
17
17
  'bds-tooltip',
18
18
  { content, placement },
19
- children ?? React.createElement('button', { type: 'button' }, 'Hover me'),
19
+ children ?? React.createElement('bds-button', null, 'Hover me'),
20
20
  );
21
21
  }
22
22
 
23
23
  const meta = {
24
24
  title: 'Web Components/UI/Tooltip',
25
25
  component: BdsTooltip,
26
- tags: ['!stable', 'experimental'],
26
+ tags: ['!stable', 'alpha'],
27
27
  parameters: { layout: 'centered' },
28
28
  argTypes: {
29
29
  content: { control: 'text' },
@@ -44,11 +44,7 @@ export const OnButton: Story = {
44
44
  React.createElement(
45
45
  'bds-tooltip',
46
46
  { content: args.content, placement: args.placement },
47
- React.createElement(
48
- 'button',
49
- { type: 'button', style: { padding: '0.5rem 1rem', cursor: 'pointer' } },
50
- 'Save',
51
- ),
47
+ React.createElement('bds-button', null, 'Save'),
52
48
  ),
53
49
  };
54
50
 
@@ -64,6 +60,14 @@ export const Right: Story = {
64
60
  args: { content: 'Appears to the right', placement: 'right' },
65
61
  };
66
62
 
63
+ export const LongText: Story = {
64
+ args: {
65
+ content:
66
+ 'Longer explanation that wraps onto a second line once it reaches the maximum width of the tooltip.',
67
+ placement: 'bottom',
68
+ },
69
+ };
70
+
67
71
  export const AllPlacements: Story = {
68
72
  render: () => (
69
73
  <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, auto)', gap: '4rem', padding: '3rem' }}>
@@ -74,11 +78,7 @@ export const AllPlacements: Story = {
74
78
  React.createElement(
75
79
  'bds-tooltip',
76
80
  { content: `Placement: ${placement}`, placement },
77
- React.createElement(
78
- 'button',
79
- { type: 'button', style: { padding: '0.5rem 1rem', cursor: 'pointer' } },
80
- placement,
81
- ),
81
+ React.createElement('bds-button', null, placement),
82
82
  ),
83
83
  ),
84
84
  )}
@@ -0,0 +1,72 @@
1
+ import { LitElement, css, html, nothing } from 'lit';
2
+
3
+ /**
4
+ * `<bds-dropdown-menu-group>` — a labelled group of `<bds-dropdown-menu-item>`
5
+ * elements inside a `<bds-dropdown-menu>`.
6
+ *
7
+ * The shadow root renders a `role="group"` element named by the visible label
8
+ * (`aria-labelledby` inside the same shadow root). The label is not focusable;
9
+ * keyboard navigation in the menu only visits the items.
10
+ *
11
+ * Attributes:
12
+ * label — visible group label, also the accessible name of the group
13
+ *
14
+ * Slots:
15
+ * (default) — `<bds-dropdown-menu-item>` elements
16
+ *
17
+ * @example
18
+ * <bds-dropdown-menu-group label="Edit">
19
+ * <bds-dropdown-menu-item value="edit">Edit</bds-dropdown-menu-item>
20
+ * </bds-dropdown-menu-group>
21
+ */
22
+ export class BdsDropdownMenuGroup extends LitElement {
23
+ static styles = css`
24
+ /* Shadow DOM does not inherit the global box-sizing reset, so set it here. */
25
+ :host,
26
+ *,
27
+ *::before,
28
+ *::after {
29
+ box-sizing: border-box;
30
+ }
31
+
32
+ :host {
33
+ display: block;
34
+ }
35
+
36
+ .label {
37
+ padding: var(--dropdown_group-label-padding, var(--bds-space_xs) var(--bds-space_s) var(--bds-space_xxs));
38
+ font-family: var(--bds-font_family--body);
39
+ font-size: var(--dropdown_group-label-font-size, var(--bds-font_size--body--s));
40
+ font-weight: var(--dropdown_group-label-font-weight, var(--bds-font_weight--bold));
41
+ color: var(--dropdown_group-label-color, var(--bds-color_on-bg--muted, var(--bds-color_on-bg)));
42
+ }
43
+ `;
44
+
45
+ static properties = {
46
+ label: { type: String, reflect: true },
47
+ };
48
+
49
+ declare label: string;
50
+
51
+ constructor() {
52
+ super();
53
+ this.label = '';
54
+ }
55
+
56
+ render() {
57
+ return html`
58
+ <div role="group" aria-labelledby=${this.label ? 'label' : nothing}>
59
+ ${this.label ? html`<div id="label" class="label">${this.label}</div>` : nothing}
60
+ <slot></slot>
61
+ </div>
62
+ `;
63
+ }
64
+ }
65
+
66
+ customElements.define('bds-dropdown-menu-group', BdsDropdownMenuGroup);
67
+
68
+ declare global {
69
+ interface HTMLElementTagNameMap {
70
+ 'bds-dropdown-menu-group': BdsDropdownMenuGroup;
71
+ }
72
+ }
@@ -1,4 +1,4 @@
1
- import { LitElement, css, html } from 'lit';
1
+ import { LitElement, css, html, nothing } from 'lit';
2
2
 
3
3
  /**
4
4
  * `<bds-dropdown-menu-item>` — a single item inside a `<bds-dropdown-menu>`.
@@ -6,9 +6,12 @@ import { LitElement, css, html } from 'lit';
6
6
  * Attributes:
7
7
  * value — value associated with this item
8
8
  * disabled — disables this item
9
- * destructive — renders the item in a destructive (red) style
9
+ * destructive — renders the item in a destructive (error colour) style
10
+ * shortcut — keyboard shortcut as display text (decorative, `aria-hidden`);
11
+ * the consumer wires the actual key
10
12
  *
11
13
  * Slots:
14
+ * icon — optional icon shown before the label (decorative)
12
15
  * (default) — item label text
13
16
  *
14
17
  * Events:
@@ -34,7 +37,7 @@ export class BdsDropdownMenuItem extends LitElement {
34
37
  }
35
38
 
36
39
  :host([disabled]) {
37
- opacity: 0.5;
40
+ opacity: var(--dropdown_item-opacity--disabled, 0.4);
38
41
  pointer-events: none;
39
42
  }
40
43
 
@@ -43,36 +46,67 @@ export class BdsDropdownMenuItem extends LitElement {
43
46
  align-items: center;
44
47
  gap: var(--bds-space_xs);
45
48
  inline-size: 100%;
46
- padding: var(--bds-space_xs) var(--bds-space_s);
47
- font-size: var(--bds-font_size--body);
49
+ padding: var(--dropdown_item-padding, var(--bds-space_xs) var(--bds-space_s));
50
+ font-size: var(--dropdown_item-font-size, var(--bds-font_size--body));
48
51
  font-family: var(--bds-font_family--body);
49
- color: var(--bds-color_on-bg);
52
+ color: inherit;
50
53
  background: none;
51
54
  border: none;
52
55
  text-align: start;
53
56
  cursor: pointer;
54
- border-radius: var(--bds-border_radius--xs);
57
+ border-radius: var(--dropdown_item-radius, var(--bds-border_radius--xs));
55
58
  transition: var(--bds-animation_transition);
56
59
  }
57
60
 
58
61
  :host([destructive]) .item {
59
- color: var(--bds-color_error);
62
+ color: var(--dropdown_item-color--destructive, var(--bds-color_error_on-bg));
63
+ }
64
+
65
+ .item:focus-visible {
66
+ outline: var(--bds-outline_default);
67
+ outline-offset: calc(var(--bds-outline_offset) * -1);
68
+ }
69
+
70
+ .item:not(:disabled):focus-visible {
71
+ background-color: var(--dropdown_item-bg--hover, var(--bds-color_primary--subtle, var(--bds-color_blue--subtle)));
72
+ color: var(--dropdown_item-color--hover, var(--bds-color_on-primary--subtle, var(--bds-color_on-blue--subtle)));
73
+ }
74
+
75
+ :host([destructive]) .item:not(:disabled):focus-visible {
76
+ background-color: var(--dropdown_item-bg--destructive-hover, var(--bds-color_error--subtle));
77
+ color: var(--dropdown_item-color--destructive-hover, var(--bds-color_on-error--subtle));
60
78
  }
61
79
 
62
80
  @media (hover: hover) and (pointer: fine) {
63
- .item:hover {
64
- background-color: var(--dropdown_item-bg--hover, var(--bds-color_bg--subtle));
65
- color: var(--dropdown_item-color--hover, var(--bds-color_interactive_on-bg));
81
+ .item:not(:disabled):hover {
82
+ background-color: var(--dropdown_item-bg--hover, var(--bds-color_primary--subtle, var(--bds-color_blue--subtle)));
83
+ color: var(--dropdown_item-color--hover, var(--bds-color_on-primary--subtle, var(--bds-color_on-blue--subtle)));
66
84
  }
67
85
 
68
- :host([destructive]) .item:hover {
69
- background-color: color-mix(in srgb, var(--bds-color_error) 10%, transparent);
86
+ :host([destructive]) .item:not(:disabled):hover {
87
+ background-color: var(--dropdown_item-bg--destructive-hover, var(--bds-color_error--subtle));
88
+ color: var(--dropdown_item-color--destructive-hover, var(--bds-color_on-error--subtle));
70
89
  }
71
90
  }
72
91
 
73
- .item:focus-visible {
74
- outline: var(--bds-outline_default);
75
- outline-offset: var(--bds-outline_offset);
92
+ .icon[hidden] {
93
+ display: none;
94
+ }
95
+
96
+ .icon {
97
+ display: flex;
98
+ align-items: center;
99
+ flex-shrink: 0;
100
+ }
101
+
102
+ .label {
103
+ flex: 1;
104
+ }
105
+
106
+ .shortcut {
107
+ flex-shrink: 0;
108
+ color: var(--dropdown_shortcut-color, var(--bds-color_on-bg--muted, var(--bds-color_on-bg)));
109
+ font-size: var(--dropdown_shortcut-font-size, var(--bds-font_size--body--s));
76
110
  }
77
111
  `;
78
112
 
@@ -80,17 +114,27 @@ export class BdsDropdownMenuItem extends LitElement {
80
114
  value: { type: String, reflect: true },
81
115
  disabled: { type: Boolean, reflect: true },
82
116
  destructive: { type: Boolean, reflect: true },
117
+ shortcut: { type: String, reflect: true },
118
+ _hasIcon: { state: true },
83
119
  };
84
120
 
85
121
  declare value: string;
86
122
  declare disabled: boolean;
87
123
  declare destructive: boolean;
124
+ declare shortcut: string;
125
+ declare _hasIcon: boolean;
88
126
 
89
127
  constructor() {
90
128
  super();
91
129
  this.value = '';
92
130
  this.disabled = false;
93
131
  this.destructive = false;
132
+ this.shortcut = '';
133
+ this._hasIcon = false;
134
+ }
135
+
136
+ private _onIconSlotChange(e: Event) {
137
+ this._hasIcon = (e.target as HTMLSlotElement).assignedNodes().length > 0;
94
138
  }
95
139
 
96
140
  private _handleClick() {
@@ -120,7 +164,11 @@ export class BdsDropdownMenuItem extends LitElement {
120
164
  @click=${this._handleClick}
121
165
  @keydown=${this._handleKeydown}
122
166
  >
123
- <slot></slot>
167
+ <span class="icon" aria-hidden="true" ?hidden=${!this._hasIcon}>
168
+ <slot name="icon" @slotchange=${this._onIconSlotChange}></slot>
169
+ </span>
170
+ <span class="label"><slot></slot></span>
171
+ ${this.shortcut ? html`<span class="shortcut" aria-hidden="true">${this.shortcut}</span>` : nothing}
124
172
  </button>
125
173
  `;
126
174
  }