@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,90 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
3
|
+
import type { CardVariant, CardPadding, CardTextAlign } from './bds-card';
|
|
4
|
+
import '../index';
|
|
5
|
+
|
|
6
|
+
function BdsCard({
|
|
7
|
+
variant,
|
|
8
|
+
padding,
|
|
9
|
+
textAlign,
|
|
10
|
+
clickable,
|
|
11
|
+
ariaLabel,
|
|
12
|
+
onClick,
|
|
13
|
+
children,
|
|
14
|
+
}: {
|
|
15
|
+
variant?: CardVariant;
|
|
16
|
+
padding?: CardPadding;
|
|
17
|
+
textAlign?: CardTextAlign;
|
|
18
|
+
clickable?: boolean;
|
|
19
|
+
ariaLabel?: string;
|
|
20
|
+
onClick?: () => void;
|
|
21
|
+
children?: React.ReactNode;
|
|
22
|
+
}) {
|
|
23
|
+
return React.createElement(
|
|
24
|
+
'bds-card',
|
|
25
|
+
{
|
|
26
|
+
variant,
|
|
27
|
+
padding,
|
|
28
|
+
'text-align': textAlign,
|
|
29
|
+
clickable: clickable || undefined,
|
|
30
|
+
'aria-label': ariaLabel,
|
|
31
|
+
onbdsclick: onClick,
|
|
32
|
+
},
|
|
33
|
+
children,
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const meta = {
|
|
38
|
+
title: 'Web Components/UI/Card',
|
|
39
|
+
component: BdsCard,
|
|
40
|
+
tags: ['!stable', 'experimental'],
|
|
41
|
+
parameters: { layout: 'centered' },
|
|
42
|
+
argTypes: {
|
|
43
|
+
variant: { control: 'select', options: ['default', 'elevated', 'outlined'] },
|
|
44
|
+
padding: { control: 'select', options: ['none', 'small', 'medium', 'large'] },
|
|
45
|
+
textAlign: { control: 'select', options: ['start', 'center', 'end'] },
|
|
46
|
+
},
|
|
47
|
+
} satisfies Meta<typeof BdsCard>;
|
|
48
|
+
|
|
49
|
+
export default meta;
|
|
50
|
+
type Story = StoryObj<typeof meta>;
|
|
51
|
+
|
|
52
|
+
const cardContent = React.createElement(
|
|
53
|
+
'div',
|
|
54
|
+
null,
|
|
55
|
+
React.createElement('strong', null, 'Card title'),
|
|
56
|
+
React.createElement('p', { style: { margin: '8px 0 0' } }, 'Card body with some descriptive text.'),
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
export const Default: Story = { args: { variant: 'default', children: cardContent } };
|
|
60
|
+
export const Elevated: Story = { args: { variant: 'elevated', children: cardContent } };
|
|
61
|
+
export const Outlined: Story = { args: { variant: 'outlined', children: cardContent } };
|
|
62
|
+
export const Clickable: Story = { args: { variant: 'default', clickable: true, ariaLabel: 'Open details', children: cardContent } };
|
|
63
|
+
|
|
64
|
+
export const AllVariants: Story = {
|
|
65
|
+
render: () => (
|
|
66
|
+
<div style={{ display: 'flex', gap: '16px', flexWrap: 'wrap' }}>
|
|
67
|
+
{(['default', 'elevated', 'outlined'] as const).map(v => (
|
|
68
|
+
<BdsCard key={v} variant={v} style={{ width: '200px' } as React.CSSProperties}>
|
|
69
|
+
<strong>{v}</strong>
|
|
70
|
+
<p style={{ margin: '8px 0 0' }}>Card variant</p>
|
|
71
|
+
</BdsCard>
|
|
72
|
+
))}
|
|
73
|
+
</div>
|
|
74
|
+
),
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export const Interactive: Story = {
|
|
78
|
+
render: () => {
|
|
79
|
+
const [count, setCount] = React.useState(0);
|
|
80
|
+
return (
|
|
81
|
+
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '16px' }}>
|
|
82
|
+
<BdsCard variant="elevated" clickable ariaLabel="Click me" onClick={() => setCount(c => c + 1)}>
|
|
83
|
+
<strong>Clickable card</strong>
|
|
84
|
+
<p style={{ margin: '8px 0 0' }}>Click to increment counter</p>
|
|
85
|
+
</BdsCard>
|
|
86
|
+
<p style={{ margin: 0 }}>Clicked {count} times</p>
|
|
87
|
+
</div>
|
|
88
|
+
);
|
|
89
|
+
},
|
|
90
|
+
};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { Meta, Canvas, ArgTypes } from '@storybook/blocks';
|
|
2
|
+
import * as Stories from './BdsDescriptionList.stories';
|
|
3
|
+
|
|
4
|
+
<Meta of={Stories} />
|
|
5
|
+
|
|
6
|
+
# <bds-description-list>
|
|
7
|
+
|
|
8
|
+
Framework-agnostic Description List custom element. Wraps a semantic `<dl>` element for rendering key–value pairs. Consumers provide `<dt>` and `<dd>` elements as slotted children.
|
|
9
|
+
|
|
10
|
+
> **Status: experimental** — API may change before stable release.
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```js
|
|
15
|
+
import '@boostdev/components/web-components';
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Examples
|
|
19
|
+
|
|
20
|
+
### All layouts
|
|
21
|
+
<Canvas of={Stories.AllVariants} />
|
|
22
|
+
|
|
23
|
+
### Stacked
|
|
24
|
+
<Canvas of={Stories.Stacked} />
|
|
25
|
+
|
|
26
|
+
### Inline
|
|
27
|
+
<Canvas of={Stories.Inline} />
|
|
28
|
+
|
|
29
|
+
## Props
|
|
30
|
+
|
|
31
|
+
<ArgTypes of={Stories} />
|
|
32
|
+
|
|
33
|
+
## Attributes
|
|
34
|
+
|
|
35
|
+
| Attribute | Type | Default | Description |
|
|
36
|
+
|-----------|------|---------|-------------|
|
|
37
|
+
| `layout` | `"stacked" \| "inline"` | `"stacked"` | Arrangement of terms and details |
|
|
38
|
+
|
|
39
|
+
## Slots
|
|
40
|
+
|
|
41
|
+
| Slot | Description |
|
|
42
|
+
|------|-------------|
|
|
43
|
+
| `(default)` | `<dt>` and `<dd>` element pairs |
|
|
44
|
+
|
|
45
|
+
## Usage in plain HTML
|
|
46
|
+
|
|
47
|
+
```html
|
|
48
|
+
<bds-description-list>
|
|
49
|
+
<dt>Name</dt>
|
|
50
|
+
<dd>Jane Doe</dd>
|
|
51
|
+
<dt>Email</dt>
|
|
52
|
+
<dd>jane@example.com</dd>
|
|
53
|
+
</bds-description-list>
|
|
54
|
+
|
|
55
|
+
<bds-description-list layout="inline">
|
|
56
|
+
<dt>Status</dt>
|
|
57
|
+
<dd>Active</dd>
|
|
58
|
+
<dt>Role</dt>
|
|
59
|
+
<dd>Designer</dd>
|
|
60
|
+
</bds-description-list>
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Accessibility
|
|
64
|
+
|
|
65
|
+
- Renders a semantic `<dl>` element — screen readers announce it as a description list
|
|
66
|
+
- Ensure `<dt>` and `<dd>` elements are properly paired
|
|
67
|
+
- The `::slotted(dt)` and `::slotted(dd)` CSS selectors apply the visual styling
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
3
|
+
import '../index';
|
|
4
|
+
|
|
5
|
+
function BdsDescriptionList({
|
|
6
|
+
layout,
|
|
7
|
+
children,
|
|
8
|
+
}: {
|
|
9
|
+
layout?: 'stacked' | 'inline';
|
|
10
|
+
children?: React.ReactNode;
|
|
11
|
+
}) {
|
|
12
|
+
return React.createElement('bds-description-list', { layout }, children);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const meta = {
|
|
16
|
+
title: 'Web Components/UI/DescriptionList',
|
|
17
|
+
component: BdsDescriptionList,
|
|
18
|
+
tags: ['!stable', 'experimental'],
|
|
19
|
+
parameters: { layout: 'centered' },
|
|
20
|
+
argTypes: {
|
|
21
|
+
layout: { control: 'select', options: ['stacked', 'inline'] },
|
|
22
|
+
},
|
|
23
|
+
} satisfies Meta<typeof BdsDescriptionList>;
|
|
24
|
+
|
|
25
|
+
export default meta;
|
|
26
|
+
type Story = StoryObj<typeof meta>;
|
|
27
|
+
|
|
28
|
+
const items = [
|
|
29
|
+
{ term: 'Name', detail: 'Jane Doe' },
|
|
30
|
+
{ term: 'Email', detail: 'jane@example.com' },
|
|
31
|
+
{ term: 'Role', detail: 'Designer' },
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
export const Stacked: Story = {
|
|
35
|
+
render: () => (
|
|
36
|
+
<BdsDescriptionList layout="stacked">
|
|
37
|
+
{items.flatMap(({ term, detail }) => [
|
|
38
|
+
React.createElement('dt', { key: `dt-${term}` }, term),
|
|
39
|
+
React.createElement('dd', { key: `dd-${term}` }, detail),
|
|
40
|
+
])}
|
|
41
|
+
</BdsDescriptionList>
|
|
42
|
+
),
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export const Inline: Story = {
|
|
46
|
+
render: () => (
|
|
47
|
+
<BdsDescriptionList layout="inline">
|
|
48
|
+
{items.flatMap(({ term, detail }) => [
|
|
49
|
+
React.createElement('dt', { key: `dt-${term}` }, term),
|
|
50
|
+
React.createElement('dd', { key: `dd-${term}` }, detail),
|
|
51
|
+
])}
|
|
52
|
+
</BdsDescriptionList>
|
|
53
|
+
),
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export const AllVariants: Story = {
|
|
57
|
+
render: () => (
|
|
58
|
+
<div style={{ display: 'flex', gap: '48px', flexWrap: 'wrap', alignItems: 'flex-start' }}>
|
|
59
|
+
<div>
|
|
60
|
+
<p style={{ margin: '0 0 8px', fontSize: '0.75rem', color: '#888', fontWeight: 600 }}>Stacked</p>
|
|
61
|
+
<BdsDescriptionList layout="stacked">
|
|
62
|
+
{items.flatMap(({ term, detail }) => [
|
|
63
|
+
React.createElement('dt', { key: `dt-${term}` }, term),
|
|
64
|
+
React.createElement('dd', { key: `dd-${term}` }, detail),
|
|
65
|
+
])}
|
|
66
|
+
</BdsDescriptionList>
|
|
67
|
+
</div>
|
|
68
|
+
<div>
|
|
69
|
+
<p style={{ margin: '0 0 8px', fontSize: '0.75rem', color: '#888', fontWeight: 600 }}>Inline</p>
|
|
70
|
+
<BdsDescriptionList layout="inline">
|
|
71
|
+
{items.flatMap(({ term, detail }) => [
|
|
72
|
+
React.createElement('dt', { key: `dt-${term}` }, term),
|
|
73
|
+
React.createElement('dd', { key: `dd-${term}` }, detail),
|
|
74
|
+
])}
|
|
75
|
+
</BdsDescriptionList>
|
|
76
|
+
</div>
|
|
77
|
+
</div>
|
|
78
|
+
),
|
|
79
|
+
};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { Meta, Canvas, ArgTypes } from '@storybook/blocks';
|
|
2
|
+
import * as Stories from './BdsIconWrapper.stories';
|
|
3
|
+
|
|
4
|
+
<Meta of={Stories} />
|
|
5
|
+
|
|
6
|
+
# <bds-icon-wrapper>
|
|
7
|
+
|
|
8
|
+
Framework-agnostic Icon Wrapper custom element. Displays an icon inside a circular container with background and foreground theming.
|
|
9
|
+
|
|
10
|
+
> **Status: experimental** — API may change before stable release.
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```js
|
|
15
|
+
import '@boostdev/components/web-components';
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Examples
|
|
19
|
+
|
|
20
|
+
### All variants
|
|
21
|
+
<Canvas of={Stories.AllVariants} />
|
|
22
|
+
|
|
23
|
+
### With star icon
|
|
24
|
+
<Canvas of={Stories.WithStar} />
|
|
25
|
+
|
|
26
|
+
## Props
|
|
27
|
+
|
|
28
|
+
<ArgTypes of={Stories} />
|
|
29
|
+
|
|
30
|
+
## Attributes
|
|
31
|
+
|
|
32
|
+
| Attribute | Type | Default | Description |
|
|
33
|
+
|-----------|------|---------|-------------|
|
|
34
|
+
| `aria-hidden` | string | — | Set to `"true"` for purely decorative icons |
|
|
35
|
+
|
|
36
|
+
## Slots
|
|
37
|
+
|
|
38
|
+
| Slot | Description |
|
|
39
|
+
|------|-------------|
|
|
40
|
+
| `(default)` | Icon content (SVG or `<img>`) |
|
|
41
|
+
|
|
42
|
+
## CSS Custom Properties
|
|
43
|
+
|
|
44
|
+
| Property | Description |
|
|
45
|
+
|----------|-------------|
|
|
46
|
+
| `--icon-wrapper-color` | Circle background colour |
|
|
47
|
+
| `--bds-on-icon-wrapper-color` | Icon fill/stroke colour |
|
|
48
|
+
|
|
49
|
+
## Usage in plain HTML
|
|
50
|
+
|
|
51
|
+
```html
|
|
52
|
+
<!-- Decorative icon -->
|
|
53
|
+
<bds-icon-wrapper aria-hidden="true">
|
|
54
|
+
<svg viewBox="0 0 24 24" fill="currentColor">
|
|
55
|
+
<path d="M12 17.27L18.18 21..."/>
|
|
56
|
+
</svg>
|
|
57
|
+
</bds-icon-wrapper>
|
|
58
|
+
|
|
59
|
+
<!-- Meaningful icon — add aria-label to the wrapper -->
|
|
60
|
+
<bds-icon-wrapper aria-label="Favourite">
|
|
61
|
+
<svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
|
|
62
|
+
<path d="M12 21.593c..."/>
|
|
63
|
+
</svg>
|
|
64
|
+
</bds-icon-wrapper>
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Accessibility
|
|
68
|
+
|
|
69
|
+
- When the icon is decorative, set `aria-hidden="true"` on the host
|
|
70
|
+
- When the icon conveys meaning, set `aria-label` on the host and `aria-hidden="true"` on the SVG itself
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
3
|
+
import '../index';
|
|
4
|
+
|
|
5
|
+
const StarIcon = () =>
|
|
6
|
+
React.createElement(
|
|
7
|
+
'svg',
|
|
8
|
+
{ viewBox: '0 0 24 24', fill: 'currentColor', width: '1.25em', height: '1.25em', 'aria-hidden': 'true' },
|
|
9
|
+
React.createElement('path', {
|
|
10
|
+
d: 'M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z',
|
|
11
|
+
}),
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
const CheckIcon = () =>
|
|
15
|
+
React.createElement(
|
|
16
|
+
'svg',
|
|
17
|
+
{ viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: '2.5', width: '1.25em', height: '1.25em', 'aria-hidden': 'true' },
|
|
18
|
+
React.createElement('path', { strokeLinecap: 'round', strokeLinejoin: 'round', d: 'M5 13l4 4L19 7' }),
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
const HeartIcon = () =>
|
|
22
|
+
React.createElement(
|
|
23
|
+
'svg',
|
|
24
|
+
{ viewBox: '0 0 24 24', fill: 'currentColor', width: '1.25em', height: '1.25em', 'aria-hidden': 'true' },
|
|
25
|
+
React.createElement('path', {
|
|
26
|
+
d: 'M12 21.593c-.425-.052-8.092-5.65-8.092-10.82C3.908 6.64 7.084 4 10.408 4c1.75 0 3.192.806 4.175 2.016A5.355 5.355 0 0 1 18.175 4c3.324 0 6.5 2.64 6.5 6.773 0 5.17-7.667 10.768-8.092 10.82z',
|
|
27
|
+
}),
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
function BdsIconWrapper({ children }: { children?: React.ReactNode }) {
|
|
31
|
+
return React.createElement('bds-icon-wrapper', null, children);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const meta = {
|
|
35
|
+
title: 'Web Components/UI/IconWrapper',
|
|
36
|
+
component: BdsIconWrapper,
|
|
37
|
+
tags: ['!stable', 'experimental'],
|
|
38
|
+
parameters: { layout: 'centered' },
|
|
39
|
+
} satisfies Meta<typeof BdsIconWrapper>;
|
|
40
|
+
|
|
41
|
+
export default meta;
|
|
42
|
+
type Story = StoryObj<typeof meta>;
|
|
43
|
+
|
|
44
|
+
export const WithStar: Story = {
|
|
45
|
+
render: () => (
|
|
46
|
+
<BdsIconWrapper>
|
|
47
|
+
<StarIcon />
|
|
48
|
+
</BdsIconWrapper>
|
|
49
|
+
),
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export const WithCheck: Story = {
|
|
53
|
+
render: () => (
|
|
54
|
+
<BdsIconWrapper>
|
|
55
|
+
<CheckIcon />
|
|
56
|
+
</BdsIconWrapper>
|
|
57
|
+
),
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export const WithHeart: Story = {
|
|
61
|
+
render: () => (
|
|
62
|
+
<BdsIconWrapper>
|
|
63
|
+
<HeartIcon />
|
|
64
|
+
</BdsIconWrapper>
|
|
65
|
+
),
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export const AllVariants: Story = {
|
|
69
|
+
render: () => (
|
|
70
|
+
<div style={{ display: 'flex', gap: '16px', alignItems: 'center' }}>
|
|
71
|
+
<BdsIconWrapper><StarIcon /></BdsIconWrapper>
|
|
72
|
+
<BdsIconWrapper><CheckIcon /></BdsIconWrapper>
|
|
73
|
+
<BdsIconWrapper><HeartIcon /></BdsIconWrapper>
|
|
74
|
+
</div>
|
|
75
|
+
),
|
|
76
|
+
};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { Meta, Canvas, ArgTypes } from '@storybook/blocks';
|
|
2
|
+
import * as Stories from './BdsLink.stories';
|
|
3
|
+
|
|
4
|
+
<Meta of={Stories} />
|
|
5
|
+
|
|
6
|
+
# <bds-link>
|
|
7
|
+
|
|
8
|
+
Framework-agnostic Link custom element. Renders a semantic `<a>` element with three visual styles and built-in external link handling.
|
|
9
|
+
|
|
10
|
+
> **Status: experimental** — API may change before stable release.
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```js
|
|
15
|
+
import '@boostdev/components/web-components';
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Examples
|
|
19
|
+
|
|
20
|
+
### All variants
|
|
21
|
+
<Canvas of={Stories.AllVariants} />
|
|
22
|
+
|
|
23
|
+
### Default
|
|
24
|
+
<Canvas of={Stories.Default} />
|
|
25
|
+
|
|
26
|
+
### Standalone
|
|
27
|
+
<Canvas of={Stories.Standalone} />
|
|
28
|
+
|
|
29
|
+
### External
|
|
30
|
+
<Canvas of={Stories.External} />
|
|
31
|
+
|
|
32
|
+
## Props
|
|
33
|
+
|
|
34
|
+
<ArgTypes of={Stories} />
|
|
35
|
+
|
|
36
|
+
## Attributes
|
|
37
|
+
|
|
38
|
+
| Attribute | Type | Default | Description |
|
|
39
|
+
|-----------|------|---------|-------------|
|
|
40
|
+
| `href` | string | — | Link destination |
|
|
41
|
+
| `target` | string | — | Native anchor target |
|
|
42
|
+
| `variant` | `"default" \| "subtle" \| "standalone"` | `"default"` | Visual style |
|
|
43
|
+
| `external` | boolean | `false` | Adds `rel="noreferrer noopener"`, opens in new tab, appends screen-reader text |
|
|
44
|
+
| `external-label` | string | `"(opens in new tab)"` | Visually-hidden text appended for external links |
|
|
45
|
+
|
|
46
|
+
## Slots
|
|
47
|
+
|
|
48
|
+
| Slot | Description |
|
|
49
|
+
|------|-------------|
|
|
50
|
+
| `(default)` | Link text content |
|
|
51
|
+
|
|
52
|
+
## CSS Custom Properties
|
|
53
|
+
|
|
54
|
+
| Property | Description |
|
|
55
|
+
|----------|-------------|
|
|
56
|
+
| `--link_color` | Link text colour |
|
|
57
|
+
| `--link_color-hover` | Link colour on hover |
|
|
58
|
+
|
|
59
|
+
## Usage in plain HTML
|
|
60
|
+
|
|
61
|
+
```html
|
|
62
|
+
<bds-link href="/docs">Read the docs</bds-link>
|
|
63
|
+
|
|
64
|
+
<bds-link href="/about" variant="subtle">About us</bds-link>
|
|
65
|
+
|
|
66
|
+
<bds-link href="/get-started" variant="standalone">Get started →</bds-link>
|
|
67
|
+
|
|
68
|
+
<bds-link href="https://example.com" external>Visit site</bds-link>
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Accessibility
|
|
72
|
+
|
|
73
|
+
- Renders a native `<a>` — fully keyboard accessible
|
|
74
|
+
- `external` adds a visually-hidden `(opens in new tab)` label for screen reader users and sets `rel="noreferrer noopener"` for security
|
|
75
|
+
- Always provide meaningful link text — avoid "click here" or "read more"
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
3
|
+
import type { LinkVariant } from './bds-link';
|
|
4
|
+
import '../index';
|
|
5
|
+
|
|
6
|
+
function BdsLink({
|
|
7
|
+
href,
|
|
8
|
+
variant,
|
|
9
|
+
external,
|
|
10
|
+
externalLabel,
|
|
11
|
+
children,
|
|
12
|
+
}: {
|
|
13
|
+
href?: string;
|
|
14
|
+
variant?: LinkVariant;
|
|
15
|
+
external?: boolean;
|
|
16
|
+
externalLabel?: string;
|
|
17
|
+
children?: React.ReactNode;
|
|
18
|
+
}) {
|
|
19
|
+
return React.createElement(
|
|
20
|
+
'bds-link',
|
|
21
|
+
{
|
|
22
|
+
href: href ?? '#',
|
|
23
|
+
variant,
|
|
24
|
+
external: external || undefined,
|
|
25
|
+
'external-label': externalLabel,
|
|
26
|
+
},
|
|
27
|
+
children,
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const meta = {
|
|
32
|
+
title: 'Web Components/UI/Link',
|
|
33
|
+
component: BdsLink,
|
|
34
|
+
tags: ['!stable', 'experimental'],
|
|
35
|
+
parameters: { layout: 'centered' },
|
|
36
|
+
argTypes: {
|
|
37
|
+
variant: { control: 'select', options: ['default', 'subtle', 'standalone'] },
|
|
38
|
+
},
|
|
39
|
+
} satisfies Meta<typeof BdsLink>;
|
|
40
|
+
|
|
41
|
+
export default meta;
|
|
42
|
+
type Story = StoryObj<typeof meta>;
|
|
43
|
+
|
|
44
|
+
export const Default: Story = { args: { children: 'Default link', variant: 'default' } };
|
|
45
|
+
export const Subtle: Story = { args: { children: 'Subtle link', variant: 'subtle' } };
|
|
46
|
+
export const Standalone: Story = { args: { children: 'Standalone link →', variant: 'standalone' } };
|
|
47
|
+
export const External: Story = { args: { children: 'External link', variant: 'default', external: true } };
|
|
48
|
+
|
|
49
|
+
export const AllVariants: Story = {
|
|
50
|
+
render: () => (
|
|
51
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: '12px' }}>
|
|
52
|
+
{(['default', 'subtle', 'standalone'] as const).map(v => (
|
|
53
|
+
<div key={v} style={{ display: 'flex', alignItems: 'center', gap: '12px' }}>
|
|
54
|
+
<BdsLink variant={v}>{v.charAt(0).toUpperCase() + v.slice(1)} link</BdsLink>
|
|
55
|
+
<span style={{ fontSize: '0.75rem', color: '#888' }}>{v}</span>
|
|
56
|
+
</div>
|
|
57
|
+
))}
|
|
58
|
+
<div style={{ display: 'flex', alignItems: 'center', gap: '12px' }}>
|
|
59
|
+
<BdsLink external>External link</BdsLink>
|
|
60
|
+
<span style={{ fontSize: '0.75rem', color: '#888' }}>external</span>
|
|
61
|
+
</div>
|
|
62
|
+
</div>
|
|
63
|
+
),
|
|
64
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { Meta, Canvas, ArgTypes } from '@storybook/blocks';
|
|
2
|
+
import * as Stories from './BdsLoading.stories';
|
|
3
|
+
|
|
4
|
+
<Meta of={Stories} />
|
|
5
|
+
|
|
6
|
+
# <bds-loading>
|
|
7
|
+
|
|
8
|
+
Framework-agnostic Loading spinner custom element. Use to indicate an ongoing asynchronous operation.
|
|
9
|
+
|
|
10
|
+
> **Status: experimental** — API may change before stable release.
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```js
|
|
15
|
+
import '@boostdev/components/web-components';
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Examples
|
|
19
|
+
|
|
20
|
+
### All sizes
|
|
21
|
+
<Canvas of={Stories.AllVariants} />
|
|
22
|
+
|
|
23
|
+
### Small
|
|
24
|
+
<Canvas of={Stories.Small} />
|
|
25
|
+
|
|
26
|
+
### Medium
|
|
27
|
+
<Canvas of={Stories.Medium} />
|
|
28
|
+
|
|
29
|
+
### Large
|
|
30
|
+
<Canvas of={Stories.Large} />
|
|
31
|
+
|
|
32
|
+
## Props
|
|
33
|
+
|
|
34
|
+
<ArgTypes of={Stories} />
|
|
35
|
+
|
|
36
|
+
## Attributes
|
|
37
|
+
|
|
38
|
+
| Attribute | Type | Default | Description |
|
|
39
|
+
|-----------|------|---------|-------------|
|
|
40
|
+
| `size` | `"small" \| "medium" \| "large"` | `"medium"` | Spinner diameter |
|
|
41
|
+
|
|
42
|
+
## CSS Custom Properties
|
|
43
|
+
|
|
44
|
+
The spinner uses design tokens directly:
|
|
45
|
+
|
|
46
|
+
| Token | Description |
|
|
47
|
+
|-------|-------------|
|
|
48
|
+
| `--bds-color_bg` | Track colour |
|
|
49
|
+
| `--bds-color_interactive` | Active arc colour |
|
|
50
|
+
|
|
51
|
+
## Usage in plain HTML
|
|
52
|
+
|
|
53
|
+
```html
|
|
54
|
+
<bds-loading></bds-loading>
|
|
55
|
+
<bds-loading size="small"></bds-loading>
|
|
56
|
+
<bds-loading size="large"></bds-loading>
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Accessibility
|
|
60
|
+
|
|
61
|
+
- Renders a `role="status"` element with `aria-label="Loading"` — screen readers announce the loading state
|
|
62
|
+
- Respects `prefers-reduced-motion`: the spin animation stops for users who prefer reduced motion
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
3
|
+
import '../index';
|
|
4
|
+
|
|
5
|
+
function BdsLoading({ size }: { size?: 'small' | 'medium' | 'large' }) {
|
|
6
|
+
return React.createElement('bds-loading', { size });
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const meta = {
|
|
10
|
+
title: 'Web Components/UI/Loading',
|
|
11
|
+
component: BdsLoading,
|
|
12
|
+
tags: ['!stable', 'experimental'],
|
|
13
|
+
parameters: { layout: 'centered' },
|
|
14
|
+
argTypes: {
|
|
15
|
+
size: { control: 'select', options: ['small', 'medium', 'large'] },
|
|
16
|
+
},
|
|
17
|
+
} satisfies Meta<typeof BdsLoading>;
|
|
18
|
+
|
|
19
|
+
export default meta;
|
|
20
|
+
type Story = StoryObj<typeof meta>;
|
|
21
|
+
|
|
22
|
+
export const Small: Story = { args: { size: 'small' } };
|
|
23
|
+
export const Medium: Story = { args: { size: 'medium' } };
|
|
24
|
+
export const Large: Story = { args: { size: 'large' } };
|
|
25
|
+
|
|
26
|
+
export const AllVariants: Story = {
|
|
27
|
+
render: () => (
|
|
28
|
+
<div style={{ display: 'flex', alignItems: 'center', gap: '32px' }}>
|
|
29
|
+
{(['small', 'medium', 'large'] as const).map(s => (
|
|
30
|
+
<div key={s} style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '8px' }}>
|
|
31
|
+
<BdsLoading size={s} />
|
|
32
|
+
<span style={{ fontSize: '0.75rem', color: '#888' }}>{s}</span>
|
|
33
|
+
</div>
|
|
34
|
+
))}
|
|
35
|
+
</div>
|
|
36
|
+
),
|
|
37
|
+
};
|