@boostdev/design-system-components 1.2.0 → 1.2.1

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 (126) hide show
  1. package/AGENTS.md +25 -4
  2. package/dist/client.cjs +58 -54
  3. package/dist/client.css +503 -525
  4. package/dist/client.js +58 -54
  5. package/dist/index.cjs +58 -54
  6. package/dist/index.css +503 -525
  7. package/dist/index.js +58 -54
  8. package/dist/web-components/{chunk-6MH5UWUD.js → chunk-2FGATTGT.js} +5 -0
  9. package/dist/web-components/{chunk-5IPHEONG.js → chunk-6I2DBFQ7.js} +1 -0
  10. package/dist/web-components/{chunk-DI46Q2EA.js → chunk-OCODKRVZ.js} +57 -82
  11. package/dist/web-components/index.d.ts +571 -1
  12. package/dist/web-components/index.js +1501 -4
  13. package/dist/web-components/interaction/bds-collapsible.js +1 -1
  14. package/dist/web-components/interaction/bds-drawer.js +1 -1
  15. package/dist/web-components/interaction/form/bds-segmented-control.js +1 -1
  16. package/package.json +1 -1
  17. package/src/components/interaction/Drawer/Drawer.module.css +37 -62
  18. package/src/components/interaction/Drawer/Drawer.tsx +21 -17
  19. package/src/components/interaction/form/SegmentedControl/SegmentedControl.mdx +8 -4
  20. package/src/components/interaction/form/SegmentedControl/SegmentedControl.module.css +13 -6
  21. package/src/stories/Introduction.mdx +2 -1
  22. package/src/web-components/index.ts +12 -0
  23. package/src/web-components/interaction/BdsAccordion.mdx +80 -28
  24. package/src/web-components/interaction/BdsAccordion.stories.tsx +67 -58
  25. package/src/web-components/interaction/BdsCollapsible.mdx +93 -23
  26. package/src/web-components/interaction/BdsCollapsible.stories.tsx +29 -48
  27. package/src/web-components/interaction/BdsDialog.mdx +88 -27
  28. package/src/web-components/interaction/BdsDialog.stories.tsx +129 -47
  29. package/src/web-components/interaction/BdsDrawer.mdx +85 -27
  30. package/src/web-components/interaction/BdsDrawer.stories.tsx +161 -31
  31. package/src/web-components/interaction/BdsDropdownMenu.mdx +108 -0
  32. package/src/web-components/interaction/BdsDropdownMenu.stories.tsx +91 -0
  33. package/src/web-components/interaction/BdsSkipLink.mdx +72 -16
  34. package/src/web-components/interaction/BdsSkipLink.stories.tsx +47 -34
  35. package/src/web-components/interaction/BdsTabs.mdx +97 -27
  36. package/src/web-components/interaction/BdsTabs.stories.tsx +69 -55
  37. package/src/web-components/interaction/BdsTooltip.mdx +84 -18
  38. package/src/web-components/interaction/BdsTooltip.stories.tsx +49 -30
  39. package/src/web-components/interaction/bds-collapsible.ts +1 -0
  40. package/src/web-components/interaction/bds-drawer.ts +59 -82
  41. package/src/web-components/interaction/bds-dropdown-menu-item.ts +124 -0
  42. package/src/web-components/interaction/bds-dropdown-menu.spec.ts +102 -0
  43. package/src/web-components/interaction/bds-dropdown-menu.ts +200 -0
  44. package/src/web-components/interaction/form/BdsCheckbox.mdx +57 -20
  45. package/src/web-components/interaction/form/BdsCheckbox.stories.tsx +35 -36
  46. package/src/web-components/interaction/form/BdsCheckboxGroup.mdx +70 -0
  47. package/src/web-components/interaction/form/BdsCheckboxGroup.stories.tsx +81 -0
  48. package/src/web-components/interaction/form/BdsCombobox.mdx +52 -33
  49. package/src/web-components/interaction/form/BdsCombobox.stories.tsx +55 -53
  50. package/src/web-components/interaction/form/BdsFileInput.mdx +59 -24
  51. package/src/web-components/interaction/form/BdsFileInput.stories.tsx +38 -53
  52. package/src/web-components/interaction/form/BdsFormInput.mdx +98 -0
  53. package/src/web-components/interaction/form/BdsFormInput.stories.tsx +139 -0
  54. package/src/web-components/interaction/form/BdsNumberInput.mdx +51 -22
  55. package/src/web-components/interaction/form/BdsNumberInput.stories.tsx +24 -46
  56. package/src/web-components/interaction/form/BdsRadio.mdx +53 -22
  57. package/src/web-components/interaction/form/BdsRadio.stories.tsx +19 -51
  58. package/src/web-components/interaction/form/BdsRadioGroup.mdx +73 -0
  59. package/src/web-components/interaction/form/BdsRadioGroup.stories.tsx +88 -0
  60. package/src/web-components/interaction/form/BdsSegmentedControl.mdx +76 -23
  61. package/src/web-components/interaction/form/BdsSegmentedControl.stories.tsx +64 -54
  62. package/src/web-components/interaction/form/BdsSelect.mdx +59 -21
  63. package/src/web-components/interaction/form/BdsSelect.stories.tsx +47 -56
  64. package/src/web-components/interaction/form/BdsSlider.mdx +55 -27
  65. package/src/web-components/interaction/form/BdsSlider.stories.tsx +23 -44
  66. package/src/web-components/interaction/form/BdsSwitch.mdx +53 -20
  67. package/src/web-components/interaction/form/BdsSwitch.stories.tsx +22 -37
  68. package/src/web-components/interaction/form/BdsTextarea.mdx +54 -22
  69. package/src/web-components/interaction/form/BdsTextarea.stories.tsx +35 -44
  70. package/src/web-components/interaction/form/bds-checkbox-group.spec.ts +55 -0
  71. package/src/web-components/interaction/form/bds-checkbox-group.ts +117 -0
  72. package/src/web-components/interaction/form/bds-form-input.spec.ts +83 -0
  73. package/src/web-components/interaction/form/bds-form-input.ts +268 -0
  74. package/src/web-components/interaction/form/bds-radio-group.spec.ts +62 -0
  75. package/src/web-components/interaction/form/bds-radio-group.ts +142 -0
  76. package/src/web-components/interaction/form/bds-segmented-control.ts +5 -0
  77. package/src/web-components/ui/BdsAvatar.mdx +29 -20
  78. package/src/web-components/ui/BdsAvatar.stories.tsx +14 -28
  79. package/src/web-components/ui/BdsBreadcrumb.mdx +22 -19
  80. package/src/web-components/ui/BdsBreadcrumb.stories.tsx +11 -21
  81. package/src/web-components/ui/BdsButtonGroup.mdx +69 -0
  82. package/src/web-components/ui/BdsButtonGroup.stories.tsx +66 -0
  83. package/src/web-components/ui/BdsCalendar.mdx +93 -0
  84. package/src/web-components/ui/BdsCalendar.stories.tsx +63 -0
  85. package/src/web-components/ui/BdsCard.mdx +30 -25
  86. package/src/web-components/ui/BdsCard.stories.tsx +19 -42
  87. package/src/web-components/ui/BdsCarousel.mdx +83 -0
  88. package/src/web-components/ui/BdsCarousel.stories.tsx +96 -0
  89. package/src/web-components/ui/BdsDescriptionList.mdx +13 -16
  90. package/src/web-components/ui/BdsDescriptionList.stories.tsx +34 -49
  91. package/src/web-components/ui/BdsIconWrapper.mdx +20 -20
  92. package/src/web-components/ui/BdsIconWrapper.stories.tsx +46 -41
  93. package/src/web-components/ui/BdsLink.mdx +21 -17
  94. package/src/web-components/ui/BdsLink.stories.tsx +19 -20
  95. package/src/web-components/ui/BdsLoading.mdx +9 -13
  96. package/src/web-components/ui/BdsLoading.stories.tsx +8 -10
  97. package/src/web-components/ui/BdsNotificationBanner.mdx +32 -37
  98. package/src/web-components/ui/BdsNotificationBanner.stories.tsx +38 -47
  99. package/src/web-components/ui/BdsPagination.mdx +74 -0
  100. package/src/web-components/ui/BdsPagination.stories.tsx +36 -0
  101. package/src/web-components/ui/BdsProgress.mdx +24 -17
  102. package/src/web-components/ui/BdsProgress.stories.tsx +55 -29
  103. package/src/web-components/ui/BdsProgressCircle.mdx +24 -18
  104. package/src/web-components/ui/BdsProgressCircle.stories.tsx +17 -29
  105. package/src/web-components/ui/BdsRating.mdx +22 -22
  106. package/src/web-components/ui/BdsRating.stories.tsx +19 -13
  107. package/src/web-components/ui/BdsSectionHeader.mdx +31 -28
  108. package/src/web-components/ui/BdsSectionHeader.stories.tsx +21 -23
  109. package/src/web-components/ui/BdsSeparator.mdx +22 -8
  110. package/src/web-components/ui/BdsSeparator.stories.tsx +27 -19
  111. package/src/web-components/ui/BdsSkeleton.mdx +20 -26
  112. package/src/web-components/ui/BdsSkeleton.stories.tsx +23 -23
  113. package/src/web-components/ui/BdsTable.mdx +81 -0
  114. package/src/web-components/ui/BdsTable.stories.tsx +83 -0
  115. package/src/web-components/ui/BdsTypography.mdx +20 -29
  116. package/src/web-components/ui/BdsTypography.stories.tsx +19 -18
  117. package/src/web-components/ui/bds-button-group.spec.ts +40 -0
  118. package/src/web-components/ui/bds-button-group.ts +78 -0
  119. package/src/web-components/ui/bds-calendar.spec.ts +91 -0
  120. package/src/web-components/ui/bds-calendar.ts +427 -0
  121. package/src/web-components/ui/bds-carousel.spec.ts +64 -0
  122. package/src/web-components/ui/bds-carousel.ts +296 -0
  123. package/src/web-components/ui/bds-pagination.spec.ts +67 -0
  124. package/src/web-components/ui/bds-pagination.ts +197 -0
  125. package/src/web-components/ui/bds-table.spec.ts +45 -0
  126. package/src/web-components/ui/bds-table.ts +96 -0
