@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
|
@@ -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:
|
|
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', '
|
|
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:
|
|
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` |
|
|
80
|
-
| `--tooltip_text` |
|
|
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',
|
|
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', '
|
|
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
|
)}
|
|
@@ -70,7 +70,9 @@ export class BdsButton extends LitElement {
|
|
|
70
70
|
all: unset;
|
|
71
71
|
position: relative;
|
|
72
72
|
font: inherit;
|
|
73
|
-
|
|
73
|
+
--button_padding-inline--size: var(--bds-space_l);
|
|
74
|
+
|
|
75
|
+
padding-inline: var(--button_padding-inline--size);
|
|
74
76
|
display: inline-flex;
|
|
75
77
|
gap: var(--bds-space_xs);
|
|
76
78
|
border-radius: var(--button_radius, var(--bds-border_radius--full));
|
|
@@ -120,17 +122,17 @@ export class BdsButton extends LitElement {
|
|
|
120
122
|
.button.small {
|
|
121
123
|
--button_height: 2.25em;
|
|
122
124
|
--button_font-size: var(--bds-font_size--body--s);
|
|
123
|
-
|
|
125
|
+
--button_padding-inline--size: var(--bds-space_m);
|
|
124
126
|
}
|
|
125
127
|
|
|
126
128
|
.button.medium {
|
|
127
129
|
--button_height: 3em;
|
|
128
|
-
|
|
130
|
+
--button_padding-inline--size: var(--bds-space_l);
|
|
129
131
|
}
|
|
130
132
|
|
|
131
133
|
.button.large {
|
|
132
134
|
--button_font-size: var(--bds-font_size--heading-3);
|
|
133
|
-
|
|
135
|
+
--button_padding-inline--size: var(--bds-space_xl);
|
|
134
136
|
}
|
|
135
137
|
|
|
136
138
|
/* Pulse */
|
|
@@ -173,15 +175,23 @@ export class BdsButton extends LitElement {
|
|
|
173
175
|
align-items: center;
|
|
174
176
|
}
|
|
175
177
|
|
|
178
|
+
/* Icon offset — pulls the icon into the padding so the optical gap between
|
|
179
|
+
icon and edge matches the gap between label and edge. Defaults to half
|
|
180
|
+
the size's inline padding (--button_padding-inline--size, set above per
|
|
181
|
+
size), so it scales automatically with size and with the responsive
|
|
182
|
+
space tokens. --button_icon-offset is the public override; it is read
|
|
183
|
+
only as a var() fallback here, never declared on .button, so a value
|
|
184
|
+
set on the host or an ancestor inherits through the shadow boundary
|
|
185
|
+
instead of being shadowed by a same-element declaration. */
|
|
176
186
|
.icon-start.has-content {
|
|
177
187
|
display: flex;
|
|
178
|
-
margin-inline-start: calc(var(--
|
|
188
|
+
margin-inline-start: calc(var(--button_icon-offset, calc(var(--button_padding-inline--size) / 2)) * -1);
|
|
179
189
|
transition: var(--bds-animation_transition);
|
|
180
190
|
}
|
|
181
191
|
|
|
182
192
|
.icon-end.has-content {
|
|
183
193
|
display: flex;
|
|
184
|
-
margin-inline-end: calc(var(--
|
|
194
|
+
margin-inline-end: calc(var(--button_icon-offset, calc(var(--button_padding-inline--size) / 2)) * -1);
|
|
185
195
|
transition: var(--bds-animation_transition);
|
|
186
196
|
}
|
|
187
197
|
|
|
@@ -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 (
|
|
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.
|
|
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:
|
|
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-
|
|
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-
|
|
65
|
-
color: var(--dropdown_item-color--hover, var(--bds-
|
|
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:
|
|
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
|
-
.
|
|
74
|
-
|
|
75
|
-
|
|
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
|
-
<
|
|
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
|
}
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { fixture, cleanup } from '../test/helpers';
|
|
2
2
|
import { BdsDropdownMenu } from './bds-dropdown-menu';
|
|
3
3
|
import { BdsDropdownMenuItem } from './bds-dropdown-menu-item';
|
|
4
|
+
import { BdsDropdownMenuGroup } from './bds-dropdown-menu-group';
|
|
5
|
+
import { readFileSync } from 'node:fs';
|
|
6
|
+
import { resolve } from 'node:path';
|
|
7
|
+
|
|
8
|
+
const itemSource = readFileSync(resolve(process.cwd(), 'src/web-components/interaction/bds-dropdown-menu-item.ts'), 'utf8');
|
|
9
|
+
const groupSource = readFileSync(resolve(process.cwd(), 'src/web-components/interaction/bds-dropdown-menu-group.ts'), 'utf8');
|
|
10
|
+
const menuSource = readFileSync(resolve(process.cwd(), 'src/web-components/interaction/bds-dropdown-menu.ts'), 'utf8');
|
|
4
11
|
|
|
5
12
|
describe('bds-dropdown-menu', () => {
|
|
6
13
|
it('is registered as a custom element', () => {
|
|
@@ -163,3 +170,131 @@ describe('bds-dropdown-menu-item', () => {
|
|
|
163
170
|
cleanup(el);
|
|
164
171
|
});
|
|
165
172
|
});
|
|
173
|
+
|
|
174
|
+
describe('bds-dropdown-menu-item colour', () => {
|
|
175
|
+
it('inherits the colour from the menu panel so --dropdown_on-color applies', () => {
|
|
176
|
+
expect(String(BdsDropdownMenuItem.styles)).toMatch(/\.item \{[^}]*color:\s*inherit/);
|
|
177
|
+
expect(String(BdsDropdownMenuItem.styles)).not.toMatch(/\.item \{[^}]*color:\s*var\(--bds-color_on-bg\)/);
|
|
178
|
+
expect(itemSource).toContain(':host([destructive]) .item {');
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
describe('bds-dropdown-menu-item shortcut, icon and destructive', () => {
|
|
183
|
+
it('renders the shortcut aria-hidden and reflects the attribute', async () => {
|
|
184
|
+
const el = await fixture('<bds-dropdown-menu-item value="edit" shortcut="⌘E">Edit</bds-dropdown-menu-item>') as BdsDropdownMenuItem;
|
|
185
|
+
const shortcut = el.shadowRoot!.querySelector('.shortcut')!;
|
|
186
|
+
expect(shortcut.textContent).toBe('⌘E');
|
|
187
|
+
expect(shortcut.getAttribute('aria-hidden')).toBe('true');
|
|
188
|
+
expect(el.getAttribute('shortcut')).toBe('⌘E');
|
|
189
|
+
cleanup(el);
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
it('omits the shortcut element when no shortcut is set', async () => {
|
|
193
|
+
const el = await fixture('<bds-dropdown-menu-item value="edit">Edit</bds-dropdown-menu-item>');
|
|
194
|
+
expect(el.shadowRoot!.querySelector('.shortcut')).toBeNull();
|
|
195
|
+
cleanup(el);
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
it('offers an icon slot before the label, hidden until filled', async () => {
|
|
199
|
+
const el = await fixture('<bds-dropdown-menu-item value="edit">Edit</bds-dropdown-menu-item>') as BdsDropdownMenuItem;
|
|
200
|
+
const icon = el.shadowRoot!.querySelector('.icon')!;
|
|
201
|
+
expect(icon.querySelector('slot[name="icon"]')).toBeTruthy();
|
|
202
|
+
expect(icon.hasAttribute('hidden')).toBe(true);
|
|
203
|
+
expect(icon.compareDocumentPosition(el.shadowRoot!.querySelector('.label')!) & Node.DOCUMENT_POSITION_FOLLOWING).toBeTruthy();
|
|
204
|
+
cleanup(el);
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
it('reflects the destructive attribute', async () => {
|
|
208
|
+
const el = await fixture('<bds-dropdown-menu-item value="delete" destructive>Delete</bds-dropdown-menu-item>') as BdsDropdownMenuItem;
|
|
209
|
+
expect(el.destructive).toBe(true);
|
|
210
|
+
expect(el.hasAttribute('destructive')).toBe(true);
|
|
211
|
+
cleanup(el);
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
it.each([
|
|
215
|
+
'--dropdown_item-padding',
|
|
216
|
+
'--dropdown_item-radius',
|
|
217
|
+
'--dropdown_item-font-size',
|
|
218
|
+
'--dropdown_item-bg--hover',
|
|
219
|
+
'--dropdown_item-color--hover',
|
|
220
|
+
'--dropdown_item-opacity--disabled',
|
|
221
|
+
'--dropdown_item-color--destructive',
|
|
222
|
+
'--dropdown_item-bg--destructive-hover',
|
|
223
|
+
'--dropdown_item-color--destructive-hover',
|
|
224
|
+
'--dropdown_shortcut-color',
|
|
225
|
+
'--dropdown_shortcut-font-size',
|
|
226
|
+
])('reads %s through var() in the item stylesheet', hook => {
|
|
227
|
+
expect(itemSource).toContain(`var(${hook},`);
|
|
228
|
+
});
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
describe('bds-dropdown-menu-group', () => {
|
|
232
|
+
it('is registered as a custom element', () => {
|
|
233
|
+
expect(customElements.get('bds-dropdown-menu-group')).toBe(BdsDropdownMenuGroup);
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
it('renders a role="group" named by its visible label', async () => {
|
|
237
|
+
const el = await fixture('<bds-dropdown-menu-group label="Edit"></bds-dropdown-menu-group>') as BdsDropdownMenuGroup;
|
|
238
|
+
const group = el.shadowRoot!.querySelector('[role="group"]')!;
|
|
239
|
+
const labelId = group.getAttribute('aria-labelledby')!;
|
|
240
|
+
const label = el.shadowRoot!.getElementById(labelId)!;
|
|
241
|
+
expect(label.textContent?.trim()).toBe('Edit');
|
|
242
|
+
cleanup(el);
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
it('renders no label element and no aria-labelledby without a label', async () => {
|
|
246
|
+
const el = await fixture('<bds-dropdown-menu-group></bds-dropdown-menu-group>') as BdsDropdownMenuGroup;
|
|
247
|
+
const group = el.shadowRoot!.querySelector('[role="group"]')!;
|
|
248
|
+
expect(group.hasAttribute('aria-labelledby')).toBe(false);
|
|
249
|
+
expect(el.shadowRoot!.querySelector('.label')).toBeNull();
|
|
250
|
+
cleanup(el);
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
it('updates the label when the attribute changes', async () => {
|
|
254
|
+
const el = await fixture('<bds-dropdown-menu-group label="Edit"></bds-dropdown-menu-group>') as BdsDropdownMenuGroup;
|
|
255
|
+
el.setAttribute('label', 'Danger');
|
|
256
|
+
await el.updateComplete;
|
|
257
|
+
expect(el.shadowRoot!.querySelector('.label')!.textContent?.trim()).toBe('Danger');
|
|
258
|
+
cleanup(el);
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
it.each([
|
|
262
|
+
'--dropdown_group-label-font-size',
|
|
263
|
+
'--dropdown_group-label-font-weight',
|
|
264
|
+
'--dropdown_group-label-color',
|
|
265
|
+
'--dropdown_group-label-padding',
|
|
266
|
+
])('reads %s through var() in the group stylesheet', hook => {
|
|
267
|
+
expect(groupSource).toContain(`var(${hook},`);
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
it('moves focus from the last item of one group to the first of the next', async () => {
|
|
271
|
+
const el = await fixture(`
|
|
272
|
+
<bds-dropdown-menu>
|
|
273
|
+
<button slot="trigger" type="button">Options</button>
|
|
274
|
+
<bds-dropdown-menu-group label="Edit">
|
|
275
|
+
<bds-dropdown-menu-item value="a">A</bds-dropdown-menu-item>
|
|
276
|
+
<bds-dropdown-menu-item value="b">B</bds-dropdown-menu-item>
|
|
277
|
+
</bds-dropdown-menu-group>
|
|
278
|
+
<bds-dropdown-menu-group label="Danger">
|
|
279
|
+
<bds-dropdown-menu-item value="c" destructive>C</bds-dropdown-menu-item>
|
|
280
|
+
</bds-dropdown-menu-group>
|
|
281
|
+
</bds-dropdown-menu>
|
|
282
|
+
`) as BdsDropdownMenu;
|
|
283
|
+
const items = [...el.querySelectorAll('bds-dropdown-menu-item')] as BdsDropdownMenuItem[];
|
|
284
|
+
await Promise.all(items.map(item => item.updateComplete));
|
|
285
|
+
el._open();
|
|
286
|
+
await el.updateComplete;
|
|
287
|
+
const buttons = items.map(item => item.shadowRoot!.querySelector<HTMLButtonElement>('button')!);
|
|
288
|
+
const spy = vi.spyOn(buttons[2], 'focus');
|
|
289
|
+
buttons[1].focus();
|
|
290
|
+
el.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown', bubbles: true }));
|
|
291
|
+
expect(spy).toHaveBeenCalled();
|
|
292
|
+
cleanup(el);
|
|
293
|
+
});
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
describe('bds-dropdown-menu panel hooks', () => {
|
|
297
|
+
it.each(['--dropdown_padding', '--dropdown_border-color'])('reads %s through var()', hook => {
|
|
298
|
+
expect(menuSource).toContain(`var(${hook},`);
|
|
299
|
+
});
|
|
300
|
+
});
|
|
@@ -19,7 +19,8 @@ export type DropdownMenuPlacement = 'bottom-start' | 'bottom-end' | 'top-start'
|
|
|
19
19
|
*
|
|
20
20
|
* Slots:
|
|
21
21
|
* trigger — the activating element (button or similar)
|
|
22
|
-
* (default) — `<bds-dropdown-menu-item>` elements
|
|
22
|
+
* (default) — `<bds-dropdown-menu-item>` elements, optionally wrapped in
|
|
23
|
+
* `<bds-dropdown-menu-group label="...">`
|
|
23
24
|
*
|
|
24
25
|
* Events:
|
|
25
26
|
* bds-open — fired when the menu opens
|
|
@@ -55,15 +56,15 @@ export class BdsDropdownMenu extends LitElement {
|
|
|
55
56
|
inset-inline-start: 0;
|
|
56
57
|
min-inline-size: 10rem;
|
|
57
58
|
border: var(--dropdown_border, none);
|
|
58
|
-
--bdc_color:
|
|
59
|
+
--bdc_color: var(--dropdown_border-color, var(--bds-color_on-bg--as-surface, var(--bds-color_on-bg--border, var(--bds-color_on-bg))));
|
|
59
60
|
--bdc-outline_radius: var(--bds-border_radius--s);
|
|
60
61
|
|
|
61
62
|
border-radius: var(--dropdown_radius, var(--bdc-outline_radius));
|
|
62
63
|
background-color: var(--dropdown_color, var(--bds-color_bg--strong, var(--bds-color_bg)));
|
|
63
64
|
color: var(--dropdown_on-color, var(--bds-color_on-bg));
|
|
64
65
|
box-shadow: inset 0 0 0 var(--bdc-outline_width) var(--bdc_color),
|
|
65
|
-
var(--dropdown_shadow, var(--bds-
|
|
66
|
-
padding: var(--bds-space_xxs);
|
|
66
|
+
var(--dropdown_shadow, var(--bds-shadow_l));
|
|
67
|
+
padding: var(--dropdown_padding, var(--bds-space_xxs));
|
|
67
68
|
z-index: var(--bds-z-index_dropdown);
|
|
68
69
|
display: none;
|
|
69
70
|
flex-direction: column;
|
|
@@ -14,6 +14,22 @@ describe('bds-tab', () => {
|
|
|
14
14
|
cleanup(el);
|
|
15
15
|
});
|
|
16
16
|
|
|
17
|
+
it('copies the slotted label into data-label to reserve the bold width', async () => {
|
|
18
|
+
const el = await fixture('<bds-tab>Overview</bds-tab>') as BdsTab;
|
|
19
|
+
const slot = el.shadowRoot!.querySelector('slot')!;
|
|
20
|
+
slot.dispatchEvent(new Event('slotchange'));
|
|
21
|
+
await el.updateComplete;
|
|
22
|
+
expect(el.shadowRoot!.querySelector('.label')!.getAttribute('data-label')).toBe('Overview');
|
|
23
|
+
cleanup(el);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('styles a hidden ::after at the active weight', () => {
|
|
27
|
+
const css = BdsTab.styles.toString();
|
|
28
|
+
expect(css).toMatch(/\.label::after\s*\{[^}]*content:\s*attr\(data-label\)/);
|
|
29
|
+
expect(css).toMatch(/\.label::after\s*\{[^}]*font-weight:\s*var\(--tab_font-weight,\s*var\(--tab_font-weight--active,\s*var\(--bds-font_weight--bold\)\)\)/);
|
|
30
|
+
expect(css).toMatch(/\.label::after\s*\{[^}]*visibility:\s*hidden/);
|
|
31
|
+
});
|
|
32
|
+
|
|
17
33
|
it('is not selected by default', async () => {
|
|
18
34
|
const el = await fixture('<bds-tab>Label</bds-tab>') as BdsTab;
|
|
19
35
|
expect(el.selected).toBe(false);
|
|
@@ -72,10 +88,10 @@ describe('bds-tab', () => {
|
|
|
72
88
|
it('lets the public --tab_color/--tab_border-color tokens win over selected/hover-state defaults', () => {
|
|
73
89
|
const cssText = BdsTab.styles.cssText;
|
|
74
90
|
expect(cssText).toMatch(
|
|
75
|
-
/\.tab\s*{[^}]*color:\s*var\(--tab_color,\s*var\(--tab_color--state,\s*var\(--bds-color_on-bg\)\)\)/,
|
|
91
|
+
/\.tab\s*{[^}]*color:\s*var\(--tab_color,\s*var\(--tab_color--state,\s*var\(--tab_color--inactive,\s*var\(--bds-color_on-bg--muted,\s*var\(--bds-color_on-bg\)\)\)\)\)/,
|
|
76
92
|
);
|
|
77
93
|
expect(cssText).toMatch(
|
|
78
|
-
/\.tab\s*{[^}]*border-block-end:\s*
|
|
94
|
+
/\.tab\s*{[^}]*border-block-end:\s*var\(--tab_indicator-width,\s*3px\) solid var\(--tab_border-color,\s*var\(--tab_border-color--state,\s*transparent\)\)/,
|
|
79
95
|
);
|
|
80
96
|
});
|
|
81
97
|
|
|
@@ -93,4 +109,20 @@ describe('bds-tab', () => {
|
|
|
93
109
|
/--tab_color--state:\s*var\(--tab_color--hover,/,
|
|
94
110
|
);
|
|
95
111
|
});
|
|
112
|
+
|
|
113
|
+
it('styles the resting tab muted and medium, the selected tab strong and bold, and hover in the full text colour', () => {
|
|
114
|
+
const cssText = BdsTab.styles.cssText;
|
|
115
|
+
expect(cssText).toMatch(
|
|
116
|
+
/\.tab\s*{[^}]*font-weight:\s*var\(--tab_font-weight,\s*var\(--tab_font-weight--state,\s*var\(--tab_font-weight--inactive,\s*var\(--bds-font_weight--medium\)\)\)\)/,
|
|
117
|
+
);
|
|
118
|
+
expect(cssText).toMatch(
|
|
119
|
+
/:host\(\[selected\]\)\s*\.tab\s*{[^}]*--tab_color--state:\s*var\(--tab_color--active,\s*var\(--bds-color_on-bg\)\)/,
|
|
120
|
+
);
|
|
121
|
+
expect(cssText).toMatch(
|
|
122
|
+
/:host\(\[selected\]\)\s*\.tab\s*{[^}]*--tab_font-weight--state:\s*var\(--tab_font-weight--active,\s*var\(--bds-font_weight--bold\)\)/,
|
|
123
|
+
);
|
|
124
|
+
expect(cssText).toMatch(
|
|
125
|
+
/--tab_color--state:\s*var\(--tab_color--hover,\s*var\(--bds-color_on-bg\)\)/,
|
|
126
|
+
);
|
|
127
|
+
});
|
|
96
128
|
});
|