@boostdev/design-system-components 1.1.1 → 1.2.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 +13 -10
- package/dist/client.cjs +77 -99
- package/dist/client.css +611 -580
- package/dist/client.d.cts +13 -16
- package/dist/client.d.ts +13 -16
- package/dist/client.js +87 -109
- package/dist/index.cjs +77 -99
- package/dist/index.css +611 -580
- package/dist/index.d.cts +13 -16
- package/dist/index.d.ts +13 -16
- package/dist/index.js +87 -109
- package/dist/native/index.cjs +9 -8
- package/dist/native/index.d.cts +1 -1
- package/dist/native/index.d.ts +1 -1
- package/dist/native/index.js +9 -8
- package/dist/web-components/chunk-2QA62WCQ.js +48 -0
- package/dist/web-components/chunk-3REOIRDW.js +246 -0
- package/dist/web-components/chunk-57TRNCWQ.js +93 -0
- package/dist/web-components/chunk-5IPHEONG.js +139 -0
- package/dist/web-components/chunk-5R6IFELV.js +63 -0
- package/dist/web-components/chunk-5TFWOPLH.js +49 -0
- package/dist/web-components/chunk-6I3CFC26.js +89 -0
- package/dist/web-components/chunk-6MH5UWUD.js +226 -0
- package/dist/web-components/chunk-7FMR53BW.js +127 -0
- package/dist/web-components/chunk-AGKJTMJI.js +56 -0
- package/dist/web-components/chunk-AJSXNDAP.js +151 -0
- package/dist/web-components/chunk-BQLZ7I4G.js +56 -0
- package/dist/web-components/chunk-BX3IPVOB.js +167 -0
- package/dist/web-components/chunk-CR5PGUHV.js +109 -0
- package/dist/web-components/chunk-DI46Q2EA.js +278 -0
- package/dist/web-components/chunk-DZRSJGPB.js +53 -0
- package/dist/web-components/chunk-EBJM3VD4.js +107 -0
- package/dist/web-components/chunk-ECW3HHWA.js +185 -0
- package/dist/web-components/chunk-HGBNDR22.js +98 -0
- package/dist/web-components/chunk-HHHRF2PS.js +118 -0
- package/dist/web-components/chunk-ITHLKR7Q.js +105 -0
- package/dist/web-components/chunk-JUKB3BUP.js +186 -0
- package/dist/web-components/chunk-L3XHOMN6.js +111 -0
- package/dist/{web-components.js → web-components/chunk-LGEZYFUU.js} +62 -844
- package/dist/web-components/chunk-LY62SAVN.js +64 -0
- package/dist/web-components/chunk-N6IMUOY4.js +185 -0
- package/dist/web-components/chunk-OHUTLSIQ.js +69 -0
- package/dist/web-components/chunk-OQTRTMAB.js +27 -0
- package/dist/web-components/chunk-PY62FTRW.js +179 -0
- package/dist/web-components/chunk-Q4T5BJT6.js +94 -0
- package/dist/web-components/chunk-QDST57JC.js +119 -0
- package/dist/web-components/chunk-QLZ2362S.js +279 -0
- package/dist/web-components/chunk-QPOKHLMQ.js +45 -0
- package/dist/web-components/chunk-SOQQ7RVJ.js +88 -0
- package/dist/web-components/chunk-T6AETZRP.js +131 -0
- package/dist/web-components/chunk-UFFCKVZE.js +149 -0
- package/dist/web-components/chunk-VMMVWLXL.js +53 -0
- package/dist/web-components/chunk-X3FKVHLK.js +144 -0
- package/dist/web-components/chunk-XNA6WTXG.js +133 -0
- package/dist/web-components/chunk-Y4MAXTMA.js +80 -0
- package/dist/web-components/chunk-YLVTEY23.js +165 -0
- package/dist/web-components/chunk-YRXCVKHV.js +116 -0
- package/dist/web-components/chunk-ZTC6GRP7.js +64 -0
- package/dist/web-components/globals.d.ts +2 -0
- package/dist/web-components/globals.js +1 -0
- package/dist/web-components/index.d.ts +41 -0
- package/dist/web-components/index.js +165 -0
- package/dist/web-components/interaction/bds-accordion-item.d.ts +54 -0
- package/dist/web-components/interaction/bds-accordion-item.js +7 -0
- package/dist/web-components/interaction/bds-accordion.d.ts +50 -0
- package/dist/web-components/interaction/bds-accordion.js +7 -0
- package/dist/web-components/interaction/bds-button.d.ts +100 -0
- package/dist/web-components/interaction/bds-button.js +7 -0
- package/dist/web-components/interaction/bds-collapsible.d.ts +52 -0
- package/dist/web-components/interaction/bds-collapsible.js +7 -0
- package/dist/web-components/interaction/bds-dialog.d.ts +56 -0
- package/dist/web-components/interaction/bds-dialog.js +7 -0
- package/dist/web-components/interaction/bds-drawer.d.ts +64 -0
- package/dist/web-components/interaction/bds-drawer.js +7 -0
- package/dist/web-components/interaction/bds-popover.d.ts +62 -0
- package/dist/web-components/interaction/bds-popover.js +7 -0
- package/dist/web-components/interaction/bds-skip-link.d.ts +36 -0
- package/dist/web-components/interaction/bds-skip-link.js +7 -0
- package/dist/web-components/interaction/bds-tab-panel.d.ts +26 -0
- package/dist/web-components/interaction/bds-tab-panel.js +7 -0
- package/dist/web-components/interaction/bds-tab.d.ts +45 -0
- package/dist/web-components/interaction/bds-tab.js +7 -0
- package/dist/web-components/interaction/bds-tabs.d.ts +46 -0
- package/dist/web-components/interaction/bds-tabs.js +7 -0
- package/dist/web-components/interaction/bds-toast-provider.d.ts +57 -0
- package/dist/web-components/interaction/bds-toast-provider.js +7 -0
- package/dist/web-components/interaction/bds-tooltip.d.ts +50 -0
- package/dist/web-components/interaction/bds-tooltip.js +7 -0
- package/dist/web-components/interaction/form/bds-checkbox.d.ts +70 -0
- package/dist/web-components/interaction/form/bds-checkbox.js +7 -0
- package/dist/web-components/interaction/form/bds-combobox.d.ts +84 -0
- package/dist/web-components/interaction/form/bds-combobox.js +7 -0
- package/dist/web-components/interaction/form/bds-file-input.d.ts +62 -0
- package/dist/web-components/interaction/form/bds-file-input.js +7 -0
- package/dist/web-components/interaction/form/bds-number-input.d.ts +68 -0
- package/dist/web-components/interaction/form/bds-number-input.js +7 -0
- package/dist/web-components/interaction/form/bds-radio.d.ts +68 -0
- package/dist/web-components/interaction/form/bds-radio.js +7 -0
- package/dist/web-components/interaction/form/bds-segmented-control.d.ts +88 -0
- package/dist/web-components/interaction/form/bds-segmented-control.js +7 -0
- package/dist/web-components/interaction/form/bds-select.d.ts +79 -0
- package/dist/web-components/interaction/form/bds-select.js +7 -0
- package/dist/web-components/interaction/form/bds-slider.d.ts +70 -0
- package/dist/web-components/interaction/form/bds-slider.js +7 -0
- package/dist/web-components/interaction/form/bds-switch.d.ts +67 -0
- package/dist/web-components/interaction/form/bds-switch.js +7 -0
- package/dist/web-components/interaction/form/bds-textarea.d.ts +70 -0
- package/dist/web-components/interaction/form/bds-textarea.js +7 -0
- package/dist/web-components/ui/bds-alert.d.ts +66 -0
- package/dist/web-components/ui/bds-alert.js +7 -0
- package/dist/web-components/ui/bds-avatar.d.ts +50 -0
- package/dist/web-components/ui/bds-avatar.js +7 -0
- package/dist/web-components/ui/bds-badge.d.ts +35 -0
- package/dist/web-components/ui/bds-badge.js +7 -0
- package/dist/web-components/ui/bds-breadcrumb.d.ts +35 -0
- package/dist/web-components/ui/bds-breadcrumb.js +7 -0
- package/dist/web-components/ui/bds-card.d.ts +72 -0
- package/dist/web-components/ui/bds-card.js +7 -0
- package/dist/web-components/ui/bds-description-list.d.ts +42 -0
- package/dist/web-components/ui/bds-description-list.js +7 -0
- package/dist/web-components/ui/bds-icon-wrapper.d.ts +39 -0
- package/dist/web-components/ui/bds-icon-wrapper.js +7 -0
- package/dist/web-components/ui/bds-link.d.ts +59 -0
- package/dist/web-components/ui/bds-link.js +7 -0
- package/dist/web-components/ui/bds-loading.d.ts +32 -0
- package/dist/web-components/ui/bds-loading.js +7 -0
- package/dist/web-components/ui/bds-notification-banner.d.ts +61 -0
- package/dist/web-components/ui/bds-notification-banner.js +7 -0
- package/dist/web-components/ui/bds-progress-circle.d.ts +53 -0
- package/dist/web-components/ui/bds-progress-circle.js +7 -0
- package/dist/web-components/ui/bds-progress.d.ts +54 -0
- package/dist/web-components/ui/bds-progress.js +7 -0
- package/dist/web-components/ui/bds-rating.d.ts +36 -0
- package/dist/web-components/ui/bds-rating.js +7 -0
- package/dist/web-components/ui/bds-section-header.d.ts +53 -0
- package/dist/web-components/ui/bds-section-header.js +8 -0
- package/dist/web-components/ui/bds-separator.d.ts +32 -0
- package/dist/web-components/ui/bds-separator.js +7 -0
- package/dist/web-components/ui/bds-skeleton.d.ts +22 -0
- package/dist/web-components/ui/bds-skeleton.js +7 -0
- package/dist/web-components/ui/bds-typography.d.ts +44 -0
- package/dist/web-components/ui/bds-typography.js +8 -0
- package/package.json +170 -5
- package/src/components/interaction/Button/Button.module.css +12 -11
- package/src/components/interaction/Button/Button.native.tsx +10 -9
- package/src/components/interaction/Button/Button.tsx +1 -1
- package/src/components/interaction/Command/Command.module.css +3 -7
- package/src/components/interaction/Dialog/Dialog.module.css +7 -5
- package/src/components/interaction/Drawer/Drawer.module.css +49 -1
- package/src/components/interaction/DropdownMenu/DropdownMenu.module.css +1 -3
- package/src/components/interaction/Popover/Popover.module.css +1 -3
- package/src/components/interaction/form/Checkbox/Checkbox.module.css +1 -3
- package/src/components/interaction/form/Combobox/Combobox.module.css +2 -6
- package/src/components/interaction/form/FormInput/FormInput.module.css +1 -3
- package/src/components/interaction/form/NumberInput/NumberInput.module.css +16 -4
- package/src/components/interaction/form/Radio/Radio.module.css +6 -16
- package/src/components/interaction/form/SegmentedControl/SegmentedControl.mdx +70 -25
- package/src/components/interaction/form/SegmentedControl/SegmentedControl.module.css +55 -33
- package/src/components/interaction/form/SegmentedControl/SegmentedControl.spec.tsx +127 -56
- package/src/components/interaction/form/SegmentedControl/SegmentedControl.stories.tsx +89 -72
- package/src/components/interaction/form/SegmentedControl/SegmentedControl.tsx +40 -62
- package/src/components/interaction/form/SegmentedControl/index.ts +1 -1
- package/src/components/interaction/form/Select/Select.module.css +2 -4
- package/src/components/interaction/form/Switch/Switch.module.css +5 -7
- package/src/components/interaction/form/Switch/Switch.native.spec.tsx +9 -9
- package/src/components/interaction/form/Switch/Switch.native.tsx +2 -2
- package/src/components/interaction/form/Textarea/Textarea.module.css +1 -3
- package/src/components/interaction/form/atoms/InputContainer.stories.tsx +64 -0
- package/src/components/interaction/form/atoms/Label.stories.tsx +33 -0
- package/src/components/interaction/form/atoms/Message.stories.tsx +33 -0
- package/src/components/layout/Card/Card.module.css +1 -3
- package/src/components/ui/Accordion/Accordion.module.css +1 -2
- package/src/components/ui/Alert/Alert.module.css +1 -2
- package/src/components/ui/Calendar/Calendar.module.css +2 -5
- package/src/components/ui/Carousel/Carousel.module.css +1 -3
- package/src/components/ui/NotificationBanner/NotificationBanner.module.css +1 -2
- package/src/components/ui/Pagination/Pagination.module.css +1 -2
- package/src/components/ui/SkipLink/SkipLink.module.css +1 -2
- package/src/components/ui/Table/Table.module.css +1 -2
- package/src/css/bdc.css +16 -11
- package/src/index.ts +1 -1
- package/src/web-components/globals.ts +3 -3
- package/src/web-components/index.ts +47 -0
- package/src/web-components/interaction/BdsAccordion.mdx +51 -0
- package/src/web-components/interaction/BdsAccordion.stories.tsx +85 -0
- package/src/web-components/interaction/BdsCollapsible.mdx +46 -0
- package/src/web-components/interaction/BdsCollapsible.stories.tsx +87 -0
- package/src/web-components/interaction/BdsDialog.mdx +49 -0
- package/src/web-components/interaction/BdsDialog.stories.tsx +75 -0
- package/src/web-components/interaction/BdsDrawer.mdx +50 -0
- package/src/web-components/interaction/BdsDrawer.stories.tsx +66 -0
- package/src/web-components/interaction/BdsSkipLink.mdx +34 -0
- package/src/web-components/interaction/BdsSkipLink.stories.tsx +55 -0
- package/src/web-components/interaction/BdsTabs.mdx +47 -0
- package/src/web-components/interaction/BdsTabs.stories.tsx +80 -0
- package/src/web-components/interaction/BdsTooltip.mdx +38 -0
- package/src/web-components/interaction/BdsTooltip.stories.tsx +68 -0
- package/src/web-components/interaction/bds-accordion-item.spec.ts +75 -0
- package/src/web-components/interaction/bds-accordion-item.ts +181 -0
- package/src/web-components/interaction/bds-accordion.spec.ts +73 -0
- package/src/web-components/interaction/bds-accordion.ts +98 -0
- package/src/web-components/interaction/bds-button.ts +15 -13
- package/src/web-components/interaction/bds-collapsible.spec.ts +56 -0
- package/src/web-components/interaction/bds-collapsible.ts +170 -0
- package/src/web-components/interaction/bds-dialog.spec.ts +119 -0
- package/src/web-components/interaction/bds-dialog.ts +221 -0
- package/src/web-components/interaction/bds-drawer.spec.ts +113 -0
- package/src/web-components/interaction/bds-drawer.ts +315 -0
- package/src/web-components/interaction/bds-skip-link.spec.ts +42 -0
- package/src/web-components/interaction/bds-skip-link.ts +74 -0
- package/src/web-components/interaction/bds-tab-panel.spec.ts +32 -0
- package/src/web-components/interaction/bds-tab-panel.ts +38 -0
- package/src/web-components/interaction/bds-tab.spec.ts +71 -0
- package/src/web-components/interaction/bds-tab.ts +110 -0
- package/src/web-components/interaction/bds-tabs.spec.ts +120 -0
- package/src/web-components/interaction/bds-tabs.ts +152 -0
- package/src/web-components/interaction/bds-tooltip.spec.ts +49 -0
- package/src/web-components/interaction/bds-tooltip.ts +127 -0
- package/src/web-components/interaction/form/BdsCheckbox.mdx +39 -0
- package/src/web-components/interaction/form/BdsCheckbox.stories.tsx +73 -0
- package/src/web-components/interaction/form/BdsCombobox.mdx +52 -0
- package/src/web-components/interaction/form/BdsCombobox.stories.tsx +91 -0
- package/src/web-components/interaction/form/BdsFileInput.mdx +44 -0
- package/src/web-components/interaction/form/BdsFileInput.stories.tsx +84 -0
- package/src/web-components/interaction/form/BdsNumberInput.mdx +41 -0
- package/src/web-components/interaction/form/BdsNumberInput.stories.tsx +90 -0
- package/src/web-components/interaction/form/BdsRadio.mdx +41 -0
- package/src/web-components/interaction/form/BdsRadio.stories.tsx +90 -0
- package/src/web-components/interaction/form/BdsSegmentedControl.mdx +42 -0
- package/src/web-components/interaction/form/BdsSegmentedControl.stories.tsx +92 -0
- package/src/web-components/interaction/form/BdsSelect.mdx +38 -0
- package/src/web-components/interaction/form/BdsSelect.stories.tsx +93 -0
- package/src/web-components/interaction/form/BdsSlider.mdx +49 -0
- package/src/web-components/interaction/form/BdsSlider.stories.tsx +89 -0
- package/src/web-components/interaction/form/BdsSwitch.mdx +39 -0
- package/src/web-components/interaction/form/BdsSwitch.stories.tsx +73 -0
- package/src/web-components/interaction/form/BdsTextarea.mdx +41 -0
- package/src/web-components/interaction/form/BdsTextarea.stories.tsx +79 -0
- package/src/web-components/interaction/form/bds-checkbox.spec.ts +63 -0
- package/src/web-components/interaction/form/bds-checkbox.ts +166 -0
- package/src/web-components/interaction/form/bds-combobox.spec.ts +117 -0
- package/src/web-components/interaction/form/bds-combobox.ts +334 -0
- package/src/web-components/interaction/form/bds-file-input.spec.ts +58 -0
- package/src/web-components/interaction/form/bds-file-input.ts +209 -0
- package/src/web-components/interaction/form/bds-number-input.spec.ts +87 -0
- package/src/web-components/interaction/form/bds-number-input.ts +220 -0
- package/src/web-components/interaction/form/bds-radio.spec.ts +70 -0
- package/src/web-components/interaction/form/bds-radio.ts +151 -0
- package/src/web-components/interaction/form/bds-segmented-control.spec.ts +74 -0
- package/src/web-components/interaction/form/bds-segmented-control.ts +282 -0
- package/src/web-components/interaction/form/bds-select.spec.ts +74 -0
- package/src/web-components/interaction/form/bds-select.ts +188 -0
- package/src/web-components/interaction/form/bds-slider.spec.ts +41 -0
- package/src/web-components/interaction/form/bds-slider.ts +162 -0
- package/src/web-components/interaction/form/bds-switch.spec.ts +62 -0
- package/src/web-components/interaction/form/bds-switch.ts +165 -0
- package/src/web-components/interaction/form/bds-textarea.spec.ts +55 -0
- package/src/web-components/interaction/form/bds-textarea.ts +141 -0
- package/src/web-components/ui/BdsAvatar.mdx +67 -0
- package/src/web-components/ui/BdsAvatar.stories.tsx +62 -0
- package/src/web-components/ui/BdsBreadcrumb.mdx +63 -0
- package/src/web-components/ui/BdsBreadcrumb.stories.tsx +59 -0
- package/src/web-components/ui/BdsCard.mdx +83 -0
- package/src/web-components/ui/BdsCard.stories.tsx +90 -0
- package/src/web-components/ui/BdsDescriptionList.mdx +67 -0
- package/src/web-components/ui/BdsDescriptionList.stories.tsx +79 -0
- package/src/web-components/ui/BdsIconWrapper.mdx +70 -0
- package/src/web-components/ui/BdsIconWrapper.stories.tsx +76 -0
- package/src/web-components/ui/BdsLink.mdx +75 -0
- package/src/web-components/ui/BdsLink.stories.tsx +64 -0
- package/src/web-components/ui/BdsLoading.mdx +62 -0
- package/src/web-components/ui/BdsLoading.stories.tsx +37 -0
- package/src/web-components/ui/BdsNotificationBanner.mdx +90 -0
- package/src/web-components/ui/BdsNotificationBanner.stories.tsx +93 -0
- package/src/web-components/ui/BdsProgress.mdx +63 -0
- package/src/web-components/ui/BdsProgress.stories.tsx +70 -0
- package/src/web-components/ui/BdsProgressCircle.mdx +64 -0
- package/src/web-components/ui/BdsProgressCircle.stories.tsx +69 -0
- package/src/web-components/ui/BdsRating.mdx +61 -0
- package/src/web-components/ui/BdsRating.stories.tsx +39 -0
- package/src/web-components/ui/BdsSectionHeader.mdx +69 -0
- package/src/web-components/ui/BdsSectionHeader.stories.tsx +56 -0
- package/src/web-components/ui/BdsSeparator.mdx +63 -0
- package/src/web-components/ui/BdsSeparator.stories.tsx +47 -0
- package/src/web-components/ui/BdsSkeleton.mdx +67 -0
- package/src/web-components/ui/BdsSkeleton.stories.tsx +50 -0
- package/src/web-components/ui/BdsTypography.mdx +83 -0
- package/src/web-components/ui/BdsTypography.stories.tsx +51 -0
- package/src/web-components/ui/bds-alert.ts +1 -2
- package/src/web-components/ui/bds-avatar.spec.ts +75 -0
- package/src/web-components/ui/bds-avatar.ts +122 -0
- package/src/web-components/ui/bds-breadcrumb.spec.ts +55 -0
- package/src/web-components/ui/bds-breadcrumb.ts +114 -0
- package/src/web-components/ui/bds-card.spec.ts +70 -0
- package/src/web-components/ui/bds-card.ts +154 -0
- package/src/web-components/ui/bds-description-list.spec.ts +36 -0
- package/src/web-components/ui/bds-description-list.ts +79 -0
- package/src/web-components/ui/bds-icon-wrapper.spec.ts +21 -0
- package/src/web-components/ui/bds-icon-wrapper.ts +68 -0
- package/src/web-components/ui/bds-link.spec.ts +72 -0
- package/src/web-components/ui/bds-link.ts +138 -0
- package/src/web-components/ui/bds-loading.spec.ts +38 -0
- package/src/web-components/ui/bds-loading.ts +76 -0
- package/src/web-components/ui/bds-notification-banner.spec.ts +82 -0
- package/src/web-components/ui/bds-notification-banner.ts +184 -0
- package/src/web-components/ui/bds-progress-circle.spec.ts +58 -0
- package/src/web-components/ui/bds-progress-circle.ts +142 -0
- package/src/web-components/ui/bds-progress.spec.ts +66 -0
- package/src/web-components/ui/bds-progress.ts +127 -0
- package/src/web-components/ui/bds-rating.spec.ts +70 -0
- package/src/web-components/ui/bds-rating.ts +80 -0
- package/src/web-components/ui/bds-section-header.spec.ts +57 -0
- package/src/web-components/ui/bds-section-header.ts +96 -0
- package/src/web-components/ui/bds-separator.spec.ts +50 -0
- package/src/web-components/ui/bds-separator.ts +66 -0
- package/src/web-components/ui/bds-skeleton.spec.ts +22 -0
- package/src/web-components/ui/bds-skeleton.ts +55 -0
- package/src/web-components/ui/bds-typography.spec.ts +76 -0
- package/src/web-components/ui/bds-typography.ts +112 -0
- package/dist/web-components.d.ts +0 -304
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
3
|
+
import '../index';
|
|
4
|
+
|
|
5
|
+
function TabsDemo({ withDisabled = false }: { withDisabled?: boolean }) {
|
|
6
|
+
return React.createElement(
|
|
7
|
+
'bds-tabs',
|
|
8
|
+
null,
|
|
9
|
+
React.createElement('bds-tab', { slot: 'tab' }, 'Overview'),
|
|
10
|
+
React.createElement('bds-tab', { slot: 'tab' }, 'Details'),
|
|
11
|
+
withDisabled
|
|
12
|
+
? React.createElement('bds-tab', { slot: 'tab', disabled: true }, 'Disabled')
|
|
13
|
+
: React.createElement('bds-tab', { slot: 'tab' }, 'Settings'),
|
|
14
|
+
React.createElement(
|
|
15
|
+
'bds-tab-panel',
|
|
16
|
+
{ slot: 'panel' },
|
|
17
|
+
React.createElement('p', { style: { margin: 0 } }, 'Overview content — general information about this item.'),
|
|
18
|
+
),
|
|
19
|
+
React.createElement(
|
|
20
|
+
'bds-tab-panel',
|
|
21
|
+
{ slot: 'panel' },
|
|
22
|
+
React.createElement('p', { style: { margin: 0 } }, 'Details content — technical specifications and metadata.'),
|
|
23
|
+
),
|
|
24
|
+
React.createElement(
|
|
25
|
+
'bds-tab-panel',
|
|
26
|
+
{ slot: 'panel' },
|
|
27
|
+
withDisabled
|
|
28
|
+
? React.createElement('p', { style: { margin: 0 } }, 'Disabled tab content.')
|
|
29
|
+
: React.createElement('p', { style: { margin: 0 } }, 'Settings content — configuration options.'),
|
|
30
|
+
),
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Thin wrapper so Storybook controls work
|
|
35
|
+
function BdsTabs({ withDisabled }: { withDisabled?: boolean }) {
|
|
36
|
+
return React.createElement(TabsDemo, { withDisabled });
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const meta = {
|
|
40
|
+
title: 'Web Components/Interaction/Tabs',
|
|
41
|
+
component: BdsTabs,
|
|
42
|
+
tags: ['!stable', 'experimental'],
|
|
43
|
+
parameters: { layout: 'padded' },
|
|
44
|
+
argTypes: {
|
|
45
|
+
withDisabled: { control: 'boolean' },
|
|
46
|
+
},
|
|
47
|
+
} satisfies Meta<typeof BdsTabs>;
|
|
48
|
+
|
|
49
|
+
export default meta;
|
|
50
|
+
type Story = StoryObj<typeof meta>;
|
|
51
|
+
|
|
52
|
+
export const Default: Story = { args: { withDisabled: false } };
|
|
53
|
+
export const WithDisabledTab: Story = { args: { withDisabled: true } };
|
|
54
|
+
|
|
55
|
+
export const AllVariants: Story = {
|
|
56
|
+
render: () => (
|
|
57
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: '32px' }}>
|
|
58
|
+
<div>
|
|
59
|
+
<p style={{ margin: '0 0 8px', fontSize: '0.75rem', color: '#888', fontWeight: 600 }}>Standard tabs</p>
|
|
60
|
+
<TabsDemo />
|
|
61
|
+
</div>
|
|
62
|
+
<div>
|
|
63
|
+
<p style={{ margin: '0 0 8px', fontSize: '0.75rem', color: '#888', fontWeight: 600 }}>With disabled tab</p>
|
|
64
|
+
<TabsDemo withDisabled />
|
|
65
|
+
</div>
|
|
66
|
+
</div>
|
|
67
|
+
),
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export const Interactive: Story = {
|
|
71
|
+
name: 'Interactive (keyboard nav)',
|
|
72
|
+
render: () => (
|
|
73
|
+
<div>
|
|
74
|
+
<p style={{ margin: '0 0 12px', fontSize: '0.875rem', color: '#666' }}>
|
|
75
|
+
Use ArrowLeft / ArrowRight to navigate between tabs. Home / End jump to first / last.
|
|
76
|
+
</p>
|
|
77
|
+
<TabsDemo />
|
|
78
|
+
</div>
|
|
79
|
+
),
|
|
80
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Meta, Canvas, ArgTypes } from '@storybook/blocks';
|
|
2
|
+
import * as Stories from './BdsTooltip.stories';
|
|
3
|
+
|
|
4
|
+
<Meta of={Stories} />
|
|
5
|
+
|
|
6
|
+
# Tooltip
|
|
7
|
+
|
|
8
|
+
`<bds-tooltip>` wraps any trigger element and shows a floating tooltip on hover and focus. The tooltip is dismissed on mouse-out and blur.
|
|
9
|
+
|
|
10
|
+
## Usage
|
|
11
|
+
|
|
12
|
+
```html
|
|
13
|
+
<bds-tooltip content="Save changes" placement="top">
|
|
14
|
+
<button type="button">Save</button>
|
|
15
|
+
</bds-tooltip>
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Attributes
|
|
19
|
+
|
|
20
|
+
| Attribute | Type | Default | Description |
|
|
21
|
+
|-------------|-----------------------------------------|----------|----------------------------------|
|
|
22
|
+
| `content` | `string` | `""` | Tooltip text |
|
|
23
|
+
| `placement` | `"top" \| "bottom" \| "left" \| "right"` | `"top"` | Preferred tooltip placement |
|
|
24
|
+
|
|
25
|
+
## Slots
|
|
26
|
+
|
|
27
|
+
| Slot | Description |
|
|
28
|
+
|-----------|------------------------------------|
|
|
29
|
+
| (default) | The trigger element for the tooltip |
|
|
30
|
+
|
|
31
|
+
## Stories
|
|
32
|
+
|
|
33
|
+
<Canvas of={Stories.Top} />
|
|
34
|
+
<Canvas of={Stories.AllPlacements} />
|
|
35
|
+
|
|
36
|
+
## Controls
|
|
37
|
+
|
|
38
|
+
<ArgTypes of={Stories} />
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
3
|
+
import type { TooltipPlacement } from './bds-tooltip';
|
|
4
|
+
import '../index';
|
|
5
|
+
|
|
6
|
+
function BdsTooltip({
|
|
7
|
+
content,
|
|
8
|
+
placement,
|
|
9
|
+
children,
|
|
10
|
+
}: {
|
|
11
|
+
content?: string;
|
|
12
|
+
placement?: TooltipPlacement;
|
|
13
|
+
children?: React.ReactNode;
|
|
14
|
+
}) {
|
|
15
|
+
return React.createElement(
|
|
16
|
+
'bds-tooltip',
|
|
17
|
+
{ content, placement },
|
|
18
|
+
children ?? React.createElement('button', { type: 'button' }, 'Hover me'),
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const meta = {
|
|
23
|
+
title: 'Web Components/Interaction/Tooltip',
|
|
24
|
+
component: BdsTooltip,
|
|
25
|
+
tags: ['!stable', 'experimental'],
|
|
26
|
+
parameters: { layout: 'centered' },
|
|
27
|
+
argTypes: {
|
|
28
|
+
placement: { control: 'select', options: ['top', 'bottom', 'left', 'right'] },
|
|
29
|
+
},
|
|
30
|
+
} satisfies Meta<typeof BdsTooltip>;
|
|
31
|
+
|
|
32
|
+
export default meta;
|
|
33
|
+
type Story = StoryObj<typeof meta>;
|
|
34
|
+
|
|
35
|
+
export const Top: Story = { args: { content: 'Tooltip on top', placement: 'top' } };
|
|
36
|
+
export const Bottom: Story = { args: { content: 'Tooltip on bottom', placement: 'bottom' } };
|
|
37
|
+
export const Left: Story = { args: { content: 'Tooltip on left', placement: 'left' } };
|
|
38
|
+
export const Right: Story = { args: { content: 'Tooltip on right', placement: 'right' } };
|
|
39
|
+
|
|
40
|
+
export const AllPlacements: Story = {
|
|
41
|
+
render: () => (
|
|
42
|
+
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, auto)', gap: '64px', padding: '48px' }}>
|
|
43
|
+
{(['top', 'bottom', 'left', 'right'] as const).map(p => (
|
|
44
|
+
<div key={p} style={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
|
|
45
|
+
<BdsTooltip content={`Placed ${p}`} placement={p}>
|
|
46
|
+
<button type="button">{p}</button>
|
|
47
|
+
</BdsTooltip>
|
|
48
|
+
</div>
|
|
49
|
+
))}
|
|
50
|
+
</div>
|
|
51
|
+
),
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export const AllVariants: Story = {
|
|
55
|
+
render: () => (
|
|
56
|
+
<div style={{ display: 'flex', gap: '32px', flexWrap: 'wrap', padding: '32px' }}>
|
|
57
|
+
<BdsTooltip content="A helpful tip" placement="top">
|
|
58
|
+
<button type="button">Info button</button>
|
|
59
|
+
</BdsTooltip>
|
|
60
|
+
<BdsTooltip content="Delete this item" placement="bottom">
|
|
61
|
+
<button type="button">Delete</button>
|
|
62
|
+
</BdsTooltip>
|
|
63
|
+
<BdsTooltip content="Opens in new tab" placement="right">
|
|
64
|
+
<button type="button">External link</button>
|
|
65
|
+
</BdsTooltip>
|
|
66
|
+
</div>
|
|
67
|
+
),
|
|
68
|
+
};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { fixture, cleanup } from '../test/helpers';
|
|
2
|
+
import { BdsAccordionItem } from './bds-accordion-item';
|
|
3
|
+
|
|
4
|
+
describe('bds-accordion-item', () => {
|
|
5
|
+
it('is registered as a custom element', () => {
|
|
6
|
+
expect(customElements.get('bds-accordion-item')).toBe(BdsAccordionItem);
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
it('is closed by default', async () => {
|
|
10
|
+
const el = await fixture('<bds-accordion-item><span slot="header">Q</span><p>A</p></bds-accordion-item>') as BdsAccordionItem;
|
|
11
|
+
expect(el.open).toBe(false);
|
|
12
|
+
cleanup(el);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it('renders a trigger button', async () => {
|
|
16
|
+
const el = await fixture('<bds-accordion-item><span slot="header">Q</span><p>A</p></bds-accordion-item>');
|
|
17
|
+
expect(el.shadowRoot!.querySelector('button.trigger')).not.toBeNull();
|
|
18
|
+
cleanup(el);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('trigger has aria-expanded="false" when closed', async () => {
|
|
22
|
+
const el = await fixture('<bds-accordion-item><span slot="header">Q</span><p>A</p></bds-accordion-item>');
|
|
23
|
+
const btn = el.shadowRoot!.querySelector('button')!;
|
|
24
|
+
expect(btn.getAttribute('aria-expanded')).toBe('false');
|
|
25
|
+
cleanup(el);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('trigger has aria-expanded="true" when open', async () => {
|
|
29
|
+
const el = await fixture('<bds-accordion-item open><span slot="header">Q</span><p>A</p></bds-accordion-item>');
|
|
30
|
+
const btn = el.shadowRoot!.querySelector('button')!;
|
|
31
|
+
expect(btn.getAttribute('aria-expanded')).toBe('true');
|
|
32
|
+
cleanup(el);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('panel is hidden when closed', async () => {
|
|
36
|
+
const el = await fixture('<bds-accordion-item><span slot="header">Q</span><p>A</p></bds-accordion-item>');
|
|
37
|
+
const panel = el.shadowRoot!.querySelector('[role="region"]')!;
|
|
38
|
+
expect(panel.hasAttribute('hidden')).toBe(true);
|
|
39
|
+
cleanup(el);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('panel is visible when open', async () => {
|
|
43
|
+
const el = await fixture('<bds-accordion-item open><span slot="header">Q</span><p>A</p></bds-accordion-item>');
|
|
44
|
+
const panel = el.shadowRoot!.querySelector('[role="region"]')!;
|
|
45
|
+
expect(panel.hasAttribute('hidden')).toBe(false);
|
|
46
|
+
cleanup(el);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('fires bds-accordion-item-toggle when trigger is clicked', async () => {
|
|
50
|
+
const el = await fixture('<bds-accordion-item><span slot="header">Q</span><p>A</p></bds-accordion-item>');
|
|
51
|
+
const btn = el.shadowRoot!.querySelector('button')!;
|
|
52
|
+
const handler = vi.fn();
|
|
53
|
+
el.addEventListener('bds-accordion-item-toggle', handler);
|
|
54
|
+
btn.dispatchEvent(new MouseEvent('click', { bubbles: true, composed: true }));
|
|
55
|
+
expect(handler).toHaveBeenCalledOnce();
|
|
56
|
+
cleanup(el);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('does not fire toggle event when disabled', async () => {
|
|
60
|
+
const el = await fixture('<bds-accordion-item disabled><span slot="header">Q</span><p>A</p></bds-accordion-item>');
|
|
61
|
+
const btn = el.shadowRoot!.querySelector('button')!;
|
|
62
|
+
const handler = vi.fn();
|
|
63
|
+
el.addEventListener('bds-accordion-item-toggle', handler);
|
|
64
|
+
btn.dispatchEvent(new MouseEvent('click', { bubbles: true, composed: true }));
|
|
65
|
+
expect(handler).not.toHaveBeenCalled();
|
|
66
|
+
cleanup(el);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('button is disabled when disabled attribute is set', async () => {
|
|
70
|
+
const el = await fixture('<bds-accordion-item disabled><span slot="header">Q</span><p>A</p></bds-accordion-item>');
|
|
71
|
+
const btn = el.shadowRoot!.querySelector('button')!;
|
|
72
|
+
expect(btn.hasAttribute('disabled')).toBe(true);
|
|
73
|
+
cleanup(el);
|
|
74
|
+
});
|
|
75
|
+
});
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { LitElement, css, html } from 'lit';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* `<bds-accordion-item>` — child element of `<bds-accordion>`.
|
|
5
|
+
*
|
|
6
|
+
* Manages a single collapsible panel. The `open` and `disabled` state is
|
|
7
|
+
* controlled by the parent `<bds-accordion>` element.
|
|
8
|
+
*
|
|
9
|
+
* Attributes:
|
|
10
|
+
* open — boolean; whether the panel is expanded
|
|
11
|
+
* disabled — boolean; prevents the user from toggling this item
|
|
12
|
+
*
|
|
13
|
+
* Slots:
|
|
14
|
+
* header — the always-visible trigger label
|
|
15
|
+
* (default) — the content revealed when open
|
|
16
|
+
*
|
|
17
|
+
* Events:
|
|
18
|
+
* bds-accordion-item-toggle — fired (bubbles, composed) when the trigger
|
|
19
|
+
* button is clicked; the parent accordion handles
|
|
20
|
+
* the state change.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* <bds-accordion-item>
|
|
24
|
+
* <span slot="header">Question</span>
|
|
25
|
+
* <p>Answer content</p>
|
|
26
|
+
* </bds-accordion-item>
|
|
27
|
+
*/
|
|
28
|
+
export class BdsAccordionItem extends LitElement {
|
|
29
|
+
static styles = css`
|
|
30
|
+
:host {
|
|
31
|
+
display: block;
|
|
32
|
+
border-block-end: 1px solid var(--bds-color_bg--subtle);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
:host(:last-child) {
|
|
36
|
+
border-block-end: none;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.heading {
|
|
40
|
+
margin: 0;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.trigger {
|
|
44
|
+
all: unset;
|
|
45
|
+
display: flex;
|
|
46
|
+
align-items: center;
|
|
47
|
+
justify-content: space-between;
|
|
48
|
+
inline-size: 100%;
|
|
49
|
+
padding: var(--bds-space_m);
|
|
50
|
+
font-family: var(--bds-font_family--body);
|
|
51
|
+
font-size: var(--bds-font_size--body);
|
|
52
|
+
font-weight: var(--bds-font_weight--semibold);
|
|
53
|
+
color: var(--bds-color_on-bg);
|
|
54
|
+
cursor: pointer;
|
|
55
|
+
transition: var(--bds-animation_transition);
|
|
56
|
+
box-sizing: border-box;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.trigger:disabled {
|
|
60
|
+
opacity: 0.4;
|
|
61
|
+
cursor: not-allowed;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.trigger:focus-visible {
|
|
65
|
+
outline: var(--bds-outline_default);
|
|
66
|
+
outline-offset: calc(var(--bds-outline_offset) * -1);
|
|
67
|
+
border-radius: var(--bds-border_radius--xs);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
@media (hover: hover) and (pointer: fine) {
|
|
71
|
+
.trigger:not(:disabled):hover {
|
|
72
|
+
background-color: var(--bds-color_bg--subtle);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.trigger-label {
|
|
77
|
+
flex: 1;
|
|
78
|
+
text-align: start;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.chevron {
|
|
82
|
+
inline-size: 1.25rem;
|
|
83
|
+
block-size: 1.25rem;
|
|
84
|
+
flex-shrink: 0;
|
|
85
|
+
transition: transform var(--bds-animation_transition-duration) var(--bds-animation_easing);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
:host([open]) .chevron {
|
|
89
|
+
transform: rotate(180deg);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.panel {
|
|
93
|
+
overflow: hidden;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.panel-content {
|
|
97
|
+
padding: 0 var(--bds-space_m) var(--bds-space_m);
|
|
98
|
+
color: var(--bds-color_on-bg);
|
|
99
|
+
font-size: var(--bds-font_size--body);
|
|
100
|
+
line-height: var(--bds-font_line-height--body);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
@media (prefers-reduced-motion: reduce) {
|
|
104
|
+
.chevron {
|
|
105
|
+
transition: none;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
`;
|
|
109
|
+
|
|
110
|
+
static properties = {
|
|
111
|
+
open: { type: Boolean, reflect: true },
|
|
112
|
+
disabled: { type: Boolean, reflect: true },
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
declare open: boolean;
|
|
116
|
+
declare disabled: boolean;
|
|
117
|
+
|
|
118
|
+
// Stable IDs for aria-controls / aria-labelledby
|
|
119
|
+
private readonly _uid = Math.random().toString(36).slice(2, 8);
|
|
120
|
+
|
|
121
|
+
constructor() {
|
|
122
|
+
super();
|
|
123
|
+
this.open = false;
|
|
124
|
+
this.disabled = false;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
private _handleTriggerClick() {
|
|
128
|
+
if (this.disabled) return;
|
|
129
|
+
this.dispatchEvent(
|
|
130
|
+
new CustomEvent('bds-accordion-item-toggle', { bubbles: true, composed: true }),
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
render() {
|
|
135
|
+
const triggerId = `bds-acc-trigger-${this._uid}`;
|
|
136
|
+
const panelId = `bds-acc-panel-${this._uid}`;
|
|
137
|
+
|
|
138
|
+
return html`
|
|
139
|
+
<h3 class="heading">
|
|
140
|
+
<button
|
|
141
|
+
type="button"
|
|
142
|
+
id=${triggerId}
|
|
143
|
+
class="trigger"
|
|
144
|
+
aria-expanded=${this.open}
|
|
145
|
+
aria-controls=${panelId}
|
|
146
|
+
?disabled=${this.disabled}
|
|
147
|
+
@click=${this._handleTriggerClick}
|
|
148
|
+
>
|
|
149
|
+
<span class="trigger-label"><slot name="header"></slot></span>
|
|
150
|
+
<svg
|
|
151
|
+
class="chevron"
|
|
152
|
+
aria-hidden="true"
|
|
153
|
+
viewBox="0 0 24 24"
|
|
154
|
+
fill="none"
|
|
155
|
+
stroke="currentColor"
|
|
156
|
+
stroke-width="2"
|
|
157
|
+
>
|
|
158
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M6 9l6 6 6-6" />
|
|
159
|
+
</svg>
|
|
160
|
+
</button>
|
|
161
|
+
</h3>
|
|
162
|
+
<div
|
|
163
|
+
id=${panelId}
|
|
164
|
+
class="panel"
|
|
165
|
+
role="region"
|
|
166
|
+
aria-labelledby=${triggerId}
|
|
167
|
+
?hidden=${!this.open}
|
|
168
|
+
>
|
|
169
|
+
<div class="panel-content"><slot></slot></div>
|
|
170
|
+
</div>
|
|
171
|
+
`;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
customElements.define('bds-accordion-item', BdsAccordionItem);
|
|
176
|
+
|
|
177
|
+
declare global {
|
|
178
|
+
interface HTMLElementTagNameMap {
|
|
179
|
+
'bds-accordion-item': BdsAccordionItem;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { fixture, cleanup } from '../test/helpers';
|
|
2
|
+
import { BdsAccordion } from './bds-accordion';
|
|
3
|
+
import { BdsAccordionItem } from './bds-accordion-item';
|
|
4
|
+
|
|
5
|
+
const html = `
|
|
6
|
+
<bds-accordion>
|
|
7
|
+
<bds-accordion-item><span slot="header">Q1</span><p>A1</p></bds-accordion-item>
|
|
8
|
+
<bds-accordion-item><span slot="header">Q2</span><p>A2</p></bds-accordion-item>
|
|
9
|
+
<bds-accordion-item><span slot="header">Q3</span><p>A3</p></bds-accordion-item>
|
|
10
|
+
</bds-accordion>
|
|
11
|
+
`;
|
|
12
|
+
|
|
13
|
+
describe('bds-accordion', () => {
|
|
14
|
+
it('is registered as a custom element', () => {
|
|
15
|
+
expect(customElements.get('bds-accordion')).toBe(BdsAccordion);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('all items are closed by default', async () => {
|
|
19
|
+
const el = await fixture(html);
|
|
20
|
+
const items = [...el.querySelectorAll<BdsAccordionItem>('bds-accordion-item')];
|
|
21
|
+
// Reflect: true means open=false removes the attribute; check attribute absence.
|
|
22
|
+
expect(items.every(i => !i.hasAttribute('open'))).toBe(true);
|
|
23
|
+
cleanup(el);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('opens the toggled item when a bds-accordion-item-toggle fires', async () => {
|
|
27
|
+
const el = await fixture(html);
|
|
28
|
+
const items = [...el.querySelectorAll<BdsAccordionItem>('bds-accordion-item')];
|
|
29
|
+
items[0].dispatchEvent(new CustomEvent('bds-accordion-item-toggle', { bubbles: true, composed: true }));
|
|
30
|
+
expect(items[0].open).toBe(true);
|
|
31
|
+
cleanup(el);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('closes other items when a new one is toggled (exclusive by default)', async () => {
|
|
35
|
+
const el = await fixture(html);
|
|
36
|
+
const items = [...el.querySelectorAll<BdsAccordionItem>('bds-accordion-item')];
|
|
37
|
+
// Open first
|
|
38
|
+
items[0].dispatchEvent(new CustomEvent('bds-accordion-item-toggle', { bubbles: true, composed: true }));
|
|
39
|
+
expect(items[0].open).toBe(true);
|
|
40
|
+
// Toggle second
|
|
41
|
+
items[1].dispatchEvent(new CustomEvent('bds-accordion-item-toggle', { bubbles: true, composed: true }));
|
|
42
|
+
expect(items[1].open).toBe(true);
|
|
43
|
+
expect(items[0].open).toBe(false);
|
|
44
|
+
cleanup(el);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('allows multiple open items when allow-multiple is set', async () => {
|
|
48
|
+
const el = await fixture(`
|
|
49
|
+
<bds-accordion allow-multiple>
|
|
50
|
+
<bds-accordion-item><span slot="header">Q1</span><p>A1</p></bds-accordion-item>
|
|
51
|
+
<bds-accordion-item><span slot="header">Q2</span><p>A2</p></bds-accordion-item>
|
|
52
|
+
</bds-accordion>
|
|
53
|
+
`);
|
|
54
|
+
const items = [...el.querySelectorAll<BdsAccordionItem>('bds-accordion-item')];
|
|
55
|
+
items[0].dispatchEvent(new CustomEvent('bds-accordion-item-toggle', { bubbles: true, composed: true }));
|
|
56
|
+
items[1].dispatchEvent(new CustomEvent('bds-accordion-item-toggle', { bubbles: true, composed: true }));
|
|
57
|
+
expect(items[0].open).toBe(true);
|
|
58
|
+
expect(items[1].open).toBe(true);
|
|
59
|
+
cleanup(el);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('closes an already-open item when toggled again', async () => {
|
|
63
|
+
const el = await fixture(html);
|
|
64
|
+
const items = [...el.querySelectorAll<BdsAccordionItem>('bds-accordion-item')];
|
|
65
|
+
// Open first
|
|
66
|
+
items[0].dispatchEvent(new CustomEvent('bds-accordion-item-toggle', { bubbles: true, composed: true }));
|
|
67
|
+
expect(items[0].open).toBe(true);
|
|
68
|
+
// Toggle again to close
|
|
69
|
+
items[0].dispatchEvent(new CustomEvent('bds-accordion-item-toggle', { bubbles: true, composed: true }));
|
|
70
|
+
expect(items[0].open).toBe(false);
|
|
71
|
+
cleanup(el);
|
|
72
|
+
});
|
|
73
|
+
});
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { LitElement, css, html } from 'lit';
|
|
2
|
+
import type { BdsAccordionItem } from './bds-accordion-item';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* `<bds-accordion>` — framework-agnostic Accordion custom element.
|
|
6
|
+
*
|
|
7
|
+
* Contains `<bds-accordion-item>` children. Coordinates open/closed state
|
|
8
|
+
* across items; by default only one item is open at a time.
|
|
9
|
+
*
|
|
10
|
+
* Attributes:
|
|
11
|
+
* allow-multiple — boolean; when set, multiple items can be open simultaneously
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* <bds-accordion>
|
|
15
|
+
* <bds-accordion-item>
|
|
16
|
+
* <span slot="header">Question 1</span>
|
|
17
|
+
* <p>Answer 1</p>
|
|
18
|
+
* </bds-accordion-item>
|
|
19
|
+
* <bds-accordion-item>
|
|
20
|
+
* <span slot="header">Question 2</span>
|
|
21
|
+
* <p>Answer 2</p>
|
|
22
|
+
* </bds-accordion-item>
|
|
23
|
+
* </bds-accordion>
|
|
24
|
+
*/
|
|
25
|
+
export class BdsAccordion extends LitElement {
|
|
26
|
+
static styles = css`
|
|
27
|
+
:host {
|
|
28
|
+
display: block;
|
|
29
|
+
--bdc_color: var(--bds-color_bg--subtle);
|
|
30
|
+
--bdc-outline_radius: var(--bds-border_radius--s);
|
|
31
|
+
border-radius: var(--accordion_radius, var(--bdc-outline_radius));
|
|
32
|
+
box-shadow: inset 0 0 0 var(--bdc-outline_width) var(--bdc_color);
|
|
33
|
+
overflow: hidden;
|
|
34
|
+
}
|
|
35
|
+
`;
|
|
36
|
+
|
|
37
|
+
static properties = {
|
|
38
|
+
allowMultiple: { type: Boolean, attribute: 'allow-multiple', reflect: true },
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
declare allowMultiple: boolean;
|
|
42
|
+
|
|
43
|
+
private _mo: MutationObserver | null = null;
|
|
44
|
+
|
|
45
|
+
constructor() {
|
|
46
|
+
super();
|
|
47
|
+
this.allowMultiple = false;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
connectedCallback() {
|
|
51
|
+
super.connectedCallback();
|
|
52
|
+
this.addEventListener('bds-accordion-item-toggle', this._handleItemToggle);
|
|
53
|
+
this._mo = new MutationObserver(() => this._discoverItems());
|
|
54
|
+
this._mo.observe(this, { childList: true, subtree: false });
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
disconnectedCallback() {
|
|
58
|
+
super.disconnectedCallback();
|
|
59
|
+
this.removeEventListener('bds-accordion-item-toggle', this._handleItemToggle);
|
|
60
|
+
this._mo?.disconnect();
|
|
61
|
+
this._mo = null;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
private get _items(): BdsAccordionItem[] {
|
|
65
|
+
return [...this.querySelectorAll<BdsAccordionItem>('bds-accordion-item')];
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
private _discoverItems() {
|
|
69
|
+
// No-op: items are queried on demand via _items getter.
|
|
70
|
+
// The MutationObserver ensures we react to added/removed items.
|
|
71
|
+
this.requestUpdate();
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
private _handleItemToggle = (e: Event) => {
|
|
75
|
+
const toggled = e.target as BdsAccordionItem;
|
|
76
|
+
const items = this._items;
|
|
77
|
+
const wasOpen = toggled.open;
|
|
78
|
+
|
|
79
|
+
if (!this.allowMultiple) {
|
|
80
|
+
// Close all others
|
|
81
|
+
items.forEach(item => { item.open = false; });
|
|
82
|
+
}
|
|
83
|
+
// Toggle the clicked item
|
|
84
|
+
toggled.open = !wasOpen;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
render() {
|
|
88
|
+
return html`<slot></slot>`;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
customElements.define('bds-accordion', BdsAccordion);
|
|
93
|
+
|
|
94
|
+
declare global {
|
|
95
|
+
interface HTMLElementTagNameMap {
|
|
96
|
+
'bds-accordion': BdsAccordion;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { LitElement, css, html, nothing } from 'lit';
|
|
2
2
|
|
|
3
|
-
export type ButtonVariant = 'default' | 'ghost';
|
|
3
|
+
export type ButtonVariant = 'default' | 'outline' | 'ghost'; // 'ghost' is deprecated, use 'outline'
|
|
4
4
|
export type ButtonSize = 'small' | 'medium' | 'large';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* `<bds-button>` — framework-agnostic Button custom element.
|
|
8
8
|
*
|
|
9
9
|
* Attributes:
|
|
10
|
-
* variant — "default" (filled, default) | "
|
|
10
|
+
* variant — "default" (filled, default) | "outline" (transparent + outlined) | "ghost" (deprecated alias for "outline")
|
|
11
11
|
* size — "small" | "medium" (default) | "large"
|
|
12
12
|
* disabled — boolean
|
|
13
13
|
* href — renders an <a> tag instead of <button>
|
|
@@ -38,9 +38,9 @@ export class BdsButton extends LitElement {
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
@keyframes pulse {
|
|
41
|
-
0% { transform: scale(1); box-shadow: 0 0 0 0 rgb(from var(--button_pulse-color, var(--button_color, var(--bds-
|
|
42
|
-
70% { transform: scale(1.01); box-shadow: 0 0 0 var(--bds-space_m) rgb(from var(--button_pulse-color, var(--button_color, var(--bds-
|
|
43
|
-
100% { transform: scale(1); box-shadow: 0 0 0 0 rgb(from var(--button_pulse-color, var(--button_color, var(--bds-
|
|
41
|
+
0% { transform: scale(1); box-shadow: 0 0 0 0 rgb(from var(--button_pulse-color, var(--button_color, var(--bds-color_interactive))) r g b / 50%); }
|
|
42
|
+
70% { transform: scale(1.01); box-shadow: 0 0 0 var(--bds-space_m) rgb(from var(--button_pulse-color, var(--button_color, var(--bds-color_interactive))) r g b / 0%); }
|
|
43
|
+
100% { transform: scale(1); box-shadow: 0 0 0 0 rgb(from var(--button_pulse-color, var(--button_color, var(--bds-color_interactive))) r g b / 0%); }
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
:host {
|
|
@@ -64,16 +64,16 @@ export class BdsButton extends LitElement {
|
|
|
64
64
|
white-space: nowrap;
|
|
65
65
|
line-height: 1;
|
|
66
66
|
|
|
67
|
-
--button_color:
|
|
68
|
-
--button_on-color:
|
|
67
|
+
--button_color: var(--bds-color_interactive);
|
|
68
|
+
--button_on-color: var(--bds-color_on-interactive);
|
|
69
|
+
--button_color--on-bg: var(--bds-color_interactive_on-bg);
|
|
69
70
|
|
|
70
71
|
background-color: var(--button_bg, var(--button_color));
|
|
71
72
|
color: var(--button_text, var(--button_on-color));
|
|
72
73
|
border: var(--button_border, none);
|
|
73
74
|
--bdc_color: transparent;
|
|
74
75
|
|
|
75
|
-
|
|
76
|
-
outline-offset: var(--bdc-outline_offset);
|
|
76
|
+
box-shadow: inset 0 0 0 var(--bdc-outline_width) var(--bdc_color);
|
|
77
77
|
transition: var(--bds-animation_transition),
|
|
78
78
|
--bdc_color var(--bds-animation_transition-duration) var(--bds-animation_easing);
|
|
79
79
|
}
|
|
@@ -83,10 +83,11 @@ export class BdsButton extends LitElement {
|
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
/* Variants */
|
|
86
|
-
.button.
|
|
86
|
+
.button.outline,
|
|
87
|
+
.button.ghost /* deprecated — use variant="outline" */ {
|
|
87
88
|
--button_bg: transparent;
|
|
88
|
-
--button_text: var(--button_color);
|
|
89
|
-
--bdc_color: var(--button_color);
|
|
89
|
+
--button_text: var(--button_color--on-bg);
|
|
90
|
+
--bdc_color: var(--button_color--on-bg);
|
|
90
91
|
}
|
|
91
92
|
|
|
92
93
|
/* Sizes */
|
|
@@ -155,7 +156,8 @@ export class BdsButton extends LitElement {
|
|
|
155
156
|
--bdc_color: currentcolor;
|
|
156
157
|
}
|
|
157
158
|
|
|
158
|
-
/*
|
|
159
|
+
/* Outline hover */
|
|
160
|
+
.button.outline:hover,
|
|
159
161
|
.button.ghost:hover {
|
|
160
162
|
--button_bg: var(--button_color);
|
|
161
163
|
--button_text: var(--button_on-color);
|