@@ -1,16 +1,18 @@
1
1
  import React from 'react';
2
2
  import type { Meta, StoryObj } from '@storybook/react';
3
3
  import type { LinkVariant } from './bds-link';
4
- import '../index';
4
+ import '../index'; // auto-registers all custom elements
5
5
 
6
6
  function BdsLink({
7
- href,
8
- variant,
7
+ href = '#',
8
+ target,
9
+ variant = 'default',
9
10
  external,
10
11
  externalLabel,
11
12
  children,
12
13
  }: {
13
14
  href?: string;
15
+ target?: string;
14
16
  variant?: LinkVariant;
15
17
  external?: boolean;
16
18
  externalLabel?: string;
@@ -19,7 +21,8 @@ function BdsLink({
19
21
  return React.createElement(
20
22
  'bds-link',
21
23
  {
22
- href: href ?? '#',
24
+ href,
25
+ target,
23
26
  variant,
24
27
  external: external || undefined,
25
28
  'external-label': externalLabel,
@@ -34,31 +37,27 @@ const meta = {
34
37
  tags: ['!stable', 'experimental'],
35
38
  parameters: { layout: 'centered' },
36
39
  argTypes: {
37
- variant: { control: 'select', options: ['default', 'subtle', 'standalone'] },
40
+ variant: { control: 'select', options: ['default', 'subtle', 'standalone'] },
41
+ external: { control: 'boolean' },
38
42
  },
39
43
  } satisfies Meta<typeof BdsLink>;
40
44
 
41
45
  export default meta;
42
46
  type Story = StoryObj<typeof meta>;
43
47
 
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
+ export const Default: Story = { args: { children: 'Default link', variant: 'default', href: '#' } };
49
+ export const Subtle: Story = { args: { children: 'Subtle link', variant: 'subtle', href: '#' } };
50
+ export const Standalone: Story = { args: { children: 'Standalone link', variant: 'standalone', href: '#' } };
51
+ export const External: Story = {
52
+ args: { children: 'Visit our website', href: 'https://example.com', external: true },
53
+ };
48
54
 
49
55
  export const AllVariants: Story = {
50
56
  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>
57
+ <div style={{ display: 'flex', gap: 16, flexWrap: 'wrap', alignItems: 'center' }}>
58
+ {React.createElement('bds-link', { href: '#', variant: 'default' }, 'Default')}
59
+ {React.createElement('bds-link', { href: '#', variant: 'subtle' }, 'Subtle')}
60
+ {React.createElement('bds-link', { href: '#', variant: 'standalone' }, 'Standalone')}
62
61
  </div>
63
62
  ),
64
63
  };
@@ -5,7 +5,7 @@ import * as Stories from './BdsLoading.stories';
5
5
 
6
6
  # &lt;bds-loading&gt;
7
7
 
8
- Framework-agnostic Loading spinner custom element. Use to indicate an ongoing asynchronous operation.
8
+ Framework-agnostic Loading spinner custom element. Displays an animated circular spinner to indicate that a process is in progress.
9
9
 
10
10
  > **Status: experimental** — API may change before stable release.
11
11
 
@@ -15,10 +15,15 @@ Framework-agnostic Loading spinner custom element. Use to indicate an ongoing as
15
15
  import '@boostdev/components/web-components';
16
16
  ```
17
17
 
18
+ ## When to use
19
+
20
+ - While a page section or full page is loading content
21
+ - As inline feedback during form submission or data fetching
22
+
18
23
  ## Examples
19
24
 
20
25
  ### All sizes
21
- <Canvas of={Stories.AllVariants} />
26
+ <Canvas of={Stories.AllSizes} />
22
27
 
23
28
  ### Small
24
29
  <Canvas of={Stories.Small} />
@@ -39,15 +44,6 @@ import '@boostdev/components/web-components';
39
44
  |-----------|------|---------|-------------|
40
45
  | `size` | `"small" \| "medium" \| "large"` | `"medium"` | Spinner diameter |
41
46
 
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
47
  ## Usage in plain HTML
52
48
 
53
49
  ```html
@@ -58,5 +54,5 @@ The spinner uses design tokens directly:
58
54
 
59
55
  ## Accessibility
60
56
 
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
57
+ - Renders `role="status"` with `aria-label="Loading"` so screen readers announce the loading state
58
+ - The spin animation is suppressed when `prefers-reduced-motion: reduce` is set
@@ -1,8 +1,8 @@
1
1
  import React from 'react';
2
2
  import type { Meta, StoryObj } from '@storybook/react';
3
- import '../index';
3
+ import '../index'; // auto-registers all custom elements
4
4
 
5
- function BdsLoading({ size }: { size?: 'small' | 'medium' | 'large' }) {
5
+ function BdsLoading({ size = 'medium' }: { size?: 'small' | 'medium' | 'large' }) {
6
6
  return React.createElement('bds-loading', { size });
7
7
  }
8
8
 
@@ -19,19 +19,17 @@ const meta = {
19
19
  export default meta;
20
20
  type Story = StoryObj<typeof meta>;
21
21
 
22
+ export const Default: Story = { args: { size: 'medium' } };
22
23
  export const Small: Story = { args: { size: 'small' } };
23
24
  export const Medium: Story = { args: { size: 'medium' } };
24
25
  export const Large: Story = { args: { size: 'large' } };
25
26
 
26
- export const AllVariants: Story = {
27
+ export const AllSizes: Story = {
27
28
  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
- ))}
29
+ <div style={{ display: 'flex', gap: 24, alignItems: 'center' }}>
30
+ {React.createElement('bds-loading', { size: 'small' })}
31
+ {React.createElement('bds-loading', { size: 'medium' })}
32
+ {React.createElement('bds-loading', { size: 'large' })}
35
33
  </div>
36
34
  ),
37
35
  };
@@ -5,7 +5,7 @@ import * as Stories from './BdsNotificationBanner.stories';
5
5
 
6
6
  # &lt;bds-notification-banner&gt;
7
7
 
8
- Framework-agnostic full-width Notification Banner. Use for page-level messages that require user attention system notices, maintenance windows, or status updates.
8
+ Framework-agnostic Notification Banner custom element. Renders a full-width status banner at the top of a page or section with optional dismiss button and action slot.
9
9
 
10
10
  > **Status: experimental** — API may change before stable release.
11
11
 
@@ -15,13 +15,31 @@ Framework-agnostic full-width Notification Banner. Use for page-level messages t
15
15
  import '@boostdev/components/web-components';
16
16
  ```
17
17
 
18
+ ## When to use
19
+
20
+ - To surface page-level status messages (success after save, system errors, maintenance warnings)
21
+ - Use `dismissible` when the user should be able to close the banner manually
22
+ - Place an action element in the `action` slot for in-line links or undo buttons
23
+
18
24
  ## Examples
19
25
 
20
26
  ### All variants
21
27
  <Canvas of={Stories.AllVariants} />
22
28
 
29
+ ### Default (info)
30
+ <Canvas of={Stories.Default} />
31
+
32
+ ### Success
33
+ <Canvas of={Stories.Success} />
34
+
35
+ ### Warning
36
+ <Canvas of={Stories.Warning} />
37
+
38
+ ### Error
39
+ <Canvas of={Stories.Error} />
40
+
23
41
  ### Dismissible
24
- <Canvas of={Stories.Interactive} />
42
+ <Canvas of={Stories.Dismissible} />
25
43
 
26
44
  ### With action
27
45
  <Canvas of={Stories.WithAction} />
@@ -34,57 +52,34 @@ import '@boostdev/components/web-components';
34
52
 
35
53
  | Attribute | Type | Default | Description |
36
54
  |-----------|------|---------|-------------|
37
- | `variant` | `"info" \| "success" \| "warning" \| "error"` | `"info"` | Semantic colour and urgency |
55
+ | `variant` | `"info" \| "success" \| "warning" \| "error"` | `"info"` | Visual style and semantic urgency |
38
56
  | `dismissible` | boolean | `false` | Shows a dismiss (×) button |
39
- | `dismiss-label` | string | `"Dismiss notification"` | Accessible label for the dismiss button |
57
+ | `dismiss-label` | string | `"Dismiss notification"` | `aria-label` for the dismiss button |
40
58
 
41
59
  ## Slots
42
60
 
43
61
  | Slot | Description |
44
62
  |------|-------------|
45
- | `(default)` | Banner body content |
46
- | `action` | Optional action area (e.g. a button or link) |
63
+ | `(default)` | Banner body text or HTML |
64
+ | `action` | Optional action area (e.g. a `<button>` or `<a>`) |
47
65
 
48
66
  ## Events
49
67
 
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 |
68
+ | Event | Detail | Description |
69
+ |-------|--------|-------------|
70
+ | `bds-dismiss` | — | Fired when the dismiss button is clicked |
61
71
 
62
72
  ## Usage in plain HTML
63
73
 
64
74
  ```html
65
- <bds-notification-banner variant="success">
75
+ <bds-notification-banner variant="success" dismissible>
66
76
  Your changes have been saved.
77
+ <button slot="action" type="button">Undo</button>
67
78
  </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
79
  ```
85
80
 
86
81
  ## Accessibility
87
82
 
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
83
+ - `error` and `warning` variants render `role="alert"` with `aria-live="assertive"`
84
+ - `info` and `success` variants render `role="status"` with `aria-live="polite"`
85
+ - The dismiss button has a configurable `aria-label` via `dismiss-label`
@@ -1,22 +1,20 @@
1
1
  import React from 'react';
2
2
  import type { Meta, StoryObj } from '@storybook/react';
3
3
  import type { NotificationBannerVariant } from './bds-notification-banner';
4
- import '../index';
4
+ import '../index'; // auto-registers all custom elements
5
5
 
6
6
  function BdsNotificationBanner({
7
7
  variant = 'info',
8
8
  dismissible,
9
9
  dismissLabel,
10
- onDismiss,
11
- action,
12
10
  children,
11
+ action,
13
12
  }: {
14
13
  variant?: NotificationBannerVariant;
15
14
  dismissible?: boolean;
16
15
  dismissLabel?: string;
17
- onDismiss?: () => void;
18
- action?: React.ReactNode;
19
16
  children?: React.ReactNode;
17
+ action?: React.ReactNode;
20
18
  }) {
21
19
  return React.createElement(
22
20
  'bds-notification-banner',
@@ -24,10 +22,11 @@ function BdsNotificationBanner({
24
22
  variant,
25
23
  dismissible: dismissible || undefined,
26
24
  'dismiss-label': dismissLabel,
27
- onbdsdismiss: onDismiss,
28
25
  },
29
26
  children,
30
- action ? React.createElement('span', { slot: 'action' }, action) : null,
27
+ action
28
+ ? React.createElement('span', { slot: 'action' }, action)
29
+ : undefined,
31
30
  );
32
31
  }
33
32
 
@@ -35,59 +34,51 @@ const meta = {
35
34
  title: 'Web Components/UI/NotificationBanner',
36
35
  component: BdsNotificationBanner,
37
36
  tags: ['!stable', 'experimental'],
38
- parameters: { layout: 'padded' },
37
+ parameters: { layout: 'fullscreen' },
39
38
  argTypes: {
40
39
  variant: { control: 'select', options: ['info', 'success', 'warning', 'error'] },
40
+ dismissible: { control: 'boolean' },
41
41
  },
42
42
  } satisfies Meta<typeof BdsNotificationBanner>;
43
43
 
44
44
  export default meta;
45
45
  type Story = StoryObj<typeof meta>;
46
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 } };
47
+ export const Default: Story = {
48
+ args: { children: 'This is an informational banner.', variant: 'info' },
49
+ };
50
+ export const Success: Story = {
51
+ args: { children: 'Your changes have been saved successfully.', variant: 'success' },
52
+ };
53
+ export const Warning: Story = {
54
+ args: { children: 'Please review your settings before continuing.', variant: 'warning' },
55
+ };
56
+ export const Error: Story = {
57
+ args: { children: 'An error occurred. Please try again.', variant: 'error' },
58
+ };
59
+ export const Dismissible: Story = {
60
+ args: { children: 'You can dismiss this banner.', variant: 'info', dismissible: true },
61
+ };
52
62
  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
- ),
63
+ render: () =>
64
+ React.createElement(
65
+ 'bds-notification-banner',
66
+ { variant: 'success' },
67
+ 'Your file has been uploaded.',
68
+ React.createElement('button', { slot: 'action', type: 'button' }, 'Undo'),
69
+ ),
61
70
  };
62
71
 
63
72
  export const AllVariants: Story = {
64
73
  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
- ))}
74
+ <div style={{ display: 'flex', flexDirection: 'column', gap: 0 }}>
75
+ {(['info', 'success', 'warning', 'error'] as const).map(v =>
76
+ React.createElement(
77
+ 'bds-notification-banner',
78
+ { key: v, variant: v },
79
+ `This is a ${v} notification banner.`,
80
+ ),
81
+ )}
71
82
  </div>
72
83
  ),
73
84
  };
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,74 @@
1
+ import { Meta, Canvas, ArgTypes } from '@storybook/blocks';
2
+ import * as Stories from './BdsPagination.stories';
3
+
4
+ <Meta of={Stories} />
5
+
6
+ # &lt;bds-pagination&gt;
7
+
8
+ Framework-agnostic Pagination navigation custom element. Renders previous/next buttons and a page number list with smart ellipsis truncation.
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
+ ## When to use
19
+
20
+ - Below paginated lists or tables to let users navigate between pages
21
+ - Listen to `bds-page-change` to update your data layer when the page changes
22
+
23
+ ## Examples
24
+
25
+ ### Default (page 3 of 10)
26
+ <Canvas of={Stories.Default} />
27
+
28
+ ### First page
29
+ <Canvas of={Stories.FirstPage} />
30
+
31
+ ### Last page
32
+ <Canvas of={Stories.LastPage} />
33
+
34
+ ### Few pages
35
+ <Canvas of={Stories.FewPages} />
36
+
37
+ ### Many pages (with ellipsis)
38
+ <Canvas of={Stories.ManyPages} />
39
+
40
+ ## Props
41
+
42
+ <ArgTypes of={Stories} />
43
+
44
+ ## Attributes
45
+
46
+ | Attribute | Type | Default | Description |
47
+ |-----------|------|---------|-------------|
48
+ | `current-page` | number | `1` | Active page number (1-based) |
49
+ | `total-pages` | number | `1` | Total number of pages |
50
+
51
+ ## Events
52
+
53
+ | Event | Detail | Description |
54
+ |-------|--------|-------------|
55
+ | `bds-page-change` | `{ page: number }` | Fired when the user navigates to a different page |
56
+
57
+ ## Usage in plain HTML
58
+
59
+ ```html
60
+ <bds-pagination current-page="3" total-pages="10"></bds-pagination>
61
+
62
+ <script>
63
+ document.querySelector('bds-pagination')
64
+ .addEventListener('bds-page-change', e => {
65
+ console.log('Navigate to page', e.detail.page);
66
+ });
67
+ </script>
68
+ ```
69
+
70
+ ## Accessibility
71
+
72
+ - Wrapped in `<nav aria-label="Pagination">` with an `<ul>` list structure
73
+ - Active page button carries `aria-current="page"`
74
+ - Previous/Next buttons have descriptive `aria-label` values and are `disabled` at the boundaries
@@ -0,0 +1,36 @@
1
+ import React from 'react';
2
+ import type { Meta, StoryObj } from '@storybook/react';
3
+ import '../index'; // auto-registers all custom elements
4
+
5
+ function BdsPagination({
6
+ currentPage = 1,
7
+ totalPages = 1,
8
+ }: {
9
+ currentPage?: number;
10
+ totalPages?: number;
11
+ }) {
12
+ return React.createElement('bds-pagination', {
13
+ 'current-page': currentPage,
14
+ 'total-pages': totalPages,
15
+ });
16
+ }
17
+
18
+ const meta = {
19
+ title: 'Web Components/UI/Pagination',
20
+ component: BdsPagination,
21
+ tags: ['!stable', 'experimental'],
22
+ parameters: { layout: 'centered' },
23
+ argTypes: {
24
+ currentPage: { control: { type: 'number', min: 1 } },
25
+ totalPages: { control: { type: 'number', min: 1 } },
26
+ },
27
+ } satisfies Meta<typeof BdsPagination>;
28
+
29
+ export default meta;
30
+ type Story = StoryObj<typeof meta>;
31
+
32
+ export const Default: Story = { args: { currentPage: 3, totalPages: 10 } };
33
+ export const FirstPage: Story = { args: { currentPage: 1, totalPages: 10 } };
34
+ export const LastPage: Story = { args: { currentPage: 10, totalPages: 10 } };
35
+ export const FewPages: Story = { args: { currentPage: 2, totalPages: 4 } };
36
+ export const ManyPages: Story = { args: { currentPage: 7, totalPages: 20 } };
@@ -5,7 +5,7 @@ import * as Stories from './BdsProgress.stories';
5
5
 
6
6
  # &lt;bds-progress&gt;
7
7
 
8
- Framework-agnostic linear Progress bar custom element. Use to show completion status of a task or upload.
8
+ Framework-agnostic horizontal Progress bar custom element. Tracks progress toward a goal with optional label and percentage display.
9
9
 
10
10
  > **Status: experimental** — API may change before stable release.
11
11
 
@@ -15,16 +15,27 @@ Framework-agnostic linear Progress bar custom element. Use to show completion st
15
15
  import '@boostdev/components/web-components';
16
16
  ```
17
17
 
18
+ ## When to use
19
+
20
+ - File uploads, multi-step forms, or any linear task with a measurable completion percentage
21
+ - Add `show-label` to make progress visible without screen-reader-only text
22
+
18
23
  ## Examples
19
24
 
20
- ### All values
21
- <Canvas of={Stories.AllVariants} />
25
+ ### All sizes
26
+ <Canvas of={Stories.AllSizes} />
27
+
28
+ ### Default
29
+ <Canvas of={Stories.Default} />
22
30
 
23
31
  ### With label
24
32
  <Canvas of={Stories.WithLabel} />
25
33
 
26
- ### Animated
27
- <Canvas of={Stories.Interactive} />
34
+ ### Small
35
+ <Canvas of={Stories.Small} />
36
+
37
+ ### Large
38
+ <Canvas of={Stories.Large} />
28
39
 
29
40
  ## Props
30
41
 
@@ -36,28 +47,24 @@ import '@boostdev/components/web-components';
36
47
  |-----------|------|---------|-------------|
37
48
  | `value` | number | `0` | Current progress value |
38
49
  | `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 |
50
+ | `label` | string | — | Accessible label; also shown above the bar when `show-label` is set |
51
+ | `show-label` | boolean | `false` | Displays label text and percentage above the bar |
52
+ | `size` | `"small" \| "medium" \| "large"` | `"medium"` | Track height |
42
53
 
43
54
  ## CSS Custom Properties
44
55
 
45
56
  | Property | Description |
46
57
  |----------|-------------|
47
- | `--progress_color-active` | Fill colour (defaults to `--bdc-color_active`) |
58
+ | `--progress_color-active` | Fill colour of the progress bar |
48
59
 
49
60
  ## Usage in plain HTML
50
61
 
51
62
  ```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>
63
+ <bds-progress value="60" label="Upload progress" show-label></bds-progress>
64
+ <bds-progress value="30" size="small" label="Loading"></bds-progress>
57
65
  ```
58
66
 
59
67
  ## Accessibility
60
68
 
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`
69
+ - Renders with `role="progressbar"`, `aria-valuenow`, `aria-valuemin`, and `aria-valuemax`
70
+ - Always provide a `label` to give the bar a meaningful accessible name