@boostdev/design-system-components 2.14.1 → 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.
- package/AGENTS.md +20 -15
- package/dist/client.cjs +271 -205
- package/dist/client.css +808 -648
- package/dist/client.d.cts +19 -4
- package/dist/client.d.ts +19 -4
- package/dist/client.js +206 -139
- package/dist/index.cjs +271 -205
- package/dist/index.css +808 -648
- package/dist/index.d.cts +19 -4
- package/dist/index.d.ts +19 -4
- package/dist/index.js +206 -139
- package/dist/web-components/chunk-2DHW2WJZ.js +154 -0
- package/dist/web-components/{chunk-LDIPCTRN.js → chunk-2MJTO2IW.js} +48 -2
- package/dist/web-components/{chunk-3WAV6MDN.js → chunk-3FSGP35V.js} +1 -0
- package/dist/web-components/{chunk-KA3VPKMY.js → chunk-4MB2ICSK.js} +1 -0
- package/dist/web-components/{chunk-IDSM74LM.js → chunk-6XL5P76D.js} +3 -3
- package/dist/web-components/{chunk-P24JYC5V.js → chunk-7VXRMCAL.js} +10 -4
- package/dist/web-components/{chunk-CUKQ2L5B.js → chunk-AGI6YQRC.js} +9 -16
- package/dist/web-components/chunk-BDRV452N.js +51 -0
- package/dist/web-components/{chunk-3AY2YKCM.js → chunk-CKCPV347.js} +1 -0
- package/dist/web-components/{chunk-HBLJ4SLY.js → chunk-DD3OUXNG.js} +5 -5
- package/dist/web-components/{chunk-RVF7W653.js → chunk-DGOCPKHI.js} +30 -10
- package/dist/web-components/{chunk-2OLVQUBU.js → chunk-EYCW7TKB.js} +8 -15
- package/dist/web-components/{chunk-VANAKB6D.js → chunk-GPJWLAKU.js} +33 -16
- package/dist/web-components/{chunk-VED2DFJ6.js → chunk-GQNQBEYR.js} +8 -15
- package/dist/web-components/{chunk-WFVKU4GX.js → chunk-IKAJLROF.js} +49 -4
- package/dist/web-components/{chunk-RSZ3BWBK.js → chunk-KSK4RZZQ.js} +30 -7
- package/dist/web-components/{chunk-FEDABOR5.js → chunk-LHFUXZ52.js} +7 -15
- package/dist/web-components/{chunk-M3ECULRH.js → chunk-RBF7WPLI.js} +10 -8
- package/dist/web-components/{chunk-6G22I2CK.js → chunk-RZH5IVB5.js} +31 -1
- package/dist/web-components/chunk-SRKQ6GST.js +40 -0
- package/dist/web-components/{chunk-5HUAFCU6.js → chunk-TJV7UIXC.js} +7 -0
- package/dist/web-components/{chunk-J3HVUIUH.js → chunk-XI2U6U26.js} +8 -15
- package/dist/web-components/{chunk-JH6LQKLK.js → chunk-XJU7KITO.js} +8 -15
- package/dist/web-components/{chunk-XIZWAWMJ.js → chunk-XTPUKUN5.js} +16 -6
- package/dist/web-components/{chunk-JV5QT2OU.js → chunk-YLDQOESI.js} +27 -13
- package/dist/web-components/globals.js +1 -1
- package/dist/web-components/index.d.ts +1 -0
- package/dist/web-components/index.js +34 -29
- package/dist/web-components/interaction/bds-button.js +1 -1
- package/dist/web-components/interaction/bds-dropdown-menu-group.d.ts +41 -0
- package/dist/web-components/interaction/bds-dropdown-menu-group.js +7 -0
- package/dist/web-components/interaction/bds-dropdown-menu-item.d.ts +14 -1
- package/dist/web-components/interaction/bds-dropdown-menu-item.js +1 -1
- package/dist/web-components/interaction/bds-dropdown-menu.d.ts +2 -1
- package/dist/web-components/interaction/bds-dropdown-menu.js +1 -1
- package/dist/web-components/interaction/bds-tab.d.ts +5 -0
- package/dist/web-components/interaction/bds-tab.js +1 -1
- package/dist/web-components/interaction/bds-tooltip.js +1 -1
- package/dist/web-components/interaction/form/bds-checkbox-group.d.ts +6 -0
- package/dist/web-components/interaction/form/bds-checkbox-group.js +2 -1
- package/dist/web-components/interaction/form/bds-checkbox.js +1 -1
- package/dist/web-components/interaction/form/bds-combobox.js +2 -1
- package/dist/web-components/interaction/form/bds-form-input.js +2 -1
- package/dist/web-components/interaction/form/bds-number-input.js +2 -1
- package/dist/web-components/interaction/form/bds-radio-group.d.ts +5 -0
- package/dist/web-components/interaction/form/bds-radio-group.js +2 -1
- package/dist/web-components/interaction/form/bds-radio.js +1 -1
- package/dist/web-components/interaction/form/bds-select.js +2 -1
- package/dist/web-components/interaction/form/bds-slider.js +2 -1
- package/dist/web-components/interaction/form/bds-switch.js +1 -1
- package/dist/web-components/interaction/form/bds-textarea.js +2 -1
- package/dist/web-components/ui/bds-alert.d.ts +8 -1
- package/dist/web-components/ui/bds-alert.js +1 -1
- package/dist/web-components/ui/bds-avatar.d.ts +11 -0
- package/dist/web-components/ui/bds-avatar.js +1 -1
- package/dist/web-components/ui/bds-notification-banner.d.ts +14 -1
- package/dist/web-components/ui/bds-notification-banner.js +1 -1
- package/dist/web-components/ui/bds-section-header.d.ts +6 -0
- package/dist/web-components/ui/bds-section-header.js +1 -1
- package/dist/web-components/ui/bds-separator.js +1 -1
- package/dist/web-components/ui/bds-table.js +1 -1
- package/package.json +6 -2
- package/src/components/interaction/Button/Button.mdx +7 -0
- package/src/components/interaction/Button/Button.module.css +17 -9
- package/src/components/interaction/Button/Button.stories.tsx +28 -0
- package/src/components/interaction/DropdownMenu/DropdownMenu.mdx +35 -4
- package/src/components/interaction/DropdownMenu/DropdownMenu.module.css +58 -10
- package/src/components/interaction/DropdownMenu/DropdownMenu.spec.tsx +114 -1
- package/src/components/interaction/DropdownMenu/DropdownMenu.stories.tsx +25 -0
- package/src/components/interaction/DropdownMenu/DropdownMenu.tsx +69 -17
- package/src/components/interaction/form/Checkbox/Checkbox.module.css +1 -0
- package/src/components/interaction/form/Checkbox/Checkbox.spec.tsx +7 -0
- package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.mdx +1 -0
- package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.module.css +7 -0
- package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.spec.tsx +22 -0
- package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.tsx +1 -1
- package/src/components/interaction/form/Combobox/Combobox.module.css +1 -0
- package/src/components/interaction/form/Combobox/Combobox.spec.tsx +7 -0
- package/src/components/interaction/form/FormInput/FormInput.mdx +9 -0
- package/src/components/interaction/form/FormInput/FormInput.module.css +1 -0
- package/src/components/interaction/form/FormInput/FormInput.spec.tsx +7 -0
- package/src/components/interaction/form/NumberInput/NumberInput.module.css +1 -0
- package/src/components/interaction/form/NumberInput/NumberInput.spec.tsx +7 -0
- package/src/components/interaction/form/Radio/Radio.module.css +1 -0
- package/src/components/interaction/form/Radio/Radio.spec.tsx +7 -0
- package/src/components/interaction/form/RadioGroup/RadioGroup.mdx +1 -0
- package/src/components/interaction/form/RadioGroup/RadioGroup.module.css +7 -0
- package/src/components/interaction/form/RadioGroup/RadioGroup.spec.tsx +22 -0
- package/src/components/interaction/form/RadioGroup/RadioGroup.tsx +1 -1
- package/src/components/interaction/form/Select/Select.module.css +1 -0
- package/src/components/interaction/form/Select/Select.spec.tsx +7 -0
- package/src/components/interaction/form/Switch/Switch.module.css +1 -0
- package/src/components/interaction/form/Switch/Switch.spec.tsx +7 -0
- package/src/components/interaction/form/Textarea/Textarea.module.css +1 -0
- package/src/components/interaction/form/Textarea/Textarea.spec.tsx +7 -0
- package/src/components/interaction/form/atoms/Message.module.css +14 -3
- package/src/components/interaction/form/atoms/Message.spec.tsx +22 -0
- package/src/components/interaction/form/atoms/Message.tsx +5 -0
- package/src/components/layout/SectionHeader/SectionHeader.mdx +18 -5
- package/src/components/layout/SectionHeader/SectionHeader.module.css +35 -14
- package/src/components/layout/SectionHeader/SectionHeader.spec.tsx +44 -0
- package/src/components/layout/SectionHeader/SectionHeader.stories.tsx +5 -0
- package/src/components/layout/SectionHeader/SectionHeader.tsx +3 -1
- package/src/components/ui/Alert/Alert.mdx +11 -0
- package/src/components/ui/Alert/Alert.module.css +30 -1
- package/src/components/ui/Alert/Alert.spec.tsx +21 -0
- package/src/components/ui/Alert/Alert.stories.tsx +20 -0
- package/src/components/ui/Alert/Alert.tsx +8 -1
- package/src/components/ui/Avatar/Avatar.mdx +22 -2
- package/src/components/ui/Avatar/Avatar.module.css +29 -2
- package/src/components/ui/Avatar/Avatar.spec.tsx +26 -0
- package/src/components/ui/Avatar/Avatar.stories.tsx +23 -0
- package/src/components/ui/Avatar/Avatar.tsx +4 -2
- package/src/components/ui/Avatar/avatarTone.spec.ts +41 -0
- package/src/components/ui/Avatar/avatarTone.ts +22 -0
- package/src/components/ui/Collapsible/Collapsible.module.css +1 -2
- package/src/components/ui/NotificationBanner/NotificationBanner.mdx +14 -0
- package/src/components/ui/NotificationBanner/NotificationBanner.module.css +31 -1
- package/src/components/ui/NotificationBanner/NotificationBanner.spec.tsx +29 -0
- package/src/components/ui/NotificationBanner/NotificationBanner.stories.tsx +25 -0
- package/src/components/ui/NotificationBanner/NotificationBanner.tsx +15 -1
- package/src/components/ui/Separator/Separator.mdx +1 -0
- package/src/components/ui/Separator/Separator.module.css +6 -0
- package/src/components/ui/Separator/Separator.spec.tsx +19 -0
- package/src/components/ui/Separator/Separator.stories.tsx +15 -0
- package/src/components/ui/Table/Table.mdx +4 -1
- package/src/components/ui/Table/Table.module.css +7 -7
- package/src/components/ui/Table/Table.spec.tsx +11 -0
- package/src/components/ui/Tabs/Tabs.mdx +11 -5
- package/src/components/ui/Tabs/Tabs.module.css +23 -5
- package/src/components/ui/Tabs/Tabs.spec.tsx +39 -0
- package/src/components/ui/Tabs/Tabs.tsx +2 -1
- package/src/components/ui/Tabs/getNodeText.spec.tsx +23 -0
- package/src/components/ui/Tabs/getNodeText.ts +13 -0
- package/src/components/ui/Tooltip/Tooltip.mdx +6 -3
- package/src/components/ui/Tooltip/Tooltip.module.css +6 -2
- package/src/components/ui/Tooltip/Tooltip.spec.tsx +10 -0
- package/src/components/ui/Tooltip/Tooltip.stories.tsx +13 -0
- package/src/css/bdc.css +5 -2
- package/src/css/bdc.spec.ts +65 -0
- package/src/stories/DesignSystem/Borders.mdx +17 -9
- package/src/web-components/globals.ts +10 -4
- package/src/web-components/index.ts +1 -0
- package/src/web-components/interaction/BdsAccordion.mdx +1 -1
- package/src/web-components/interaction/BdsAccordion.stories.tsx +1 -1
- package/src/web-components/interaction/BdsButton.mdx +9 -1
- package/src/web-components/interaction/BdsButton.stories.tsx +42 -1
- package/src/web-components/interaction/BdsCollapsible.mdx +1 -1
- package/src/web-components/interaction/BdsCollapsible.stories.tsx +1 -1
- package/src/web-components/interaction/BdsDialog.mdx +1 -1
- package/src/web-components/interaction/BdsDialog.stories.tsx +1 -1
- package/src/web-components/interaction/BdsDrawer.mdx +1 -1
- package/src/web-components/interaction/BdsDrawer.stories.tsx +1 -1
- package/src/web-components/interaction/BdsDropdownMenu.mdx +62 -6
- package/src/web-components/interaction/BdsDropdownMenu.stories.tsx +32 -7
- package/src/web-components/interaction/BdsPopover.mdx +1 -1
- package/src/web-components/interaction/BdsPopover.stories.tsx +1 -1
- package/src/web-components/interaction/BdsSkipLink.mdx +1 -1
- package/src/web-components/interaction/BdsSkipLink.stories.tsx +1 -1
- package/src/web-components/interaction/BdsTabs.mdx +10 -1
- package/src/web-components/interaction/BdsTabs.stories.tsx +1 -1
- package/src/web-components/interaction/BdsToastProvider.mdx +1 -1
- package/src/web-components/interaction/BdsToastProvider.stories.tsx +1 -1
- package/src/web-components/interaction/BdsTooltip.mdx +13 -5
- package/src/web-components/interaction/BdsTooltip.stories.tsx +12 -12
- package/src/web-components/interaction/bds-button.ts +16 -6
- package/src/web-components/interaction/bds-dropdown-menu-group.ts +72 -0
- package/src/web-components/interaction/bds-dropdown-menu-item.ts +65 -17
- package/src/web-components/interaction/bds-dropdown-menu.spec.ts +135 -0
- package/src/web-components/interaction/bds-dropdown-menu.ts +5 -4
- package/src/web-components/interaction/bds-tab.spec.ts +34 -2
- package/src/web-components/interaction/bds-tab.ts +31 -6
- package/src/web-components/interaction/bds-tooltip.spec.ts +16 -0
- package/src/web-components/interaction/bds-tooltip.ts +10 -8
- package/src/web-components/interaction/form/BdsCheckbox.mdx +5 -1
- package/src/web-components/interaction/form/BdsCheckbox.stories.tsx +1 -1
- package/src/web-components/interaction/form/BdsCheckboxGroup.mdx +5 -1
- package/src/web-components/interaction/form/BdsCheckboxGroup.stories.tsx +1 -1
- package/src/web-components/interaction/form/BdsCombobox.mdx +5 -1
- package/src/web-components/interaction/form/BdsCombobox.stories.tsx +1 -1
- package/src/web-components/interaction/form/BdsFieldGroup.stories.tsx +1 -1
- package/src/web-components/interaction/form/BdsFileInput.mdx +1 -1
- package/src/web-components/interaction/form/BdsFileInput.stories.tsx +1 -1
- package/src/web-components/interaction/form/BdsFormInput.mdx +8 -1
- package/src/web-components/interaction/form/BdsFormInput.stories.tsx +1 -1
- package/src/web-components/interaction/form/BdsNumberInput.mdx +5 -1
- package/src/web-components/interaction/form/BdsNumberInput.stories.tsx +1 -1
- package/src/web-components/interaction/form/BdsRadio.mdx +5 -1
- package/src/web-components/interaction/form/BdsRadio.stories.tsx +1 -1
- package/src/web-components/interaction/form/BdsRadioGroup.mdx +5 -1
- package/src/web-components/interaction/form/BdsRadioGroup.stories.tsx +1 -1
- package/src/web-components/interaction/form/BdsSegmentedControl.mdx +1 -1
- package/src/web-components/interaction/form/BdsSegmentedControl.stories.tsx +1 -1
- package/src/web-components/interaction/form/BdsSelect.mdx +5 -1
- package/src/web-components/interaction/form/BdsSelect.stories.tsx +1 -1
- package/src/web-components/interaction/form/BdsSlider.mdx +5 -1
- package/src/web-components/interaction/form/BdsSlider.stories.tsx +1 -1
- package/src/web-components/interaction/form/BdsSwitch.mdx +5 -1
- package/src/web-components/interaction/form/BdsSwitch.stories.tsx +1 -1
- package/src/web-components/interaction/form/BdsTextarea.mdx +5 -1
- package/src/web-components/interaction/form/BdsTextarea.stories.tsx +1 -1
- package/src/web-components/interaction/form/bds-checkbox-group.spec.ts +32 -3
- package/src/web-components/interaction/form/bds-checkbox-group.ts +33 -17
- package/src/web-components/interaction/form/bds-checkbox.ts +1 -0
- package/src/web-components/interaction/form/bds-combobox.ts +6 -16
- package/src/web-components/interaction/form/bds-form-input.ts +6 -16
- package/src/web-components/interaction/form/bds-number-input.ts +6 -16
- package/src/web-components/interaction/form/bds-radio-group.spec.ts +32 -3
- package/src/web-components/interaction/form/bds-radio-group.ts +26 -14
- package/src/web-components/interaction/form/bds-radio.ts +1 -0
- package/src/web-components/interaction/form/bds-select.ts +6 -16
- package/src/web-components/interaction/form/bds-slider.ts +5 -16
- package/src/web-components/interaction/form/bds-switch.ts +1 -0
- package/src/web-components/interaction/form/bds-textarea.ts +6 -16
- package/src/web-components/interaction/form/field-message.spec.ts +62 -0
- package/src/web-components/interaction/form/field-message.ts +55 -0
- package/src/web-components/layout/BdsGrid.mdx +1 -1
- package/src/web-components/layout/BdsGrid.stories.tsx +1 -1
- package/src/web-components/layout/BdsGridItem.mdx +1 -1
- package/src/web-components/layout/BdsGridItem.stories.tsx +1 -1
- package/src/web-components/ui/BdsAlert.mdx +19 -1
- package/src/web-components/ui/BdsAlert.stories.tsx +29 -3
- package/src/web-components/ui/BdsAvatar.mdx +20 -3
- package/src/web-components/ui/BdsAvatar.stories.tsx +25 -2
- package/src/web-components/ui/BdsBadge.mdx +1 -1
- package/src/web-components/ui/BdsBadge.stories.tsx +1 -1
- package/src/web-components/ui/BdsBreadcrumb.mdx +1 -1
- package/src/web-components/ui/BdsBreadcrumb.stories.tsx +1 -1
- package/src/web-components/ui/BdsButtonContainer.mdx +1 -1
- package/src/web-components/ui/BdsButtonContainer.stories.tsx +1 -1
- package/src/web-components/ui/BdsCalendar.mdx +1 -1
- package/src/web-components/ui/BdsCalendar.stories.tsx +1 -1
- package/src/web-components/ui/BdsCalendarRange.mdx +1 -1
- package/src/web-components/ui/BdsCalendarRange.stories.tsx +1 -1
- package/src/web-components/ui/BdsCard.mdx +1 -1
- package/src/web-components/ui/BdsCard.stories.tsx +1 -1
- package/src/web-components/ui/BdsCarousel.mdx +1 -1
- package/src/web-components/ui/BdsCarousel.stories.tsx +1 -1
- package/src/web-components/ui/BdsDescriptionList.mdx +1 -1
- package/src/web-components/ui/BdsDescriptionList.stories.tsx +1 -1
- package/src/web-components/ui/BdsIconWrapper.mdx +1 -1
- package/src/web-components/ui/BdsIconWrapper.stories.tsx +1 -1
- package/src/web-components/ui/BdsLink.mdx +1 -1
- package/src/web-components/ui/BdsLink.stories.tsx +1 -1
- package/src/web-components/ui/BdsLoading.mdx +1 -1
- package/src/web-components/ui/BdsLoading.stories.tsx +1 -1
- package/src/web-components/ui/BdsNotificationBanner.mdx +10 -1
- package/src/web-components/ui/BdsNotificationBanner.stories.tsx +29 -2
- package/src/web-components/ui/BdsPagination.mdx +1 -1
- package/src/web-components/ui/BdsPagination.stories.tsx +1 -1
- package/src/web-components/ui/BdsProgress.mdx +1 -1
- package/src/web-components/ui/BdsProgress.stories.tsx +1 -1
- package/src/web-components/ui/BdsProgressCircle.mdx +1 -1
- package/src/web-components/ui/BdsProgressCircle.stories.tsx +1 -1
- package/src/web-components/ui/BdsRating.mdx +1 -1
- package/src/web-components/ui/BdsRating.stories.tsx +1 -1
- package/src/web-components/ui/BdsSectionHeader.mdx +18 -6
- package/src/web-components/ui/BdsSectionHeader.stories.tsx +10 -2
- package/src/web-components/ui/BdsSeparator.mdx +2 -1
- package/src/web-components/ui/BdsSeparator.stories.tsx +13 -1
- package/src/web-components/ui/BdsSkeleton.mdx +1 -1
- package/src/web-components/ui/BdsSkeleton.stories.tsx +1 -1
- package/src/web-components/ui/BdsTable.mdx +5 -1
- package/src/web-components/ui/BdsTable.stories.tsx +1 -1
- package/src/web-components/ui/BdsTypography.mdx +1 -1
- package/src/web-components/ui/BdsTypography.stories.tsx +1 -1
- package/src/web-components/ui/bds-alert.spec.ts +27 -0
- package/src/web-components/ui/bds-alert.ts +34 -1
- package/src/web-components/ui/bds-avatar.spec.ts +47 -0
- package/src/web-components/ui/bds-avatar.ts +36 -3
- package/src/web-components/ui/bds-notification-banner.spec.ts +45 -0
- package/src/web-components/ui/bds-notification-banner.ts +53 -1
- package/src/web-components/ui/bds-section-header.spec.ts +36 -3
- package/src/web-components/ui/bds-section-header.ts +32 -10
- package/src/web-components/ui/bds-separator.spec.ts +8 -0
- package/src/web-components/ui/bds-separator.ts +7 -0
- package/src/web-components/ui/bds-table.spec.ts +11 -0
- package/src/web-components/ui/bds-table.ts +5 -5
- package/dist/web-components/chunk-QZAIRJ75.js +0 -111
|
@@ -2,16 +2,19 @@ import * as lit from 'lit';
|
|
|
2
2
|
import { LitElement } from 'lit';
|
|
3
3
|
|
|
4
4
|
type NotificationBannerVariant = 'info' | 'success' | 'warning' | 'error';
|
|
5
|
+
type NotificationBannerAppearance = 'default' | 'gradient';
|
|
5
6
|
/**
|
|
6
7
|
* `<bds-notification-banner>` — framework-agnostic Notification Banner custom element.
|
|
7
8
|
*
|
|
8
9
|
* Attributes:
|
|
9
10
|
* variant — "info" (default) | "success" | "warning" | "error"
|
|
11
|
+
* appearance — "default" | "gradient" (fades the tint to the surface, accent line, shadow)
|
|
10
12
|
* dismissible — boolean; shows a dismiss button when present
|
|
11
13
|
* dismiss-label — aria-label for the dismiss button (default: "Dismiss notification")
|
|
12
14
|
*
|
|
13
15
|
* Slots:
|
|
14
16
|
* (default) — banner body content
|
|
17
|
+
* icon — optional icon displayed before the content
|
|
15
18
|
* action — optional action area (e.g. a button)
|
|
16
19
|
*
|
|
17
20
|
* Events:
|
|
@@ -30,6 +33,10 @@ declare class BdsNotificationBanner extends LitElement {
|
|
|
30
33
|
type: StringConstructor;
|
|
31
34
|
reflect: boolean;
|
|
32
35
|
};
|
|
36
|
+
appearance: {
|
|
37
|
+
type: StringConstructor;
|
|
38
|
+
reflect: boolean;
|
|
39
|
+
};
|
|
33
40
|
dismissible: {
|
|
34
41
|
type: BooleanConstructor;
|
|
35
42
|
reflect: boolean;
|
|
@@ -41,12 +48,18 @@ declare class BdsNotificationBanner extends LitElement {
|
|
|
41
48
|
_actionFilled: {
|
|
42
49
|
state: boolean;
|
|
43
50
|
};
|
|
51
|
+
_iconFilled: {
|
|
52
|
+
state: boolean;
|
|
53
|
+
};
|
|
44
54
|
};
|
|
45
55
|
variant: NotificationBannerVariant;
|
|
56
|
+
appearance: NotificationBannerAppearance;
|
|
46
57
|
dismissible: boolean;
|
|
47
58
|
dismissLabel: string;
|
|
48
59
|
private _actionFilled;
|
|
60
|
+
private _iconFilled;
|
|
49
61
|
constructor();
|
|
62
|
+
private _onIconSlotChange;
|
|
50
63
|
private _onActionSlotChange;
|
|
51
64
|
private get _isUrgent();
|
|
52
65
|
private _handleDismiss;
|
|
@@ -58,4 +71,4 @@ declare global {
|
|
|
58
71
|
}
|
|
59
72
|
}
|
|
60
73
|
|
|
61
|
-
export { BdsNotificationBanner, type NotificationBannerVariant };
|
|
74
|
+
export { BdsNotificationBanner, type NotificationBannerAppearance, type NotificationBannerVariant };
|
|
@@ -13,6 +13,7 @@ import { LitElement } from 'lit';
|
|
|
13
13
|
* subtitle — optional subheading text
|
|
14
14
|
* alignment — "start" (default) | "center" | "end"
|
|
15
15
|
* size — "xs" | "small" | "medium" (default) | "large"
|
|
16
|
+
* appearance — "default" | "gradient" (gradient-filled title)
|
|
16
17
|
* title-as — tag name for the title element (default: "h2")
|
|
17
18
|
*
|
|
18
19
|
* @example
|
|
@@ -38,6 +39,10 @@ declare class BdsSectionHeader extends LitElement {
|
|
|
38
39
|
type: StringConstructor;
|
|
39
40
|
reflect: boolean;
|
|
40
41
|
};
|
|
42
|
+
appearance: {
|
|
43
|
+
type: StringConstructor;
|
|
44
|
+
reflect: boolean;
|
|
45
|
+
};
|
|
41
46
|
titleAs: {
|
|
42
47
|
type: StringConstructor;
|
|
43
48
|
attribute: string;
|
|
@@ -53,6 +58,7 @@ declare class BdsSectionHeader extends LitElement {
|
|
|
53
58
|
subtitle: string;
|
|
54
59
|
alignment: 'start' | 'center' | 'end';
|
|
55
60
|
size: 'xs' | 'small' | 'medium' | 'large';
|
|
61
|
+
appearance: 'default' | 'gradient';
|
|
56
62
|
titleAs: string;
|
|
57
63
|
constructor();
|
|
58
64
|
private get _headingText();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@boostdev/design-system-components",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.16.0",
|
|
4
4
|
"description": "BoostDev React component library: accessible, token-driven components built on @boostdev/design-system-foundation",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"React",
|
|
@@ -171,6 +171,10 @@
|
|
|
171
171
|
"types": "./dist/web-components/interaction/bds-dropdown-menu-item.d.ts",
|
|
172
172
|
"import": "./dist/web-components/interaction/bds-dropdown-menu-item.js"
|
|
173
173
|
},
|
|
174
|
+
"./web-components/interaction/bds-dropdown-menu-group": {
|
|
175
|
+
"types": "./dist/web-components/interaction/bds-dropdown-menu-group.d.ts",
|
|
176
|
+
"import": "./dist/web-components/interaction/bds-dropdown-menu-group.js"
|
|
177
|
+
},
|
|
174
178
|
"./web-components/interaction/bds-popover": {
|
|
175
179
|
"types": "./dist/web-components/interaction/bds-popover.d.ts",
|
|
176
180
|
"import": "./dist/web-components/interaction/bds-popover.js"
|
|
@@ -338,7 +342,7 @@
|
|
|
338
342
|
"changelog:unreleased": "pnpm exec git-cliff --unreleased"
|
|
339
343
|
},
|
|
340
344
|
"devDependencies": {
|
|
341
|
-
"@boostdev/design-system-foundation": "^2.
|
|
345
|
+
"@boostdev/design-system-foundation": "^2.4.0",
|
|
342
346
|
"@boostdev/design-system-react-native": "0.2.0",
|
|
343
347
|
"@modelcontextprotocol/sdk": "^1.27.0",
|
|
344
348
|
"@storybook/addon-docs": "8.6.14",
|
|
@@ -55,6 +55,12 @@ Pass any `ReactNode` to `iconStart` or `iconEnd`. Icons inherit the button's `cu
|
|
|
55
55
|
<Canvas of={Stories.WithIconEnd} />
|
|
56
56
|
<Canvas of={Stories.WithBothIcons} />
|
|
57
57
|
|
|
58
|
+
### Icon offset across sizes
|
|
59
|
+
|
|
60
|
+
The gap between an icon and the button edge (`--button_icon-offset`) is half the size's inline padding by default, so it scales automatically with `size` and with the responsive space tokens at wider viewports.
|
|
61
|
+
|
|
62
|
+
<Canvas of={Stories.IconOffsetMatrix} />
|
|
63
|
+
|
|
58
64
|
### Icon-only (1:1 aspect ratio)
|
|
59
65
|
|
|
60
66
|
Set `isIconOnly` to render a square button with equal `xs` padding on both axes — composable with any `variant`. The icon sits centred; the button's height (from `size`) determines both width and height. Always pair with `aria-label` — there's no visible text for assistive tech to read.
|
|
@@ -143,6 +149,7 @@ Every public token below can be set on the button or any ancestor — the consum
|
|
|
143
149
|
<tr><td>`--button_radius`</td><td>`var(--bds-border_radius--full)`</td><td>Button border radius.</td></tr>
|
|
144
150
|
<tr><td>`--button_height`</td><td>`3em` (medium)</td><td>Button height. Also drives the width when `isIconOnly` is set.</td></tr>
|
|
145
151
|
<tr><td>`--button_font-size`</td><td>`inherit` (medium)</td><td>Button font size.</td></tr>
|
|
152
|
+
<tr><td>`--button_icon-offset`</td><td>Half of the inline padding for the current size</td><td>How far `iconStart`/`iconEnd` pull into the padding (optical correction). Scales with `size` and with the responsive space tokens by default — override to pin a fixed offset instead.</td></tr>
|
|
146
153
|
</tbody>
|
|
147
154
|
</table>
|
|
148
155
|
|
|
@@ -33,7 +33,9 @@
|
|
|
33
33
|
all: unset;
|
|
34
34
|
position: relative;
|
|
35
35
|
font: inherit;
|
|
36
|
-
|
|
36
|
+
--button_padding-inline--size: var(--bds-space_l);
|
|
37
|
+
|
|
38
|
+
padding-inline: var(--button_padding-inline--size);
|
|
37
39
|
display: inline-flex;
|
|
38
40
|
gap: var(--bds-space_xs);
|
|
39
41
|
border-radius: var(--button_radius, var(--bds-border_radius--full));
|
|
@@ -82,20 +84,17 @@
|
|
|
82
84
|
.button.--size_small {
|
|
83
85
|
--button_height: 2.25em;
|
|
84
86
|
--button_font-size: var(--bds-font_size--body--s);
|
|
85
|
-
|
|
86
|
-
padding-inline: var(--bds-space_m);
|
|
87
|
+
--button_padding-inline--size: var(--bds-space_m);
|
|
87
88
|
}
|
|
88
89
|
|
|
89
90
|
.button.--size_medium {
|
|
90
91
|
--button_height: 3em;
|
|
91
|
-
|
|
92
|
-
padding-inline: var(--bds-space_l);
|
|
92
|
+
--button_padding-inline--size: var(--bds-space_l);
|
|
93
93
|
}
|
|
94
94
|
|
|
95
95
|
.button.--size_large {
|
|
96
96
|
--button_font-size: var(--bds-font_size--heading-3);
|
|
97
|
-
|
|
98
|
-
padding-inline: var(--bds-space_xl);
|
|
97
|
+
--button_padding-inline--size: var(--bds-space_xl);
|
|
99
98
|
}
|
|
100
99
|
|
|
101
100
|
.button.--hasPulse {
|
|
@@ -133,17 +132,26 @@
|
|
|
133
132
|
flex-shrink: 0;
|
|
134
133
|
}
|
|
135
134
|
|
|
135
|
+
/* Icon offset — pulls the icon into the padding so the optical gap between
|
|
136
|
+
icon and edge matches the gap between label and edge. Defaults to half
|
|
137
|
+
the size's inline padding (--button_padding-inline--size, set above per
|
|
138
|
+
--size_*), so it scales automatically with size and with the responsive
|
|
139
|
+
space tokens (space_l/space_xl grow at wider viewports). --button_icon-offset
|
|
140
|
+
is the public override; like the identity tokens above it is intentionally
|
|
141
|
+
read only as a var() fallback here, never declared on .button, so an
|
|
142
|
+
ancestor-set value inherits through instead of being shadowed by a
|
|
143
|
+
same-element declaration. */
|
|
136
144
|
.iconStart {
|
|
137
145
|
display: flex;
|
|
138
146
|
align-items: center;
|
|
139
|
-
margin-inline-start: calc(var(--
|
|
147
|
+
margin-inline-start: calc(var(--button_icon-offset, calc(var(--button_padding-inline--size) / 2)) * -1);
|
|
140
148
|
transition: var(--bds-animation_transition);
|
|
141
149
|
}
|
|
142
150
|
|
|
143
151
|
.iconEnd {
|
|
144
152
|
display: flex;
|
|
145
153
|
align-items: center;
|
|
146
|
-
margin-inline-end: calc(var(--
|
|
154
|
+
margin-inline-end: calc(var(--button_icon-offset, calc(var(--button_padding-inline--size) / 2)) * -1);
|
|
147
155
|
transition: var(--bds-animation_transition);
|
|
148
156
|
}
|
|
149
157
|
|
|
@@ -158,3 +158,31 @@ export const AllIconOnly: Story = {
|
|
|
158
158
|
</div>
|
|
159
159
|
),
|
|
160
160
|
};
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Every size × icon position × variant combination in one grid, so the
|
|
164
|
+
* icon-to-edge offset (which now scales with the size's inline padding —
|
|
165
|
+
* see `--button_icon-offset` in the CSS variables docs) can be eyeballed
|
|
166
|
+
* and measured across viewports. Each button's label states its own
|
|
167
|
+
* variant/size/position so a verification script can find the right
|
|
168
|
+
* `.iconStart`/`.iconEnd` span via the button's accessible name and read
|
|
169
|
+
* `getComputedStyle(span).marginInlineStart` / `marginInlineEnd`.
|
|
170
|
+
*/
|
|
171
|
+
export const IconOffsetMatrix: Story = {
|
|
172
|
+
render: () => (
|
|
173
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: '16px' }}>
|
|
174
|
+
{(['small', 'medium', 'large'] as const).map(s => (
|
|
175
|
+
<div key={s} style={{ display: 'flex', gap: '12px', flexWrap: 'wrap', alignItems: 'center' }}>
|
|
176
|
+
{(['default', 'outline'] as const).flatMap(v => [
|
|
177
|
+
<Button key={`${v}-${s}-start`} variant={v} size={s} iconStart={CheckIcon}>
|
|
178
|
+
{v} {s} start
|
|
179
|
+
</Button>,
|
|
180
|
+
<Button key={`${v}-${s}-end`} variant={v} size={s} iconEnd={CheckIcon}>
|
|
181
|
+
{v} {s} end
|
|
182
|
+
</Button>,
|
|
183
|
+
])}
|
|
184
|
+
</div>
|
|
185
|
+
))}
|
|
186
|
+
</div>
|
|
187
|
+
),
|
|
188
|
+
};
|
|
@@ -5,7 +5,7 @@ import * as Stories from './DropdownMenu.stories';
|
|
|
5
5
|
|
|
6
6
|
# DropdownMenu
|
|
7
7
|
|
|
8
|
-
Floating menu with a list of selectable actions, triggered by a button. Supports disabled items and
|
|
8
|
+
Floating menu with a list of selectable actions, triggered by a button. Supports disabled items, separators, destructive items, shortcut hints and labelled groups.
|
|
9
9
|
|
|
10
10
|
## When to use
|
|
11
11
|
- Overflow actions in a toolbar or table row
|
|
@@ -26,6 +26,12 @@ Floating menu with a list of selectable actions, triggered by a button. Supports
|
|
|
26
26
|
### With disabled item
|
|
27
27
|
<Canvas of={Stories.WithDisabledItem} />
|
|
28
28
|
|
|
29
|
+
### With groups
|
|
30
|
+
<Canvas of={Stories.WithGroups} />
|
|
31
|
+
|
|
32
|
+
### With destructive item
|
|
33
|
+
<Canvas of={Stories.WithDestructiveItem} />
|
|
34
|
+
|
|
29
35
|
### Aligned end
|
|
30
36
|
<Canvas of={Stories.AlignedEnd} />
|
|
31
37
|
|
|
@@ -45,14 +51,37 @@ Floating menu with a list of selectable actions, triggered by a button. Supports
|
|
|
45
51
|
<tr><td>`--dropdown_radius`</td><td>`var(--bdc-outline_radius)`</td><td>Menu container corner radius</td></tr>
|
|
46
52
|
<tr><td>`--dropdown_color`</td><td>`var(--bds-color_bg)`</td><td>Menu background colour</td></tr>
|
|
47
53
|
<tr><td>`--dropdown_on-color`</td><td>`var(--bds-color_on-bg)`</td><td>Menu text colour</td></tr>
|
|
48
|
-
<tr><td>`--dropdown_shadow`</td><td>`var(--bds-
|
|
54
|
+
<tr><td>`--dropdown_shadow`</td><td>`var(--bds-shadow_l)`</td><td>Menu box shadow</td></tr>
|
|
49
55
|
<tr><td>`--dropdown_separator-color`</td><td>`var(--bds-color_on-bg--as-surface)`</td><td>Separator line colour — the non-text member of the colour set (≥ 3:1)</td></tr>
|
|
50
|
-
<tr><td>`--dropdown_item-bg--hover`</td><td>`var(--bds-
|
|
51
|
-
<tr><td>`--dropdown_item-color--hover`</td><td>`var(--bds-
|
|
56
|
+
<tr><td>`--dropdown_item-bg--hover`</td><td>`var(--bds-color_primary--subtle)`</td><td>Menu item background on hover and focus</td></tr>
|
|
57
|
+
<tr><td>`--dropdown_item-color--hover`</td><td>`var(--bds-color_on-primary--subtle)`</td><td>Menu item text colour on hover and focus</td></tr>
|
|
58
|
+
<tr><td>`--dropdown_padding`</td><td>`var(--bds-space_xxs)`</td><td>Menu padding on all sides</td></tr>
|
|
59
|
+
<tr><td>`--dropdown_border-color`</td><td>`var(--bds-color_on-bg--as-surface)`</td><td>Menu outline colour</td></tr>
|
|
60
|
+
<tr><td>`--dropdown_item-padding`</td><td>`var(--bds-space_xs) var(--bds-space_s)`</td><td>Item padding</td></tr>
|
|
61
|
+
<tr><td>`--dropdown_item-radius`</td><td>`var(--bds-border_radius--xs)`</td><td>Item corner radius</td></tr>
|
|
62
|
+
<tr><td>`--dropdown_item-font-size`</td><td>`var(--bds-font_size--body)`</td><td>Item font size</td></tr>
|
|
63
|
+
<tr><td>`--dropdown_item-opacity--disabled`</td><td>`0.4`</td><td>Disabled item opacity</td></tr>
|
|
64
|
+
<tr><td>`--dropdown_item-color--destructive`</td><td>`var(--bds-color_error_on-bg)`</td><td>Destructive item text colour</td></tr>
|
|
65
|
+
<tr><td>`--dropdown_item-bg--destructive-hover`</td><td>`var(--bds-color_error--subtle)`</td><td>Destructive item background on hover and focus</td></tr>
|
|
66
|
+
<tr><td>`--dropdown_item-color--destructive-hover`</td><td>`var(--bds-color_on-error--subtle)`</td><td>Destructive item text colour on hover and focus</td></tr>
|
|
67
|
+
<tr><td>`--dropdown_group-label-font-size`</td><td>`var(--bds-font_size--body--s)`</td><td>Group label font size</td></tr>
|
|
68
|
+
<tr><td>`--dropdown_group-label-font-weight`</td><td>`var(--bds-font_weight--bold)`</td><td>Group label font weight</td></tr>
|
|
69
|
+
<tr><td>`--dropdown_group-label-color`</td><td>`var(--bds-color_on-bg--muted)`</td><td>Group label colour</td></tr>
|
|
70
|
+
<tr><td>`--dropdown_group-label-padding`</td><td>`var(--bds-space_xs) var(--bds-space_s) var(--bds-space_xxs)`</td><td>Group label padding</td></tr>
|
|
71
|
+
<tr><td>`--dropdown_shortcut-color`</td><td>`var(--bds-color_on-bg--muted)`</td><td>Shortcut hint colour</td></tr>
|
|
72
|
+
<tr><td>`--dropdown_shortcut-font-size`</td><td>`var(--bds-font_size--body--s)`</td><td>Shortcut hint font size</td></tr>
|
|
52
73
|
</tbody>
|
|
53
74
|
</table>
|
|
54
75
|
|
|
55
76
|
|
|
77
|
+
## Item options
|
|
78
|
+
|
|
79
|
+
| Option | Type | Description |
|
|
80
|
+
|--------|------|-------------|
|
|
81
|
+
| `destructive` | boolean | Renders the item in the error colour |
|
|
82
|
+
| `shortcut` | string | Display-only shortcut hint at the inline end; rendered `aria-hidden`, the consumer wires the actual key |
|
|
83
|
+
| `group` | string | Consecutive items with the same `group` render inside a `role="group"` named by a visible label |
|
|
84
|
+
|
|
56
85
|
## Accessibility
|
|
57
86
|
|
|
58
87
|
- Implements ARIA menu pattern: `role="menu"`, `role="menuitem"`
|
|
@@ -60,3 +89,5 @@ Floating menu with a list of selectable actions, triggered by a button. Supports
|
|
|
60
89
|
- Disabled items have `aria-disabled="true"` and are skipped during keyboard navigation
|
|
61
90
|
- Opening the menu focuses the first enabled item (disabled items are skipped as the initial target)
|
|
62
91
|
- Closing the menu via `Escape` or item activation returns focus to the trigger; closing via `Tab` lets focus move naturally to the next element
|
|
92
|
+
- Grouped items sit inside `role="group"` with `aria-labelledby` pointing at the visible group label; the label is not focusable and arrow keys skip it
|
|
93
|
+
- Shortcut hints are `aria-hidden` so they do not become part of the item name
|
|
@@ -9,15 +9,15 @@
|
|
|
9
9
|
inset-block-start: calc(100% + var(--bds-space_xxs));
|
|
10
10
|
z-index: var(--bds-z-index_dropdown);
|
|
11
11
|
min-inline-size: 10rem;
|
|
12
|
-
padding: var(--bds-space_xxs)
|
|
12
|
+
padding: var(--dropdown_padding, var(--bds-space_xxs));
|
|
13
13
|
border: var(--dropdown_border, none);
|
|
14
|
-
--bdc_color:
|
|
14
|
+
--bdc_color: var(--dropdown_border-color, var(--bds-color_on-bg--as-surface, var(--bds-color_on-bg--border, var(--bds-color_on-bg))));
|
|
15
15
|
--bdc-outline_radius: var(--bds-border_radius--s);
|
|
16
16
|
|
|
17
17
|
border-radius: var(--dropdown_radius, var(--bdc-outline_radius));
|
|
18
18
|
background-color: var(--dropdown_color, var(--bds-color_bg--strong, var(--bds-color_bg)));
|
|
19
19
|
color: var(--dropdown_on-color, var(--bds-color_on-bg));
|
|
20
|
-
box-shadow: inset 0 0 0 var(--bdc-outline_width) var(--bdc_color), var(--dropdown_shadow, var(--bds-
|
|
20
|
+
box-shadow: inset 0 0 0 var(--bdc-outline_width) var(--bdc_color), var(--dropdown_shadow, var(--bds-shadow_l));
|
|
21
21
|
list-style: none;
|
|
22
22
|
margin: 0;
|
|
23
23
|
}
|
|
@@ -29,10 +29,29 @@
|
|
|
29
29
|
.--placement_bottom-start { inset-inline-start: 0; }
|
|
30
30
|
.--placement_bottom-end { inset-inline-end: 0; }
|
|
31
31
|
|
|
32
|
+
.separatorRow {
|
|
33
|
+
padding-block: var(--bds-space_xxs);
|
|
34
|
+
}
|
|
35
|
+
|
|
32
36
|
.separator {
|
|
33
37
|
border: none;
|
|
34
38
|
border-block-start: 1px solid var(--dropdown_separator-color, var(--bds-color_on-bg--as-surface, var(--bds-color_on-bg--border, var(--bds-color_on-bg))));
|
|
35
|
-
margin:
|
|
39
|
+
margin: 0;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.group {
|
|
43
|
+
margin: 0;
|
|
44
|
+
padding: 0;
|
|
45
|
+
list-style: none;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.groupLabel {
|
|
49
|
+
display: block;
|
|
50
|
+
padding: var(--dropdown_group-label-padding, var(--bds-space_xs) var(--bds-space_s) var(--bds-space_xxs));
|
|
51
|
+
font-family: var(--bds-font_family--body);
|
|
52
|
+
font-size: var(--dropdown_group-label-font-size, var(--bds-font_size--body--s));
|
|
53
|
+
font-weight: var(--dropdown_group-label-font-weight, var(--bds-font_weight--bold));
|
|
54
|
+
color: var(--dropdown_group-label-color, var(--bds-color_on-bg--muted, var(--bds-color_on-bg)));
|
|
36
55
|
}
|
|
37
56
|
|
|
38
57
|
.item {
|
|
@@ -41,9 +60,10 @@
|
|
|
41
60
|
align-items: center;
|
|
42
61
|
gap: var(--bds-space_xs);
|
|
43
62
|
inline-size: 100%;
|
|
44
|
-
padding: var(--bds-space_xs) var(--bds-
|
|
63
|
+
padding: var(--dropdown_item-padding, var(--bds-space_xs) var(--bds-space_s));
|
|
64
|
+
border-radius: var(--dropdown_item-radius, var(--bds-border_radius--xs));
|
|
45
65
|
font-family: var(--bds-font_family--body);
|
|
46
|
-
font-size: var(--bds-font_size--body);
|
|
66
|
+
font-size: var(--dropdown_item-font-size, var(--bds-font_size--body));
|
|
47
67
|
color: currentcolor;
|
|
48
68
|
cursor: pointer;
|
|
49
69
|
box-sizing: border-box;
|
|
@@ -51,23 +71,51 @@
|
|
|
51
71
|
}
|
|
52
72
|
|
|
53
73
|
.item:disabled {
|
|
54
|
-
opacity: 0.4;
|
|
74
|
+
opacity: var(--dropdown_item-opacity--disabled, 0.4);
|
|
55
75
|
cursor: not-allowed;
|
|
56
76
|
}
|
|
57
77
|
|
|
58
78
|
.item:focus-visible {
|
|
59
79
|
outline: var(--bds-outline_default);
|
|
60
80
|
outline-offset: calc(var(--bds-outline_offset) * -1);
|
|
61
|
-
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.item:not(:disabled):focus-visible {
|
|
84
|
+
background-color: var(--dropdown_item-bg--hover, var(--bds-color_primary--subtle, var(--bds-color_blue--subtle)));
|
|
85
|
+
color: var(--dropdown_item-color--hover, var(--bds-color_on-primary--subtle, var(--bds-color_on-blue--subtle)));
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.--destructive {
|
|
89
|
+
color: var(--dropdown_item-color--destructive, var(--bds-color_error_on-bg));
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.--destructive:not(:disabled):focus-visible {
|
|
93
|
+
background-color: var(--dropdown_item-bg--destructive-hover, var(--bds-color_error--subtle));
|
|
94
|
+
color: var(--dropdown_item-color--destructive-hover, var(--bds-color_on-error--subtle));
|
|
62
95
|
}
|
|
63
96
|
|
|
64
97
|
@media (hover: hover) and (pointer: fine) {
|
|
65
98
|
.item:not(:disabled):hover {
|
|
66
|
-
background-color: var(--dropdown_item-bg--hover, var(--bds-
|
|
67
|
-
color: var(--dropdown_item-color--hover, var(--bds-
|
|
99
|
+
background-color: var(--dropdown_item-bg--hover, var(--bds-color_primary--subtle, var(--bds-color_blue--subtle)));
|
|
100
|
+
color: var(--dropdown_item-color--hover, var(--bds-color_on-primary--subtle, var(--bds-color_on-blue--subtle)));
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.--destructive:not(:disabled):hover {
|
|
104
|
+
background-color: var(--dropdown_item-bg--destructive-hover, var(--bds-color_error--subtle));
|
|
105
|
+
color: var(--dropdown_item-color--destructive-hover, var(--bds-color_on-error--subtle));
|
|
68
106
|
}
|
|
69
107
|
}
|
|
70
108
|
|
|
109
|
+
.label {
|
|
110
|
+
flex: 1;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.shortcut {
|
|
114
|
+
flex-shrink: 0;
|
|
115
|
+
color: var(--dropdown_shortcut-color, var(--bds-color_on-bg--muted, var(--bds-color_on-bg)));
|
|
116
|
+
font-size: var(--dropdown_shortcut-font-size, var(--bds-font_size--body--s));
|
|
117
|
+
}
|
|
118
|
+
|
|
71
119
|
.icon {
|
|
72
120
|
display: flex;
|
|
73
121
|
align-items: center;
|
|
@@ -1,7 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
import { render, screen, within } from '@testing-library/react';
|
|
2
4
|
import userEvent from '@testing-library/user-event';
|
|
3
5
|
import { DropdownMenu } from './DropdownMenu';
|
|
4
6
|
|
|
7
|
+
const cssSource = readFileSync(
|
|
8
|
+
resolve(process.cwd(), 'src/components/interaction/DropdownMenu/DropdownMenu.module.css'),
|
|
9
|
+
'utf8',
|
|
10
|
+
);
|
|
11
|
+
|
|
5
12
|
const items = [
|
|
6
13
|
{ id: 'edit', label: 'Edit', onClick: vi.fn() },
|
|
7
14
|
{ id: 'duplicate', label: 'Duplicate', onClick: vi.fn() },
|
|
@@ -105,4 +112,110 @@ describe('DropdownMenu', () => {
|
|
|
105
112
|
await user.click(screen.getByRole('button', { name: 'Actions' }));
|
|
106
113
|
expect(screen.getByRole('menuitem', { name: 'Edit' })).toHaveFocus();
|
|
107
114
|
});
|
|
115
|
+
|
|
116
|
+
describe('groups, destructive and shortcut', () => {
|
|
117
|
+
const grouped = [
|
|
118
|
+
{ id: 'edit', label: 'Edit', group: 'Edit' },
|
|
119
|
+
{ id: 'duplicate', label: 'Duplicate', shortcut: '⌘D', group: 'Edit' },
|
|
120
|
+
{ id: 'delete', label: 'Delete', destructive: true, group: 'Danger' },
|
|
121
|
+
];
|
|
122
|
+
|
|
123
|
+
it('renders a labelled group for consecutive items with the same group', async () => {
|
|
124
|
+
const user = userEvent.setup();
|
|
125
|
+
render(<DropdownMenu trigger={<button type="button">Actions</button>} items={grouped} />);
|
|
126
|
+
await user.click(screen.getByRole('button', { name: 'Actions' }));
|
|
127
|
+
const group = screen.getByRole('group', { name: 'Edit' });
|
|
128
|
+
expect(within(group).getAllByRole('menuitem')).toHaveLength(2);
|
|
129
|
+
expect(screen.getByRole('group', { name: 'Danger' })).toBeInTheDocument();
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it('moves focus from the last item of a group to the first of the next', async () => {
|
|
133
|
+
const user = userEvent.setup();
|
|
134
|
+
render(<DropdownMenu trigger={<button type="button">Actions</button>} items={grouped} />);
|
|
135
|
+
await user.click(screen.getByRole('button', { name: 'Actions' }));
|
|
136
|
+
await user.keyboard('{ArrowDown}');
|
|
137
|
+
expect(screen.getByRole('menuitem', { name: 'Duplicate' })).toHaveFocus();
|
|
138
|
+
await user.keyboard('{ArrowDown}');
|
|
139
|
+
expect(screen.getByRole('menuitem', { name: 'Delete' })).toHaveFocus();
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it('does not render a group for items without a group', async () => {
|
|
143
|
+
const user = userEvent.setup();
|
|
144
|
+
render(<DropdownMenu trigger={<button type="button">Actions</button>} items={items} />);
|
|
145
|
+
await user.click(screen.getByRole('button', { name: 'Actions' }));
|
|
146
|
+
expect(screen.queryByRole('group')).not.toBeInTheDocument();
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
it('marks a destructive item with the destructive class', async () => {
|
|
150
|
+
const user = userEvent.setup();
|
|
151
|
+
render(<DropdownMenu trigger={<button type="button">Actions</button>} items={grouped} />);
|
|
152
|
+
await user.click(screen.getByRole('button', { name: 'Actions' }));
|
|
153
|
+
expect(screen.getByRole('menuitem', { name: 'Delete' }).className).toMatch(/destructive/);
|
|
154
|
+
expect(screen.getByRole('menuitem', { name: 'Edit' }).className).not.toMatch(/destructive/);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it('renders the shortcut aria-hidden and keeps it out of the item name', async () => {
|
|
158
|
+
const user = userEvent.setup();
|
|
159
|
+
render(<DropdownMenu trigger={<button type="button">Actions</button>} items={grouped} />);
|
|
160
|
+
await user.click(screen.getByRole('button', { name: 'Actions' }));
|
|
161
|
+
expect(screen.getByText('⌘D')).toHaveAttribute('aria-hidden', 'true');
|
|
162
|
+
expect(screen.getByRole('menuitem', { name: 'Duplicate' })).toBeInTheDocument();
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
it('renders a separator before an item with separator set', async () => {
|
|
166
|
+
const user = userEvent.setup();
|
|
167
|
+
render(
|
|
168
|
+
<DropdownMenu
|
|
169
|
+
trigger={<button type="button">Actions</button>}
|
|
170
|
+
items={[{ id: 'a', label: 'A' }, { id: 'b', label: 'B', separator: true }]}
|
|
171
|
+
/>
|
|
172
|
+
);
|
|
173
|
+
await user.click(screen.getByRole('button', { name: 'Actions' }));
|
|
174
|
+
expect(screen.getByRole('separator')).toBeInTheDocument();
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
it('renders the separator of a group\'s first item outside the group', async () => {
|
|
178
|
+
const user = userEvent.setup();
|
|
179
|
+
render(
|
|
180
|
+
<DropdownMenu
|
|
181
|
+
trigger={<button type="button">Actions</button>}
|
|
182
|
+
items={[
|
|
183
|
+
{ id: 'a', label: 'A', group: 'One' },
|
|
184
|
+
{ id: 'b', label: 'B', group: 'Two', separator: true },
|
|
185
|
+
{ id: 'c', label: 'C', group: 'Two', separator: true },
|
|
186
|
+
]}
|
|
187
|
+
/>
|
|
188
|
+
);
|
|
189
|
+
await user.click(screen.getByRole('button', { name: 'Actions' }));
|
|
190
|
+
const groups = screen.getAllByRole('group');
|
|
191
|
+
const separators = screen.getAllByRole('separator');
|
|
192
|
+
expect(separators).toHaveLength(2);
|
|
193
|
+
expect(groups[1]).not.toContainElement(separators[0]);
|
|
194
|
+
expect(groups[1]).toContainElement(separators[1]);
|
|
195
|
+
});
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
describe('stylesheet hooks', () => {
|
|
199
|
+
it.each([
|
|
200
|
+
'--dropdown_padding',
|
|
201
|
+
'--dropdown_border-color',
|
|
202
|
+
'--dropdown_item-padding',
|
|
203
|
+
'--dropdown_item-radius',
|
|
204
|
+
'--dropdown_item-font-size',
|
|
205
|
+
'--dropdown_item-bg--hover',
|
|
206
|
+
'--dropdown_item-color--hover',
|
|
207
|
+
'--dropdown_item-opacity--disabled',
|
|
208
|
+
'--dropdown_item-color--destructive',
|
|
209
|
+
'--dropdown_item-bg--destructive-hover',
|
|
210
|
+
'--dropdown_item-color--destructive-hover',
|
|
211
|
+
'--dropdown_group-label-font-size',
|
|
212
|
+
'--dropdown_group-label-font-weight',
|
|
213
|
+
'--dropdown_group-label-color',
|
|
214
|
+
'--dropdown_group-label-padding',
|
|
215
|
+
'--dropdown_shortcut-color',
|
|
216
|
+
'--dropdown_shortcut-font-size',
|
|
217
|
+
])('reads %s through var()', hook => {
|
|
218
|
+
expect(cssSource).toContain(`var(${hook},`);
|
|
219
|
+
});
|
|
220
|
+
});
|
|
108
221
|
});
|
|
@@ -66,3 +66,28 @@ export const AlignedEnd: Story = {
|
|
|
66
66
|
/>
|
|
67
67
|
),
|
|
68
68
|
};
|
|
69
|
+
|
|
70
|
+
export const WithGroups: Story = {
|
|
71
|
+
render: () => (
|
|
72
|
+
<DropdownMenu
|
|
73
|
+
trigger={<Button variant="outline">Acties ▾</Button>}
|
|
74
|
+
items={[
|
|
75
|
+
{ id: 'edit', label: 'Bewerken', icon: <span>✎</span>, shortcut: '⌘E', group: 'Bewerken' },
|
|
76
|
+
{ id: 'duplicate', label: 'Dupliceren', shortcut: '⌘D', group: 'Bewerken' },
|
|
77
|
+
{ id: 'delete', label: 'Verwijderen', destructive: true, group: 'Gevaarlijk' },
|
|
78
|
+
]}
|
|
79
|
+
/>
|
|
80
|
+
),
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
export const WithDestructiveItem: Story = {
|
|
84
|
+
render: () => (
|
|
85
|
+
<DropdownMenu
|
|
86
|
+
trigger={<Button variant="outline">Beheer ▾</Button>}
|
|
87
|
+
items={[
|
|
88
|
+
{ id: 'edit', label: 'Bewerken' },
|
|
89
|
+
{ id: 'delete', label: 'Verwijderen', destructive: true, separator: true },
|
|
90
|
+
]}
|
|
91
|
+
/>
|
|
92
|
+
),
|
|
93
|
+
};
|