@boostdev/design-system-components 2.15.0 → 2.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +22 -15
- package/dist/client.cjs +271 -205
- package/dist/client.css +813 -650
- 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 +813 -650
- 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-3WAV6MDN.js → chunk-3FSGP35V.js} +1 -0
- package/dist/web-components/{chunk-SYNLFKD3.js → chunk-3LQKFSMR.js} +6 -0
- package/dist/web-components/{chunk-KA3VPKMY.js → chunk-4MB2ICSK.js} +1 -0
- package/dist/web-components/{chunk-6G22I2CK.js → chunk-5ATTKUCP.js} +33 -3
- 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-BPYKZVDK.js → chunk-SJLMW2VR.js} +2 -2
- 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-LDIPCTRN.js → chunk-WWWJCSXN.js} +50 -4
- 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-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 +35 -30
- 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-badge.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-rating.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/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/Rating/Rating.mdx +4 -1
- package/src/components/interaction/Rating/Rating.module.css +9 -0
- package/src/components/interaction/Rating/Rating.spec.tsx +9 -0
- 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 +2 -1
- package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.module.css +8 -1
- package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.spec.tsx +27 -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 +2 -1
- package/src/components/interaction/form/RadioGroup/RadioGroup.module.css +8 -1
- package/src/components/interaction/form/RadioGroup/RadioGroup.spec.tsx +27 -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 +12 -1
- package/src/components/ui/Alert/Alert.module.css +32 -3
- package/src/components/ui/Alert/Alert.spec.tsx +27 -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/Badge/Badge.mdx +1 -1
- package/src/components/ui/Badge/Badge.module.css +2 -2
- package/src/components/ui/Badge/Badge.spec.tsx +8 -0
- package/src/components/ui/Collapsible/Collapsible.module.css +1 -2
- package/src/components/ui/NotificationBanner/NotificationBanner.mdx +27 -1
- package/src/components/ui/NotificationBanner/NotificationBanner.module.css +33 -3
- package/src/components/ui/NotificationBanner/NotificationBanner.spec.tsx +35 -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/test/token-contract.spec.ts +1 -0
- 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 +1 -1
- package/src/web-components/interaction/BdsButton.stories.tsx +1 -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-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 +20 -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 +2 -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 +11 -2
- 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 +5 -2
- 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 +34 -0
- package/src/web-components/ui/bds-alert.ts +36 -3
- 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-badge.spec.ts +6 -0
- package/src/web-components/ui/bds-badge.ts +2 -2
- package/src/web-components/ui/bds-notification-banner.spec.ts +52 -0
- package/src/web-components/ui/bds-notification-banner.ts +55 -3
- package/src/web-components/ui/bds-rating.spec.ts +7 -0
- package/src/web-components/ui/bds-rating.ts +6 -0
- 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
|
@@ -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
|
)}
|
|
@@ -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
|
});
|
|
@@ -38,14 +38,14 @@ export class BdsTab extends LitElement {
|
|
|
38
38
|
padding: var(--bds-space_s) var(--bds-space_m);
|
|
39
39
|
font-family: var(--bds-font_family--body);
|
|
40
40
|
font-size: var(--bds-font_size--body);
|
|
41
|
-
font-weight: var(--bds-font_weight--
|
|
41
|
+
font-weight: var(--tab_font-weight, var(--tab_font-weight--state, var(--tab_font-weight--inactive, var(--bds-font_weight--medium))));
|
|
42
42
|
|
|
43
43
|
/* Layered cascade: public overrides (--tab_color, --tab_border-color) win over
|
|
44
44
|
per-state defaults. Active/hover write to the inner --tab_*--state slot —
|
|
45
45
|
mirrors the React Tabs.module.css pattern so a consumer's --tab_color
|
|
46
46
|
override is never shadowed by the selected/hover rules below. */
|
|
47
|
-
color: var(--tab_color, var(--tab_color--state, var(--bds-color_on-bg)));
|
|
48
|
-
border-block-end:
|
|
47
|
+
color: var(--tab_color, var(--tab_color--state, var(--tab_color--inactive, var(--bds-color_on-bg--muted, var(--bds-color_on-bg)))));
|
|
48
|
+
border-block-end: var(--tab_indicator-width, 3px) solid var(--tab_border-color, var(--tab_border-color--state, transparent));
|
|
49
49
|
margin-block-end: -1px;
|
|
50
50
|
cursor: pointer;
|
|
51
51
|
transition: var(--bds-animation_transition);
|
|
@@ -53,10 +53,27 @@ export class BdsTab extends LitElement {
|
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
:host([selected]) .tab {
|
|
56
|
-
--tab_color--state: var(--tab_color--active, var(--bds-
|
|
56
|
+
--tab_color--state: var(--tab_color--active, var(--bds-color_on-bg));
|
|
57
|
+
--tab_font-weight--state: var(--tab_font-weight--active, var(--bds-font_weight--bold));
|
|
57
58
|
--tab_border-color--state: var(--tab_border-color--active, var(--bds-color_interactive));
|
|
58
59
|
}
|
|
59
60
|
|
|
61
|
+
/* Reserves the width of the bold label so selecting a tab does not shift the row.
|
|
62
|
+
The hidden ::after repeats the label at the active weight in the same grid cell. */
|
|
63
|
+
.label {
|
|
64
|
+
display: inline-grid;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.label::after {
|
|
68
|
+
content: attr(data-label);
|
|
69
|
+
grid-area: 1 / 1;
|
|
70
|
+
font-weight: var(--tab_font-weight, var(--tab_font-weight--active, var(--bds-font_weight--bold)));
|
|
71
|
+
visibility: hidden;
|
|
72
|
+
pointer-events: none;
|
|
73
|
+
block-size: 0;
|
|
74
|
+
overflow: hidden;
|
|
75
|
+
}
|
|
76
|
+
|
|
60
77
|
.tab:disabled {
|
|
61
78
|
opacity: 0.4;
|
|
62
79
|
cursor: not-allowed;
|
|
@@ -70,7 +87,7 @@ export class BdsTab extends LitElement {
|
|
|
70
87
|
|
|
71
88
|
@media (hover: hover) and (pointer: fine) {
|
|
72
89
|
.tab:not(:disabled, [aria-selected='true']):hover {
|
|
73
|
-
--tab_color--state: var(--tab_color--hover, var(--bds-
|
|
90
|
+
--tab_color--state: var(--tab_color--hover, var(--bds-color_on-bg));
|
|
74
91
|
}
|
|
75
92
|
}
|
|
76
93
|
`;
|
|
@@ -78,15 +95,18 @@ export class BdsTab extends LitElement {
|
|
|
78
95
|
static properties = {
|
|
79
96
|
selected: { type: Boolean, reflect: true },
|
|
80
97
|
disabled: { type: Boolean, reflect: true },
|
|
98
|
+
_label: { state: true },
|
|
81
99
|
};
|
|
82
100
|
|
|
83
101
|
declare selected: boolean;
|
|
84
102
|
declare disabled: boolean;
|
|
103
|
+
declare private _label: string;
|
|
85
104
|
|
|
86
105
|
constructor() {
|
|
87
106
|
super();
|
|
88
107
|
this.selected = false;
|
|
89
108
|
this.disabled = false;
|
|
109
|
+
this._label = '';
|
|
90
110
|
}
|
|
91
111
|
|
|
92
112
|
/** Called by `bds-tabs` to focus the inner button for keyboard navigation. */
|
|
@@ -94,6 +114,11 @@ export class BdsTab extends LitElement {
|
|
|
94
114
|
this.shadowRoot?.querySelector<HTMLButtonElement>('button')?.focus();
|
|
95
115
|
}
|
|
96
116
|
|
|
117
|
+
private _handleSlotChange(e: Event) {
|
|
118
|
+
const slot = e.target as HTMLSlotElement;
|
|
119
|
+
this._label = slot.assignedNodes({ flatten: true }).map((n) => n.textContent ?? '').join('').trim();
|
|
120
|
+
}
|
|
121
|
+
|
|
97
122
|
private _handleClick() {
|
|
98
123
|
if (this.disabled) return;
|
|
99
124
|
this.dispatchEvent(new CustomEvent('bds-tab-select', { bubbles: true, composed: true }));
|
|
@@ -110,7 +135,7 @@ export class BdsTab extends LitElement {
|
|
|
110
135
|
?disabled=${this.disabled}
|
|
111
136
|
@click=${this._handleClick}
|
|
112
137
|
>
|
|
113
|
-
<slot></slot>
|
|
138
|
+
<span class="label" data-label=${this._label}><slot @slotchange=${this._handleSlotChange}></slot></span>
|
|
114
139
|
</button>
|
|
115
140
|
`;
|
|
116
141
|
}
|
|
@@ -117,4 +117,20 @@ describe('bds-tooltip', () => {
|
|
|
117
117
|
expect(cssText).toMatch(/z-index:\s*var\(--bds-z-index_popover\);/);
|
|
118
118
|
expect(cssText).not.toContain('200');
|
|
119
119
|
});
|
|
120
|
+
|
|
121
|
+
it('sizes the tooltip to its text up to a max width and lets it wrap', () => {
|
|
122
|
+
const cssText = BdsTooltip.styles.cssText;
|
|
123
|
+
expect(cssText).toMatch(/inline-size:\s*max-content;/);
|
|
124
|
+
expect(cssText).toMatch(/max-inline-size:\s*var\(--tooltip_max-inline-size,\s*20rem\);/);
|
|
125
|
+
expect(cssText).toMatch(/white-space:\s*normal;/);
|
|
126
|
+
expect(cssText).not.toContain('nowrap;\n pointer-events');
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it('exposes the radius, padding, font-size and offset hooks with their defaults', () => {
|
|
130
|
+
const cssText = BdsTooltip.styles.cssText;
|
|
131
|
+
expect(cssText).toContain('var(--tooltip_radius, var(--bds-border_radius--xs))');
|
|
132
|
+
expect(cssText).toContain('var(--tooltip_padding, var(--bds-space_xxs) var(--bds-space_s))');
|
|
133
|
+
expect(cssText).toContain('var(--tooltip_font-size, var(--bds-font_size--body--s))');
|
|
134
|
+
expect(cssText).toContain('var(--tooltip_offset, var(--bds-space_xs))');
|
|
135
|
+
});
|
|
120
136
|
});
|