@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.
Files changed (169) hide show
  1. package/AGENTS.md +13 -10
  2. package/dist/client.cjs +77 -99
  3. package/dist/client.css +611 -580
  4. package/dist/client.d.cts +13 -16
  5. package/dist/client.d.ts +13 -16
  6. package/dist/client.js +87 -109
  7. package/dist/index.cjs +77 -99
  8. package/dist/index.css +611 -580
  9. package/dist/index.d.cts +13 -16
  10. package/dist/index.d.ts +13 -16
  11. package/dist/index.js +87 -109
  12. package/dist/native/index.cjs +9 -8
  13. package/dist/native/index.d.cts +1 -1
  14. package/dist/native/index.d.ts +1 -1
  15. package/dist/native/index.js +9 -8
  16. package/dist/web-components/{chunk-O4UFI2RX.js → chunk-3REOIRDW.js} +13 -11
  17. package/dist/web-components/{chunk-K5CE6HSB.js → chunk-6MH5UWUD.js} +74 -17
  18. package/dist/web-components/{chunk-VM3YHGQ2.js → chunk-AJSXNDAP.js} +1 -2
  19. package/dist/web-components/{chunk-LSC4N56Q.js → chunk-BX3IPVOB.js} +1 -2
  20. package/dist/web-components/{chunk-CJ5ZOO42.js → chunk-DI46Q2EA.js} +50 -1
  21. package/dist/web-components/{chunk-CAPI25CU.js → chunk-DZRSJGPB.js} +3 -3
  22. package/dist/web-components/{chunk-VSS5ITNE.js → chunk-EBJM3VD4.js} +1 -3
  23. package/dist/web-components/{chunk-O7I63SQX.js → chunk-HHHRF2PS.js} +6 -12
  24. package/dist/web-components/{chunk-OTX4COSV.js → chunk-JUKB3BUP.js} +3 -4
  25. package/dist/web-components/{chunk-IQGLIQSO.js → chunk-N6IMUOY4.js} +2 -5
  26. package/dist/web-components/{chunk-QDRH46TF.js → chunk-QLZ2362S.js} +1 -3
  27. package/dist/web-components/{chunk-IK3PTFZ4.js → chunk-T6AETZRP.js} +1 -3
  28. package/dist/web-components/{chunk-4BX6AWXX.js → chunk-X3FKVHLK.js} +2 -4
  29. package/dist/web-components/{chunk-A67LCT7C.js → chunk-XNA6WTXG.js} +3 -4
  30. package/dist/web-components/{chunk-XIENXR7H.js → chunk-YRXCVKHV.js} +1 -3
  31. package/dist/web-components/{chunk-6T3RKUKG.js → chunk-ZTC6GRP7.js} +1 -2
  32. package/dist/web-components/globals.js +1 -1
  33. package/dist/web-components/index.js +16 -16
  34. package/dist/web-components/interaction/bds-accordion.js +1 -1
  35. package/dist/web-components/interaction/bds-button.d.ts +2 -2
  36. package/dist/web-components/interaction/bds-button.js +1 -1
  37. package/dist/web-components/interaction/bds-dialog.js +1 -1
  38. package/dist/web-components/interaction/bds-drawer.js +1 -1
  39. package/dist/web-components/interaction/form/bds-checkbox.js +1 -1
  40. package/dist/web-components/interaction/form/bds-combobox.js +1 -1
  41. package/dist/web-components/interaction/form/bds-number-input.js +1 -1
  42. package/dist/web-components/interaction/form/bds-radio.js +1 -1
  43. package/dist/web-components/interaction/form/bds-segmented-control.d.ts +20 -3
  44. package/dist/web-components/interaction/form/bds-segmented-control.js +1 -1
  45. package/dist/web-components/interaction/form/bds-select.js +1 -1
  46. package/dist/web-components/interaction/form/bds-switch.js +1 -1
  47. package/dist/web-components/interaction/form/bds-textarea.js +1 -1
  48. package/dist/web-components/ui/bds-alert.js +1 -1
  49. package/dist/web-components/ui/bds-card.js +1 -1
  50. package/dist/web-components/ui/bds-notification-banner.js +1 -1
  51. package/package.json +2 -2
  52. package/src/components/interaction/Button/Button.module.css +12 -11
  53. package/src/components/interaction/Button/Button.native.tsx +10 -9
  54. package/src/components/interaction/Button/Button.tsx +1 -1
  55. package/src/components/interaction/Command/Command.module.css +3 -7
  56. package/src/components/interaction/Dialog/Dialog.module.css +7 -5
  57. package/src/components/interaction/Drawer/Drawer.module.css +49 -1
  58. package/src/components/interaction/DropdownMenu/DropdownMenu.module.css +1 -3
  59. package/src/components/interaction/Popover/Popover.module.css +1 -3
  60. package/src/components/interaction/form/Checkbox/Checkbox.module.css +1 -3
  61. package/src/components/interaction/form/Combobox/Combobox.module.css +2 -6
  62. package/src/components/interaction/form/FormInput/FormInput.module.css +1 -3
  63. package/src/components/interaction/form/NumberInput/NumberInput.module.css +16 -4
  64. package/src/components/interaction/form/Radio/Radio.module.css +6 -16
  65. package/src/components/interaction/form/SegmentedControl/SegmentedControl.mdx +70 -25
  66. package/src/components/interaction/form/SegmentedControl/SegmentedControl.module.css +55 -33
  67. package/src/components/interaction/form/SegmentedControl/SegmentedControl.spec.tsx +127 -56
  68. package/src/components/interaction/form/SegmentedControl/SegmentedControl.stories.tsx +89 -72
  69. package/src/components/interaction/form/SegmentedControl/SegmentedControl.tsx +40 -62
  70. package/src/components/interaction/form/SegmentedControl/index.ts +1 -1
  71. package/src/components/interaction/form/Select/Select.module.css +2 -4
  72. package/src/components/interaction/form/Switch/Switch.module.css +5 -7
  73. package/src/components/interaction/form/Switch/Switch.native.spec.tsx +9 -9
  74. package/src/components/interaction/form/Switch/Switch.native.tsx +2 -2
  75. package/src/components/interaction/form/Textarea/Textarea.module.css +1 -3
  76. package/src/components/interaction/form/atoms/InputContainer.stories.tsx +64 -0
  77. package/src/components/interaction/form/atoms/Label.stories.tsx +33 -0
  78. package/src/components/interaction/form/atoms/Message.stories.tsx +33 -0
  79. package/src/components/layout/Card/Card.module.css +1 -3
  80. package/src/components/ui/Accordion/Accordion.module.css +1 -2
  81. package/src/components/ui/Alert/Alert.module.css +1 -2
  82. package/src/components/ui/Calendar/Calendar.module.css +2 -5
  83. package/src/components/ui/Carousel/Carousel.module.css +1 -3
  84. package/src/components/ui/NotificationBanner/NotificationBanner.module.css +1 -2
  85. package/src/components/ui/Pagination/Pagination.module.css +1 -2
  86. package/src/components/ui/SkipLink/SkipLink.module.css +1 -2
  87. package/src/components/ui/Table/Table.module.css +1 -2
  88. package/src/css/bdc.css +16 -11
  89. package/src/index.ts +1 -1
  90. package/src/web-components/globals.ts +3 -3
  91. package/src/web-components/interaction/BdsAccordion.mdx +51 -0
  92. package/src/web-components/interaction/BdsAccordion.stories.tsx +85 -0
  93. package/src/web-components/interaction/BdsCollapsible.mdx +46 -0
  94. package/src/web-components/interaction/BdsCollapsible.stories.tsx +87 -0
  95. package/src/web-components/interaction/BdsDialog.mdx +49 -0
  96. package/src/web-components/interaction/BdsDialog.stories.tsx +75 -0
  97. package/src/web-components/interaction/BdsDrawer.mdx +50 -0
  98. package/src/web-components/interaction/BdsDrawer.stories.tsx +66 -0
  99. package/src/web-components/interaction/BdsSkipLink.mdx +34 -0
  100. package/src/web-components/interaction/BdsSkipLink.stories.tsx +55 -0
  101. package/src/web-components/interaction/BdsTabs.mdx +47 -0
  102. package/src/web-components/interaction/BdsTabs.stories.tsx +80 -0
  103. package/src/web-components/interaction/BdsTooltip.mdx +38 -0
  104. package/src/web-components/interaction/BdsTooltip.stories.tsx +68 -0
  105. package/src/web-components/interaction/bds-accordion.ts +1 -2
  106. package/src/web-components/interaction/bds-button.ts +15 -13
  107. package/src/web-components/interaction/bds-dialog.ts +2 -5
  108. package/src/web-components/interaction/bds-drawer.ts +50 -1
  109. package/src/web-components/interaction/form/BdsCheckbox.mdx +39 -0
  110. package/src/web-components/interaction/form/BdsCheckbox.stories.tsx +73 -0
  111. package/src/web-components/interaction/form/BdsCombobox.mdx +52 -0
  112. package/src/web-components/interaction/form/BdsCombobox.stories.tsx +91 -0
  113. package/src/web-components/interaction/form/BdsFileInput.mdx +44 -0
  114. package/src/web-components/interaction/form/BdsFileInput.stories.tsx +84 -0
  115. package/src/web-components/interaction/form/BdsNumberInput.mdx +41 -0
  116. package/src/web-components/interaction/form/BdsNumberInput.stories.tsx +90 -0
  117. package/src/web-components/interaction/form/BdsRadio.mdx +41 -0
  118. package/src/web-components/interaction/form/BdsRadio.stories.tsx +90 -0
  119. package/src/web-components/interaction/form/BdsSegmentedControl.mdx +42 -0
  120. package/src/web-components/interaction/form/BdsSegmentedControl.stories.tsx +92 -0
  121. package/src/web-components/interaction/form/BdsSelect.mdx +38 -0
  122. package/src/web-components/interaction/form/BdsSelect.stories.tsx +93 -0
  123. package/src/web-components/interaction/form/BdsSlider.mdx +49 -0
  124. package/src/web-components/interaction/form/BdsSlider.stories.tsx +89 -0
  125. package/src/web-components/interaction/form/BdsSwitch.mdx +39 -0
  126. package/src/web-components/interaction/form/BdsSwitch.stories.tsx +73 -0
  127. package/src/web-components/interaction/form/BdsTextarea.mdx +41 -0
  128. package/src/web-components/interaction/form/BdsTextarea.stories.tsx +79 -0
  129. package/src/web-components/interaction/form/bds-checkbox.ts +1 -3
  130. package/src/web-components/interaction/form/bds-combobox.ts +1 -3
  131. package/src/web-components/interaction/form/bds-number-input.ts +3 -4
  132. package/src/web-components/interaction/form/bds-radio.ts +6 -12
  133. package/src/web-components/interaction/form/bds-segmented-control.ts +91 -20
  134. package/src/web-components/interaction/form/bds-select.ts +2 -4
  135. package/src/web-components/interaction/form/bds-switch.ts +3 -4
  136. package/src/web-components/interaction/form/bds-textarea.ts +1 -3
  137. package/src/web-components/ui/BdsAvatar.mdx +67 -0
  138. package/src/web-components/ui/BdsAvatar.stories.tsx +62 -0
  139. package/src/web-components/ui/BdsBreadcrumb.mdx +63 -0
  140. package/src/web-components/ui/BdsBreadcrumb.stories.tsx +59 -0
  141. package/src/web-components/ui/BdsCard.mdx +83 -0
  142. package/src/web-components/ui/BdsCard.stories.tsx +90 -0
  143. package/src/web-components/ui/BdsDescriptionList.mdx +67 -0
  144. package/src/web-components/ui/BdsDescriptionList.stories.tsx +79 -0
  145. package/src/web-components/ui/BdsIconWrapper.mdx +70 -0
  146. package/src/web-components/ui/BdsIconWrapper.stories.tsx +76 -0
  147. package/src/web-components/ui/BdsLink.mdx +75 -0
  148. package/src/web-components/ui/BdsLink.stories.tsx +64 -0
  149. package/src/web-components/ui/BdsLoading.mdx +62 -0
  150. package/src/web-components/ui/BdsLoading.stories.tsx +37 -0
  151. package/src/web-components/ui/BdsNotificationBanner.mdx +90 -0
  152. package/src/web-components/ui/BdsNotificationBanner.stories.tsx +93 -0
  153. package/src/web-components/ui/BdsProgress.mdx +63 -0
  154. package/src/web-components/ui/BdsProgress.stories.tsx +70 -0
  155. package/src/web-components/ui/BdsProgressCircle.mdx +64 -0
  156. package/src/web-components/ui/BdsProgressCircle.stories.tsx +69 -0
  157. package/src/web-components/ui/BdsRating.mdx +61 -0
  158. package/src/web-components/ui/BdsRating.stories.tsx +39 -0
  159. package/src/web-components/ui/BdsSectionHeader.mdx +69 -0
  160. package/src/web-components/ui/BdsSectionHeader.stories.tsx +56 -0
  161. package/src/web-components/ui/BdsSeparator.mdx +63 -0
  162. package/src/web-components/ui/BdsSeparator.stories.tsx +47 -0
  163. package/src/web-components/ui/BdsSkeleton.mdx +67 -0
  164. package/src/web-components/ui/BdsSkeleton.stories.tsx +50 -0
  165. package/src/web-components/ui/BdsTypography.mdx +83 -0
  166. package/src/web-components/ui/BdsTypography.stories.tsx +51 -0
  167. package/src/web-components/ui/bds-alert.ts +1 -2
  168. package/src/web-components/ui/bds-card.ts +1 -3
  169. package/src/web-components/ui/bds-notification-banner.ts +1 -2
