@boostdev/design-system-components 1.1.2 → 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-O4UFI2RX.js → chunk-3REOIRDW.js} +13 -11
- package/dist/web-components/{chunk-K5CE6HSB.js → chunk-6MH5UWUD.js} +74 -17
- package/dist/web-components/{chunk-VM3YHGQ2.js → chunk-AJSXNDAP.js} +1 -2
- package/dist/web-components/{chunk-LSC4N56Q.js → chunk-BX3IPVOB.js} +1 -2
- package/dist/web-components/{chunk-CJ5ZOO42.js → chunk-DI46Q2EA.js} +50 -1
- package/dist/web-components/{chunk-CAPI25CU.js → chunk-DZRSJGPB.js} +3 -3
- package/dist/web-components/{chunk-VSS5ITNE.js → chunk-EBJM3VD4.js} +1 -3
- package/dist/web-components/{chunk-O7I63SQX.js → chunk-HHHRF2PS.js} +6 -12
- package/dist/web-components/{chunk-OTX4COSV.js → chunk-JUKB3BUP.js} +3 -4
- package/dist/web-components/{chunk-IQGLIQSO.js → chunk-N6IMUOY4.js} +2 -5
- package/dist/web-components/{chunk-QDRH46TF.js → chunk-QLZ2362S.js} +1 -3
- package/dist/web-components/{chunk-IK3PTFZ4.js → chunk-T6AETZRP.js} +1 -3
- package/dist/web-components/{chunk-4BX6AWXX.js → chunk-X3FKVHLK.js} +2 -4
- package/dist/web-components/{chunk-A67LCT7C.js → chunk-XNA6WTXG.js} +3 -4
- package/dist/web-components/{chunk-XIENXR7H.js → chunk-YRXCVKHV.js} +1 -3
- package/dist/web-components/{chunk-6T3RKUKG.js → chunk-ZTC6GRP7.js} +1 -2
- package/dist/web-components/globals.js +1 -1
- package/dist/web-components/index.js +16 -16
- package/dist/web-components/interaction/bds-accordion.js +1 -1
- package/dist/web-components/interaction/bds-button.d.ts +2 -2
- package/dist/web-components/interaction/bds-button.js +1 -1
- package/dist/web-components/interaction/bds-dialog.js +1 -1
- package/dist/web-components/interaction/bds-drawer.js +1 -1
- package/dist/web-components/interaction/form/bds-checkbox.js +1 -1
- package/dist/web-components/interaction/form/bds-combobox.js +1 -1
- package/dist/web-components/interaction/form/bds-number-input.js +1 -1
- package/dist/web-components/interaction/form/bds-radio.js +1 -1
- package/dist/web-components/interaction/form/bds-segmented-control.d.ts +20 -3
- package/dist/web-components/interaction/form/bds-segmented-control.js +1 -1
- package/dist/web-components/interaction/form/bds-select.js +1 -1
- package/dist/web-components/interaction/form/bds-switch.js +1 -1
- package/dist/web-components/interaction/form/bds-textarea.js +1 -1
- package/dist/web-components/ui/bds-alert.js +1 -1
- package/dist/web-components/ui/bds-card.js +1 -1
- package/dist/web-components/ui/bds-notification-banner.js +1 -1
- package/package.json +2 -2
- 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/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.ts +1 -2
- package/src/web-components/interaction/bds-button.ts +15 -13
- package/src/web-components/interaction/bds-dialog.ts +2 -5
- package/src/web-components/interaction/bds-drawer.ts +50 -1
- 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.ts +1 -3
- package/src/web-components/interaction/form/bds-combobox.ts +1 -3
- package/src/web-components/interaction/form/bds-number-input.ts +3 -4
- package/src/web-components/interaction/form/bds-radio.ts +6 -12
- package/src/web-components/interaction/form/bds-segmented-control.ts +91 -20
- package/src/web-components/interaction/form/bds-select.ts +2 -4
- package/src/web-components/interaction/form/bds-switch.ts +3 -4
- package/src/web-components/interaction/form/bds-textarea.ts +1 -3
- 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-card.ts +1 -3
- package/src/web-components/ui/bds-notification-banner.ts +1 -2
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Meta, Canvas, ArgTypes } from '@storybook/blocks';
|
|
2
|
+
import * as Stories from './BdsSkipLink.stories';
|
|
3
|
+
|
|
4
|
+
<Meta of={Stories} />
|
|
5
|
+
|
|
6
|
+
# Skip Link
|
|
7
|
+
|
|
8
|
+
`<bds-skip-link>` renders a visually hidden anchor that becomes visible on focus, allowing keyboard users to skip directly to the main content. This is a critical accessibility component that should be the first focusable element on every page.
|
|
9
|
+
|
|
10
|
+
## Usage
|
|
11
|
+
|
|
12
|
+
```html
|
|
13
|
+
<bds-skip-link href="#main-content">Skip to main content</bds-skip-link>
|
|
14
|
+
<!-- ... navigation ... -->
|
|
15
|
+
<main id="main-content">...</main>
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Attributes
|
|
19
|
+
|
|
20
|
+
| Attribute | Type | Default | Description |
|
|
21
|
+
|-----------|----------|---------|----------------------------------------|
|
|
22
|
+
| `href` | `string` | `""` | Target anchor ID (e.g. `#main-content`) |
|
|
23
|
+
|
|
24
|
+
## Slots
|
|
25
|
+
|
|
26
|
+
| Slot | Description |
|
|
27
|
+
|-----------|--------------------------|
|
|
28
|
+
| (default) | The visible link text |
|
|
29
|
+
|
|
30
|
+
## Notes
|
|
31
|
+
|
|
32
|
+
- The link is visually hidden until it receives keyboard focus (Tab key)
|
|
33
|
+
- Place it as the very first element inside `<body>` before any navigation
|
|
34
|
+
- The `href` must point to an `id` on the main content container
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
3
|
+
import '../index';
|
|
4
|
+
|
|
5
|
+
function BdsSkipLink({ href, children }: { href?: string; children?: React.ReactNode }) {
|
|
6
|
+
return React.createElement('bds-skip-link', { href }, children);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const meta = {
|
|
10
|
+
title: 'Web Components/Interaction/SkipLink',
|
|
11
|
+
component: BdsSkipLink,
|
|
12
|
+
tags: ['!stable', 'experimental'],
|
|
13
|
+
parameters: { layout: 'padded' },
|
|
14
|
+
} satisfies Meta<typeof BdsSkipLink>;
|
|
15
|
+
|
|
16
|
+
export default meta;
|
|
17
|
+
type Story = StoryObj<typeof meta>;
|
|
18
|
+
|
|
19
|
+
export const Default: Story = {
|
|
20
|
+
render: () => (
|
|
21
|
+
<div style={{ position: 'relative', minHeight: '80px', border: '1px dashed #ccc', padding: '8px' }}>
|
|
22
|
+
<p style={{ margin: '0 0 8px', fontSize: '0.75rem', color: '#888' }}>
|
|
23
|
+
Tab into this area to reveal the skip link
|
|
24
|
+
</p>
|
|
25
|
+
<BdsSkipLink href="#main">Skip to main content</BdsSkipLink>
|
|
26
|
+
<p style={{ margin: '8px 0 0', fontSize: '0.875rem' }}>Press Tab to focus the skip link above</p>
|
|
27
|
+
</div>
|
|
28
|
+
),
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const CustomTarget: Story = {
|
|
32
|
+
render: () => (
|
|
33
|
+
<div style={{ position: 'relative', minHeight: '80px' }}>
|
|
34
|
+
<BdsSkipLink href="#main-content">Skip to main content</BdsSkipLink>
|
|
35
|
+
</div>
|
|
36
|
+
),
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export const CustomLabel: Story = {
|
|
40
|
+
render: () => (
|
|
41
|
+
<div style={{ position: 'relative', minHeight: '80px' }}>
|
|
42
|
+
<BdsSkipLink href="#content">Jump to content</BdsSkipLink>
|
|
43
|
+
</div>
|
|
44
|
+
),
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export const AllVariants: Story = {
|
|
48
|
+
render: () => (
|
|
49
|
+
<div style={{ position: 'relative', minHeight: '120px', display: 'flex', flexDirection: 'column', gap: '8px' }}>
|
|
50
|
+
<p style={{ margin: 0, fontSize: '0.75rem', color: '#888' }}>Tab to reveal — visually hidden until focused</p>
|
|
51
|
+
<BdsSkipLink href="#main">Skip to main content</BdsSkipLink>
|
|
52
|
+
<BdsSkipLink href="#nav">Skip to navigation</BdsSkipLink>
|
|
53
|
+
</div>
|
|
54
|
+
),
|
|
55
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { Meta, Canvas, ArgTypes } from '@storybook/blocks';
|
|
2
|
+
import * as Stories from './BdsTabs.stories';
|
|
3
|
+
|
|
4
|
+
<Meta of={Stories} />
|
|
5
|
+
|
|
6
|
+
# Tabs
|
|
7
|
+
|
|
8
|
+
`<bds-tabs>` provides a tabbed interface. Place `<bds-tab>` elements in the `tab` slot and matching `<bds-tab-panel>` elements in the `panel` slot. Tabs and panels are associated by order.
|
|
9
|
+
|
|
10
|
+
## Usage
|
|
11
|
+
|
|
12
|
+
```html
|
|
13
|
+
<bds-tabs>
|
|
14
|
+
<bds-tab slot="tab">Overview</bds-tab>
|
|
15
|
+
<bds-tab slot="tab">Details</bds-tab>
|
|
16
|
+
<bds-tab-panel slot="panel">
|
|
17
|
+
<p>Overview content.</p>
|
|
18
|
+
</bds-tab-panel>
|
|
19
|
+
<bds-tab-panel slot="panel">
|
|
20
|
+
<p>Details content.</p>
|
|
21
|
+
</bds-tab-panel>
|
|
22
|
+
</bds-tabs>
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Attributes — `<bds-tab>`
|
|
26
|
+
|
|
27
|
+
| Attribute | Type | Default | Description |
|
|
28
|
+
|------------|-----------|---------|---------------------------|
|
|
29
|
+
| `disabled` | `boolean` | `false` | Prevents selecting this tab |
|
|
30
|
+
|
|
31
|
+
## Keyboard Navigation
|
|
32
|
+
|
|
33
|
+
| Key | Action |
|
|
34
|
+
|-------------|-------------------------|
|
|
35
|
+
| `ArrowLeft` | Move to previous tab |
|
|
36
|
+
| `ArrowRight`| Move to next tab |
|
|
37
|
+
| `Home` | Move to first tab |
|
|
38
|
+
| `End` | Move to last tab |
|
|
39
|
+
|
|
40
|
+
## Stories
|
|
41
|
+
|
|
42
|
+
<Canvas of={Stories.Default} />
|
|
43
|
+
<Canvas of={Stories.AllVariants} />
|
|
44
|
+
|
|
45
|
+
## Controls
|
|
46
|
+
|
|
47
|
+
<ArgTypes of={Stories} />
|
|
@@ -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
|
+
};
|
|
@@ -28,9 +28,8 @@ export class BdsAccordion extends LitElement {
|
|
|
28
28
|
display: block;
|
|
29
29
|
--bdc_color: var(--bds-color_bg--subtle);
|
|
30
30
|
--bdc-outline_radius: var(--bds-border_radius--s);
|
|
31
|
-
outline: var(--bdc-outline_width) solid var(--bdc_color);
|
|
32
|
-
outline-offset: var(--bdc-outline_offset);
|
|
33
31
|
border-radius: var(--accordion_radius, var(--bdc-outline_radius));
|
|
32
|
+
box-shadow: inset 0 0 0 var(--bdc-outline_width) var(--bdc_color);
|
|
34
33
|
overflow: hidden;
|
|
35
34
|
}
|
|
36
35
|
`;
|
|
@@ -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);
|
|
@@ -37,10 +37,8 @@ export class BdsDialog extends LitElement {
|
|
|
37
37
|
--bdc_color: currentcolor;
|
|
38
38
|
--bdc-outline_radius: var(--bds-border_radius--m);
|
|
39
39
|
|
|
40
|
-
outline: var(--bdc-outline_width) solid var(--bdc_color);
|
|
41
|
-
outline-offset: var(--bdc-outline_offset);
|
|
42
40
|
border-radius: var(--dialog_radius, var(--bdc-outline_radius));
|
|
43
|
-
box-shadow: var(--dialog_shadow, var(--bdc-outline_shadow));
|
|
41
|
+
box-shadow: inset 0 0 0 var(--bdc-outline_width) var(--bdc_color), var(--dialog_shadow, var(--bdc-outline_shadow));
|
|
44
42
|
background-color: var(--dialog_color, var(--bds-color_grey--subtle));
|
|
45
43
|
color: var(--dialog_on-color, var(--bds-color_on-grey--subtle));
|
|
46
44
|
padding: var(--bds-space_l);
|
|
@@ -74,8 +72,7 @@ export class BdsDialog extends LitElement {
|
|
|
74
72
|
border: var(--dialog_close-border, none);
|
|
75
73
|
--bdc_color: currentcolor;
|
|
76
74
|
|
|
77
|
-
|
|
78
|
-
outline-offset: var(--bdc-outline_offset);
|
|
75
|
+
box-shadow: inset 0 0 0 var(--bdc-outline_width) var(--bdc_color);
|
|
79
76
|
cursor: pointer;
|
|
80
77
|
}
|
|
81
78
|
|
|
@@ -47,11 +47,26 @@ export class BdsDrawer extends LitElement {
|
|
|
47
47
|
border: none;
|
|
48
48
|
background: transparent;
|
|
49
49
|
overflow: hidden;
|
|
50
|
+
transition:
|
|
51
|
+
display var(--bds-animation_transition-duration) allow-discrete,
|
|
52
|
+
overlay var(--bds-animation_transition-duration) allow-discrete;
|
|
50
53
|
}
|
|
51
54
|
|
|
52
55
|
.drawer::backdrop {
|
|
53
56
|
background-color: var(--color_backdrop, rgb(0 0 0 / 50%));
|
|
54
57
|
backdrop-filter: blur(3px);
|
|
58
|
+
transition:
|
|
59
|
+
display var(--bds-animation_transition-duration) allow-discrete,
|
|
60
|
+
overlay var(--bds-animation_transition-duration) allow-discrete,
|
|
61
|
+
background-color var(--bds-animation_transition-duration) var(--bds-animation_easing),
|
|
62
|
+
backdrop-filter var(--bds-animation_transition-duration) var(--bds-animation_easing);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
@starting-style {
|
|
66
|
+
.drawer[open]::backdrop {
|
|
67
|
+
background-color: transparent;
|
|
68
|
+
backdrop-filter: blur(0);
|
|
69
|
+
}
|
|
55
70
|
}
|
|
56
71
|
|
|
57
72
|
.panel {
|
|
@@ -65,16 +80,42 @@ export class BdsDrawer extends LitElement {
|
|
|
65
80
|
color: var(--drawer_on-color, var(--bds-color_on-bg));
|
|
66
81
|
box-shadow: var(--bds-shadow_xl);
|
|
67
82
|
overflow: hidden;
|
|
68
|
-
|
|
83
|
+
translate: 100% 0;
|
|
84
|
+
transition: translate var(--bds-animation_transition-duration) var(--bds-animation_easing);
|
|
69
85
|
}
|
|
70
86
|
|
|
71
87
|
:host([side='right']) .panel {
|
|
72
88
|
inset-inline-end: 0;
|
|
89
|
+
translate: 100% 0;
|
|
73
90
|
}
|
|
74
91
|
|
|
75
92
|
:host([side='left']) .panel,
|
|
76
93
|
:host(:not([side])) .panel {
|
|
77
94
|
inset-inline-start: 0;
|
|
95
|
+
translate: -100% 0;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.drawer[open] .panel {
|
|
99
|
+
translate: 0 0;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
:host([side='right']) .drawer[open] .panel,
|
|
103
|
+
:host(:not([side])) .drawer[open] .panel {
|
|
104
|
+
animation: bds-drawer-slide-right var(--bds-animation_transition-duration) var(--bds-animation_easing) both;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
:host([side='left']) .drawer[open] .panel {
|
|
108
|
+
animation: bds-drawer-slide-left var(--bds-animation_transition-duration) var(--bds-animation_easing) both;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
@keyframes bds-drawer-slide-right {
|
|
112
|
+
from { translate: 100% 0; }
|
|
113
|
+
to { translate: 0 0; }
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
@keyframes bds-drawer-slide-left {
|
|
117
|
+
from { translate: -100% 0; }
|
|
118
|
+
to { translate: 0 0; }
|
|
78
119
|
}
|
|
79
120
|
|
|
80
121
|
.header {
|
|
@@ -128,9 +169,17 @@ export class BdsDrawer extends LitElement {
|
|
|
128
169
|
}
|
|
129
170
|
|
|
130
171
|
@media (prefers-reduced-motion: reduce) {
|
|
172
|
+
.drawer,
|
|
173
|
+
.drawer::backdrop,
|
|
131
174
|
.panel {
|
|
132
175
|
transition: none;
|
|
133
176
|
}
|
|
177
|
+
|
|
178
|
+
:host([side='right']) .drawer[open] .panel,
|
|
179
|
+
:host(:not([side])) .drawer[open] .panel,
|
|
180
|
+
:host([side='left']) .drawer[open] .panel {
|
|
181
|
+
animation: none;
|
|
182
|
+
}
|
|
134
183
|
}
|
|
135
184
|
`;
|
|
136
185
|
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Meta, Canvas, ArgTypes } from '@storybook/blocks';
|
|
2
|
+
import * as Stories from './BdsCheckbox.stories';
|
|
3
|
+
|
|
4
|
+
<Meta of={Stories} />
|
|
5
|
+
|
|
6
|
+
# Checkbox
|
|
7
|
+
|
|
8
|
+
`<bds-checkbox>` is a form-associated custom element that participates in HTML forms via the Form-Associated Custom Elements API. Native browser validation (`required`) works without any wrapper.
|
|
9
|
+
|
|
10
|
+
## Usage
|
|
11
|
+
|
|
12
|
+
```html
|
|
13
|
+
<bds-checkbox name="agree" value="yes" required>I agree to the terms</bds-checkbox>
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Attributes
|
|
17
|
+
|
|
18
|
+
| Attribute | Type | Default | Description |
|
|
19
|
+
|------------|-----------|---------|-------------------------------------|
|
|
20
|
+
| `name` | `string` | `""` | Form field name |
|
|
21
|
+
| `value` | `string` | `"on"` | Submitted value when checked |
|
|
22
|
+
| `checked` | `boolean` | `false` | Whether the checkbox is checked |
|
|
23
|
+
| `required` | `boolean` | `false` | Marks the field as required |
|
|
24
|
+
| `disabled` | `boolean` | `false` | Disables interaction |
|
|
25
|
+
|
|
26
|
+
## Slots
|
|
27
|
+
|
|
28
|
+
| Slot | Description |
|
|
29
|
+
|-----------|---------------|
|
|
30
|
+
| (default) | Label text |
|
|
31
|
+
|
|
32
|
+
## Stories
|
|
33
|
+
|
|
34
|
+
<Canvas of={Stories.Default} />
|
|
35
|
+
<Canvas of={Stories.AllVariants} />
|
|
36
|
+
|
|
37
|
+
## Controls
|
|
38
|
+
|
|
39
|
+
<ArgTypes of={Stories} />
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
3
|
+
import '../../index';
|
|
4
|
+
|
|
5
|
+
function BdsCheckbox({
|
|
6
|
+
label = 'Check me',
|
|
7
|
+
checked,
|
|
8
|
+
disabled,
|
|
9
|
+
required,
|
|
10
|
+
}: {
|
|
11
|
+
label?: string;
|
|
12
|
+
checked?: boolean;
|
|
13
|
+
disabled?: boolean;
|
|
14
|
+
required?: boolean;
|
|
15
|
+
}) {
|
|
16
|
+
return React.createElement(
|
|
17
|
+
'bds-checkbox',
|
|
18
|
+
{
|
|
19
|
+
checked: checked || undefined,
|
|
20
|
+
disabled: disabled || undefined,
|
|
21
|
+
required: required || undefined,
|
|
22
|
+
},
|
|
23
|
+
label,
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const meta = {
|
|
28
|
+
title: 'Web Components/Interaction/Form/Checkbox',
|
|
29
|
+
component: BdsCheckbox,
|
|
30
|
+
tags: ['!stable', 'experimental'],
|
|
31
|
+
parameters: { layout: 'padded' },
|
|
32
|
+
argTypes: {
|
|
33
|
+
checked: { control: 'boolean' },
|
|
34
|
+
disabled: { control: 'boolean' },
|
|
35
|
+
required: { control: 'boolean' },
|
|
36
|
+
},
|
|
37
|
+
} satisfies Meta<typeof BdsCheckbox>;
|
|
38
|
+
|
|
39
|
+
export default meta;
|
|
40
|
+
type Story = StoryObj<typeof meta>;
|
|
41
|
+
|
|
42
|
+
export const Default: Story = { args: { label: 'Accept terms and conditions' } };
|
|
43
|
+
export const Checked: Story = { args: { label: 'Already checked', checked: true } };
|
|
44
|
+
export const Disabled: Story = { args: { label: 'Disabled option', disabled: true } };
|
|
45
|
+
export const DisabledChecked: Story = { args: { label: 'Disabled and checked', checked: true, disabled: true } };
|
|
46
|
+
|
|
47
|
+
export const AllVariants: Story = {
|
|
48
|
+
render: () => (
|
|
49
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: '12px' }}>
|
|
50
|
+
{React.createElement('bds-checkbox', null, 'Unchecked')}
|
|
51
|
+
{React.createElement('bds-checkbox', { checked: true }, 'Checked')}
|
|
52
|
+
{React.createElement('bds-checkbox', { disabled: true }, 'Disabled')}
|
|
53
|
+
{React.createElement('bds-checkbox', { checked: true, disabled: true }, 'Disabled checked')}
|
|
54
|
+
{React.createElement('bds-checkbox', { required: true }, 'Required')}
|
|
55
|
+
</div>
|
|
56
|
+
),
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export const Interactive: Story = {
|
|
60
|
+
render: () => {
|
|
61
|
+
const [checked, setChecked] = React.useState(false);
|
|
62
|
+
return (
|
|
63
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
|
|
64
|
+
<p style={{ margin: 0, fontSize: '0.875rem' }}>State: {checked ? 'checked' : 'unchecked'}</p>
|
|
65
|
+
{React.createElement(
|
|
66
|
+
'bds-checkbox',
|
|
67
|
+
{ checked: checked || undefined, onChange: (e: Event) => setChecked((e.target as HTMLInputElement).checked) },
|
|
68
|
+
'Controlled checkbox',
|
|
69
|
+
)}
|
|
70
|
+
</div>
|
|
71
|
+
);
|
|
72
|
+
},
|
|
73
|
+
};
|