@@ -0,0 +1,90 @@
1
+ import { Meta, Canvas, ArgTypes } from '@storybook/blocks';
2
+ import * as Stories from './BdsNotificationBanner.stories';
3
+
4
+ <Meta of={Stories} />
5
+
6
+ # &lt;bds-notification-banner&gt;
7
+
8
+ Framework-agnostic full-width Notification Banner. Use for page-level messages that require user attention — system notices, maintenance windows, or status updates.
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
+ ### Dismissible
24
+ <Canvas of={Stories.Interactive} />
25
+
26
+ ### With action
27
+ <Canvas of={Stories.WithAction} />
28
+
29
+ ## Props
30
+
31
+ <ArgTypes of={Stories} />
32
+
33
+ ## Attributes
34
+
35
+ | Attribute | Type | Default | Description |
36
+ |-----------|------|---------|-------------|
37
+ | `variant` | `"info" \| "success" \| "warning" \| "error"` | `"info"` | Semantic colour and urgency |
38
+ | `dismissible` | boolean | `false` | Shows a dismiss (×) button |
39
+ | `dismiss-label` | string | `"Dismiss notification"` | Accessible label for the dismiss button |
40
+
41
+ ## Slots
42
+
43
+ | Slot | Description |
44
+ |------|-------------|
45
+ | `(default)` | Banner body content |
46
+ | `action` | Optional action area (e.g. a button or link) |
47
+
48
+ ## Events
49
+
50
+ | Event | Detail | Bubbles | Composed | Description |
51
+ |-------|--------|---------|----------|-------------|
52
+ | `bds-dismiss` | — | Yes | Yes | Fired when the dismiss button is clicked |
53
+
54
+ ## CSS Custom Properties
55
+
56
+ | Property | Description |
57
+ |----------|-------------|
58
+ | `--banner_bg` | Banner background colour |
59
+ | `--banner_text` | Banner text colour |
60
+ | `--banner_border` | Bottom border accent colour |
61
+
62
+ ## Usage in plain HTML
63
+
64
+ ```html
65
+ <bds-notification-banner variant="success">
66
+ Your changes have been saved.
67
+ </bds-notification-banner>
68
+
69
+ <bds-notification-banner variant="warning" dismissible>
70
+ Scheduled maintenance on Sunday.
71
+ </bds-notification-banner>
72
+
73
+ <bds-notification-banner variant="info">
74
+ New features available.
75
+ <button slot="action" type="button">Learn more</button>
76
+ </bds-notification-banner>
77
+ ```
78
+
79
+ Listen for dismiss:
80
+ ```js
81
+ document.querySelector('bds-notification-banner').addEventListener('bds-dismiss', () => {
82
+ // hide or remove the element
83
+ });
84
+ ```
85
+
86
+ ## Accessibility
87
+
88
+ - `error` and `warning` variants use `role="alert"` + `aria-live="assertive"` — announced immediately
89
+ - `info` and `success` variants use `role="status"` + `aria-live="polite"` — announced at next opportunity
90
+ - The dismiss button has an accessible label; customize with `dismiss-label` when needed
@@ -0,0 +1,93 @@
1
+ import React from 'react';
2
+ import type { Meta, StoryObj } from '@storybook/react';
3
+ import type { NotificationBannerVariant } from './bds-notification-banner';
4
+ import '../index';
5
+
6
+ function BdsNotificationBanner({
7
+ variant = 'info',
8
+ dismissible,
9
+ dismissLabel,
10
+ onDismiss,
11
+ action,
12
+ children,
13
+ }: {
14
+ variant?: NotificationBannerVariant;
15
+ dismissible?: boolean;
16
+ dismissLabel?: string;
17
+ onDismiss?: () => void;
18
+ action?: React.ReactNode;
19
+ children?: React.ReactNode;
20
+ }) {
21
+ return React.createElement(
22
+ 'bds-notification-banner',
23
+ {
24
+ variant,
25
+ dismissible: dismissible || undefined,
26
+ 'dismiss-label': dismissLabel,
27
+ onbdsdismiss: onDismiss,
28
+ },
29
+ children,
30
+ action ? React.createElement('span', { slot: 'action' }, action) : null,
31
+ );
32
+ }
33
+
34
+ const meta = {
35
+ title: 'Web Components/UI/NotificationBanner',
36
+ component: BdsNotificationBanner,
37
+ tags: ['!stable', 'experimental'],
38
+ parameters: { layout: 'padded' },
39
+ argTypes: {
40
+ variant: { control: 'select', options: ['info', 'success', 'warning', 'error'] },
41
+ },
42
+ } satisfies Meta<typeof BdsNotificationBanner>;
43
+
44
+ export default meta;
45
+ type Story = StoryObj<typeof meta>;
46
+
47
+ export const Info: Story = { args: { children: 'Your session will expire in 10 minutes.', variant: 'info' } };
48
+ export const Success: Story = { args: { children: 'Your changes have been saved.', variant: 'success' } };
49
+ export const Warning: Story = { args: { children: 'Scheduled maintenance on Sunday 02:00–04:00 UTC.', variant: 'warning' } };
50
+ export const Error: Story = { args: { children: 'Something went wrong. Please try again.', variant: 'error' } };
51
+ export const Dismissible: Story = { args: { children: 'This banner can be dismissed.', variant: 'info', dismissible: true } };
52
+ export const WithAction: Story = {
53
+ render: () => (
54
+ <BdsNotificationBanner
55
+ variant="warning"
56
+ action={React.createElement('button', { type: 'button' }, 'Learn more')}
57
+ >
58
+ New terms of service take effect on Jan 1.
59
+ </BdsNotificationBanner>
60
+ ),
61
+ };
62
+
63
+ export const AllVariants: Story = {
64
+ render: () => (
65
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '0' }}>
66
+ {(['info', 'success', 'warning', 'error'] as const).map(v => (
67
+ <BdsNotificationBanner key={v} variant={v}>
68
+ This is a {v} notification banner.
69
+ </BdsNotificationBanner>
70
+ ))}
71
+ </div>
72
+ ),
73
+ };
74
+
75
+ export const Interactive: Story = {
76
+ render: () => {
77
+ const [visible, setVisible] = React.useState(true);
78
+ return (
79
+ <div style={{ width: '100%' }}>
80
+ {visible ? (
81
+ <BdsNotificationBanner variant="info" dismissible onDismiss={() => setVisible(false)}>
82
+ Click × to dismiss this banner.
83
+ </BdsNotificationBanner>
84
+ ) : (
85
+ <div style={{ padding: '1rem', textAlign: 'center' }}>
86
+ <p style={{ margin: '0 0 8px' }}>Banner dismissed.</p>
87
+ <button onClick={() => setVisible(true)}>Show again</button>
88
+ </div>
89
+ )}
90
+ </div>
91
+ );
92
+ },
93
+ };
@@ -0,0 +1,63 @@
1
+ import { Meta, Canvas, ArgTypes } from '@storybook/blocks';
2
+ import * as Stories from './BdsProgress.stories';
3
+
4
+ <Meta of={Stories} />
5
+
6
+ # &lt;bds-progress&gt;
7
+
8
+ Framework-agnostic linear Progress bar custom element. Use to show completion status of a task or upload.
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 values
21
+ <Canvas of={Stories.AllVariants} />
22
+
23
+ ### With label
24
+ <Canvas of={Stories.WithLabel} />
25
+
26
+ ### Animated
27
+ <Canvas of={Stories.Interactive} />
28
+
29
+ ## Props
30
+
31
+ <ArgTypes of={Stories} />
32
+
33
+ ## Attributes
34
+
35
+ | Attribute | Type | Default | Description |
36
+ |-----------|------|---------|-------------|
37
+ | `value` | number | `0` | Current progress value |
38
+ | `max` | number | `100` | Maximum value |
39
+ | `label` | string | — | Accessible label text |
40
+ | `show-label` | boolean | `false` | Displays label and percentage above the bar |
41
+ | `size` | `"small" \| "medium" \| "large"` | `"medium"` | Track thickness |
42
+
43
+ ## CSS Custom Properties
44
+
45
+ | Property | Description |
46
+ |----------|-------------|
47
+ | `--progress_color-active` | Fill colour (defaults to `--bdc-color_active`) |
48
+
49
+ ## Usage in plain HTML
50
+
51
+ ```html
52
+ <bds-progress value="60"></bds-progress>
53
+
54
+ <bds-progress value="75" label="Upload progress" show-label></bds-progress>
55
+
56
+ <bds-progress value="40" size="large" label="Loading" show-label></bds-progress>
57
+ ```
58
+
59
+ ## Accessibility
60
+
61
+ - Renders `role="progressbar"` with `aria-valuenow`, `aria-valuemin`, `aria-valuemax`, and `aria-label`
62
+ - Always provide a meaningful `label` for screen reader users
63
+ - Transition animation respects `prefers-reduced-motion`
@@ -0,0 +1,70 @@
1
+ import React from 'react';
2
+ import type { Meta, StoryObj } from '@storybook/react';
3
+ import '../index';
4
+
5
+ function BdsProgress({
6
+ value = 0,
7
+ max,
8
+ label,
9
+ showLabel,
10
+ size,
11
+ }: {
12
+ value?: number;
13
+ max?: number;
14
+ label?: string;
15
+ showLabel?: boolean;
16
+ size?: 'small' | 'medium' | 'large';
17
+ }) {
18
+ return React.createElement('bds-progress', {
19
+ value,
20
+ max,
21
+ label,
22
+ 'show-label': showLabel || undefined,
23
+ size,
24
+ });
25
+ }
26
+
27
+ const meta = {
28
+ title: 'Web Components/UI/Progress',
29
+ component: BdsProgress,
30
+ tags: ['!stable', 'experimental'],
31
+ parameters: { layout: 'padded' },
32
+ argTypes: {
33
+ size: { control: 'select', options: ['small', 'medium', 'large'] },
34
+ },
35
+ } satisfies Meta<typeof BdsProgress>;
36
+
37
+ export default meta;
38
+ type Story = StoryObj<typeof meta>;
39
+
40
+ export const Default: Story = { args: { value: 60 } };
41
+ export const WithLabel: Story = { args: { value: 75, label: 'Upload progress', showLabel: true } };
42
+ export const Complete: Story = { args: { value: 100, label: 'Complete', showLabel: true } };
43
+ export const Small: Story = { args: { value: 40, size: 'small' } };
44
+ export const Medium: Story = { args: { value: 40, size: 'medium' } };
45
+ export const Large: Story = { args: { value: 40, size: 'large' } };
46
+
47
+ export const AllVariants: Story = {
48
+ render: () => (
49
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '16px', maxWidth: '400px' }}>
50
+ {[25, 50, 75, 100].map(v => (
51
+ <BdsProgress key={v} value={v} label={`${v}%`} showLabel />
52
+ ))}
53
+ </div>
54
+ ),
55
+ };
56
+
57
+ export const Interactive: Story = {
58
+ render: () => {
59
+ const [value, setValue] = React.useState(0);
60
+ React.useEffect(() => {
61
+ const id = setInterval(() => setValue(v => (v >= 100 ? 0 : v + 5)), 200);
62
+ return () => clearInterval(id);
63
+ }, []);
64
+ return (
65
+ <div style={{ maxWidth: '400px', display: 'flex', flexDirection: 'column', gap: '12px' }}>
66
+ <BdsProgress value={value} label="Loading…" showLabel />
67
+ </div>
68
+ );
69
+ },
70
+ };
@@ -0,0 +1,64 @@
1
+ import { Meta, Canvas, ArgTypes } from '@storybook/blocks';
2
+ import * as Stories from './BdsProgressCircle.stories';
3
+
4
+ <Meta of={Stories} />
5
+
6
+ # &lt;bds-progress-circle&gt;
7
+
8
+ Framework-agnostic circular Progress indicator. Uses SVG to render a smooth arc that fills based on `value / max`.
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
+ ### With value
24
+ <Canvas of={Stories.WithValue} />
25
+
26
+ ### Animated
27
+ <Canvas of={Stories.Interactive} />
28
+
29
+ ## Props
30
+
31
+ <ArgTypes of={Stories} />
32
+
33
+ ## Attributes
34
+
35
+ | Attribute | Type | Default | Description |
36
+ |-----------|------|---------|-------------|
37
+ | `value` | number | `0` | Current progress value |
38
+ | `max` | number | `100` | Maximum value |
39
+ | `label` | string | — | Accessible label text |
40
+ | `show-value` | boolean | `false` | Displays the percentage in the centre |
41
+ | `size` | `"small" \| "medium" \| "large"` | `"medium"` | SVG diameter (`40px` / `64px` / `96px`) |
42
+
43
+ ## CSS Custom Properties
44
+
45
+ | Property | Description |
46
+ |----------|-------------|
47
+ | `--progressCircle_color-active` | Arc stroke colour (defaults to `--bdc-color_active`) |
48
+
49
+ ## Usage in plain HTML
50
+
51
+ ```html
52
+ <bds-progress-circle value="75" label="Loading"></bds-progress-circle>
53
+
54
+ <bds-progress-circle value="65" label="Upload" show-value></bds-progress-circle>
55
+
56
+ <bds-progress-circle value="80" size="large" label="Progress" show-value></bds-progress-circle>
57
+ ```
58
+
59
+ ## Accessibility
60
+
61
+ - Renders `role="progressbar"` with `aria-valuenow`, `aria-valuemin`, `aria-valuemax`, and `aria-label`
62
+ - Always provide a meaningful `label` for screen readers
63
+ - SVG is hidden from assistive technology (`aria-hidden="true"`) — ARIA attributes are on the container
64
+ - Stroke transition respects `prefers-reduced-motion`
@@ -0,0 +1,69 @@
1
+ import React from 'react';
2
+ import type { Meta, StoryObj } from '@storybook/react';
3
+ import '../index';
4
+
5
+ function BdsProgressCircle({
6
+ value = 0,
7
+ max,
8
+ label,
9
+ showValue,
10
+ size,
11
+ }: {
12
+ value?: number;
13
+ max?: number;
14
+ label?: string;
15
+ showValue?: boolean;
16
+ size?: 'small' | 'medium' | 'large';
17
+ }) {
18
+ return React.createElement('bds-progress-circle', {
19
+ value,
20
+ max,
21
+ label,
22
+ 'show-value': showValue || undefined,
23
+ size,
24
+ });
25
+ }
26
+
27
+ const meta = {
28
+ title: 'Web Components/UI/ProgressCircle',
29
+ component: BdsProgressCircle,
30
+ tags: ['!stable', 'experimental'],
31
+ parameters: { layout: 'centered' },
32
+ argTypes: {
33
+ size: { control: 'select', options: ['small', 'medium', 'large'] },
34
+ },
35
+ } satisfies Meta<typeof BdsProgressCircle>;
36
+
37
+ export default meta;
38
+ type Story = StoryObj<typeof meta>;
39
+
40
+ export const Default: Story = { args: { value: 75 } };
41
+ export const WithValue: Story = { args: { value: 65, showValue: true, label: 'Progress' } };
42
+ export const Complete: Story = { args: { value: 100, showValue: true, label: 'Complete' } };
43
+ export const Small: Story = { args: { value: 60, size: 'small', showValue: true } };
44
+ export const Medium: Story = { args: { value: 60, size: 'medium', showValue: true } };
45
+ export const Large: Story = { args: { value: 60, size: 'large', showValue: true } };
46
+
47
+ export const AllVariants: Story = {
48
+ render: () => (
49
+ <div style={{ display: 'flex', alignItems: 'center', gap: '32px', flexWrap: 'wrap' }}>
50
+ {(['small', 'medium', 'large'] as const).map(s => (
51
+ <div key={s} style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '8px' }}>
52
+ <BdsProgressCircle value={75} size={s} showValue label="Progress" />
53
+ <span style={{ fontSize: '0.75rem', color: '#888' }}>{s}</span>
54
+ </div>
55
+ ))}
56
+ </div>
57
+ ),
58
+ };
59
+
60
+ export const Interactive: Story = {
61
+ render: () => {
62
+ const [value, setValue] = React.useState(0);
63
+ React.useEffect(() => {
64
+ const id = setInterval(() => setValue(v => (v >= 100 ? 0 : v + 2)), 100);
65
+ return () => clearInterval(id);
66
+ }, []);
67
+ return <BdsProgressCircle value={value} showValue label="Loading" size="large" />;
68
+ },
69
+ };
@@ -0,0 +1,61 @@
1
+ import { Meta, Canvas, ArgTypes } from '@storybook/blocks';
2
+ import * as Stories from './BdsRating.stories';
3
+
4
+ <Meta of={Stories} />
5
+
6
+ # &lt;bds-rating&gt;
7
+
8
+ Framework-agnostic read-only star Rating display. Use to show a score or user rating.
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 ratings
21
+ <Canvas of={Stories.AllVariants} />
22
+
23
+ ### 5 stars
24
+ <Canvas of={Stories.FiveStars} />
25
+
26
+ ### Custom max
27
+ <Canvas of={Stories.Custom} />
28
+
29
+ ## Props
30
+
31
+ <ArgTypes of={Stories} />
32
+
33
+ ## Attributes
34
+
35
+ | Attribute | Type | Default | Description |
36
+ |-----------|------|---------|-------------|
37
+ | `value` | number | `0` | Number of filled stars |
38
+ | `max` | number | `5` | Total number of stars |
39
+
40
+ ## CSS Custom Properties
41
+
42
+ | Property | Description |
43
+ |----------|-------------|
44
+ | `--bds-color_warning` | Filled star colour (foundation token) |
45
+
46
+ ## Usage in plain HTML
47
+
48
+ ```html
49
+ <bds-rating value="3"></bds-rating>
50
+
51
+ <bds-rating value="4" max="5"></bds-rating>
52
+
53
+ <!-- Custom scale -->
54
+ <bds-rating value="7" max="10"></bds-rating>
55
+ ```
56
+
57
+ ## Accessibility
58
+
59
+ - Renders `role="img"` with `aria-label="X out of Y stars"`
60
+ - Individual star SVGs are hidden from assistive technology (`aria-hidden="true"`)
61
+ - This is a read-only display — for interactive ratings, use a radio group pattern
@@ -0,0 +1,39 @@
1
+ import React from 'react';
2
+ import type { Meta, StoryObj } from '@storybook/react';
3
+ import '../index';
4
+
5
+ function BdsRating({ value = 0, max }: { value?: number; max?: number }) {
6
+ return React.createElement('bds-rating', { value, max });
7
+ }
8
+
9
+ const meta = {
10
+ title: 'Web Components/UI/Rating',
11
+ component: BdsRating,
12
+ tags: ['!stable', 'experimental'],
13
+ parameters: { layout: 'centered' },
14
+ argTypes: {
15
+ value: { control: { type: 'number', min: 0, max: 10 } },
16
+ max: { control: { type: 'number', min: 1, max: 10 } },
17
+ },
18
+ } satisfies Meta<typeof BdsRating>;
19
+
20
+ export default meta;
21
+ type Story = StoryObj<typeof meta>;
22
+
23
+ export const OneStar: Story = { args: { value: 1 } };
24
+ export const ThreeStars: Story = { args: { value: 3 } };
25
+ export const FiveStars: Story = { args: { value: 5 } };
26
+ export const Custom: Story = { args: { value: 7, max: 10 } };
27
+
28
+ export const AllVariants: Story = {
29
+ render: () => (
30
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
31
+ {[1, 2, 3, 4, 5].map(v => (
32
+ <div key={v} style={{ display: 'flex', alignItems: 'center', gap: '12px' }}>
33
+ <BdsRating value={v} />
34
+ <span style={{ fontSize: '0.875rem', color: '#888' }}>{v}/5</span>
35
+ </div>
36
+ ))}
37
+ </div>
38
+ ),
39
+ };
@@ -0,0 +1,69 @@
1
+ import { Meta, Canvas, ArgTypes } from '@storybook/blocks';
2
+ import * as Stories from './BdsSectionHeader.stories';
3
+
4
+ <Meta of={Stories} />
5
+
6
+ # &lt;bds-section-header&gt;
7
+
8
+ Framework-agnostic Section Header custom element. Use to introduce page sections with a title and optional subtitle.
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
+ ### With subtitle
24
+ <Canvas of={Stories.WithSubtitle} />
25
+
26
+ ### Center aligned
27
+ <Canvas of={Stories.Center} />
28
+
29
+ ## Props
30
+
31
+ <ArgTypes of={Stories} />
32
+
33
+ ## Attributes
34
+
35
+ | Attribute | Type | Default | Description |
36
+ |-----------|------|---------|-------------|
37
+ | `title` | string | — | Heading text (required) |
38
+ | `subtitle` | string | — | Optional subheading |
39
+ | `alignment` | `"start" \| "center" \| "end"` | `"start"` | Text alignment |
40
+ | `size` | `"small" \| "medium" \| "large"` | `"medium"` | Typography scale |
41
+ | `title-as` | string | `"h2"` | HTML tag for the title element |
42
+
43
+ ## CSS Custom Properties
44
+
45
+ | Property | Description |
46
+ |----------|-------------|
47
+ | `--sectionHeader-title-color` | Title text colour |
48
+ | `--sectionHeader_subtitle-color` | Subtitle text colour |
49
+
50
+ ## Usage in plain HTML
51
+
52
+ ```html
53
+ <bds-section-header title="Our Products"></bds-section-header>
54
+
55
+ <bds-section-header
56
+ title="Features"
57
+ subtitle="Everything you need"
58
+ alignment="center"
59
+ size="large"
60
+ ></bds-section-header>
61
+
62
+ <!-- Use h3 when nested inside another section -->
63
+ <bds-section-header title="Subsection" title-as="h3"></bds-section-header>
64
+ ```
65
+
66
+ ## Accessibility
67
+
68
+ - Always set `title-as` to match the correct heading level in the document outline
69
+ - Default is `h2` — adjust if the section header is nested inside an `h2` section
@@ -0,0 +1,56 @@
1
+ import React from 'react';
2
+ import type { Meta, StoryObj } from '@storybook/react';
3
+ import '../index';
4
+
5
+ function BdsSectionHeader({
6
+ title,
7
+ subtitle,
8
+ alignment,
9
+ size,
10
+ titleAs,
11
+ }: {
12
+ title?: string;
13
+ subtitle?: string;
14
+ alignment?: 'start' | 'center' | 'end';
15
+ size?: 'small' | 'medium' | 'large';
16
+ titleAs?: string;
17
+ }) {
18
+ return React.createElement('bds-section-header', {
19
+ title,
20
+ subtitle,
21
+ alignment,
22
+ size,
23
+ 'title-as': titleAs,
24
+ });
25
+ }
26
+
27
+ const meta = {
28
+ title: 'Web Components/UI/SectionHeader',
29
+ component: BdsSectionHeader,
30
+ tags: ['!stable', 'experimental'],
31
+ parameters: { layout: 'padded' },
32
+ argTypes: {
33
+ alignment: { control: 'select', options: ['start', 'center', 'end'] },
34
+ size: { control: 'select', options: ['small', 'medium', 'large'] },
35
+ },
36
+ } satisfies Meta<typeof BdsSectionHeader>;
37
+
38
+ export default meta;
39
+ type Story = StoryObj<typeof meta>;
40
+
41
+ export const Default: Story = { args: { title: 'Our Products' } };
42
+ export const WithSubtitle: Story = { args: { title: 'Our Products', subtitle: 'Browse the full range of components' } };
43
+ export const Center: Story = { args: { title: 'Features', subtitle: 'Everything you need to build faster', alignment: 'center' } };
44
+ export const End: Story = { args: { title: 'Aligned end', alignment: 'end' } };
45
+ export const Small: Story = { args: { title: 'Small header', subtitle: 'Compact section intro', size: 'small' } };
46
+ export const Large: Story = { args: { title: 'Large header', subtitle: 'Hero-scale section heading', size: 'large' } };
47
+
48
+ export const AllVariants: Story = {
49
+ render: () => (
50
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '32px' }}>
51
+ {(['small', 'medium', 'large'] as const).map(s => (
52
+ <BdsSectionHeader key={s} title={`${s.charAt(0).toUpperCase() + s.slice(1)} header`} subtitle="Optional subtitle text" size={s} />
53
+ ))}
54
+ </div>
55
+ ),
56
+ };