@boostdev/design-system-components 1.2.5 → 1.2.6

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 (64) hide show
  1. package/AGENTS.md +25 -6
  2. package/dist/client.cjs +57 -52
  3. package/dist/client.css +546 -536
  4. package/dist/client.d.cts +1 -1
  5. package/dist/client.d.ts +1 -1
  6. package/dist/client.js +57 -52
  7. package/dist/index.cjs +57 -52
  8. package/dist/index.css +546 -536
  9. package/dist/index.d.cts +1 -1
  10. package/dist/index.d.ts +1 -1
  11. package/dist/index.js +57 -52
  12. package/package.json +1 -1
  13. package/src/components/interaction/Button/Button.mdx +11 -3
  14. package/src/components/interaction/Button/Button.module.css +5 -5
  15. package/src/components/interaction/Command/Command.mdx +1 -0
  16. package/src/components/interaction/Command/Command.module.css +1 -1
  17. package/src/components/interaction/Drawer/Drawer.mdx +2 -0
  18. package/src/components/interaction/Drawer/Drawer.module.css +1 -1
  19. package/src/components/interaction/DropdownMenu/DropdownMenu.mdx +19 -0
  20. package/src/components/interaction/DropdownMenu/DropdownMenu.module.css +2 -2
  21. package/src/components/interaction/Rating/Rating.mdx +14 -0
  22. package/src/components/interaction/Rating/Rating.module.css +2 -2
  23. package/src/components/interaction/Toast/Toast.mdx +12 -4
  24. package/src/components/interaction/Toast/Toast.spec.tsx +11 -0
  25. package/src/components/interaction/Toast/Toast.tsx +11 -4
  26. package/src/components/interaction/form/Combobox/Combobox.mdx +2 -0
  27. package/src/components/interaction/form/Combobox/Combobox.module.css +3 -3
  28. package/src/components/interaction/form/FileInput/FileInput.mdx +2 -0
  29. package/src/components/interaction/form/FileInput/FileInput.module.css +2 -2
  30. package/src/components/interaction/form/NumberInput/NumberInput.mdx +4 -0
  31. package/src/components/interaction/form/NumberInput/NumberInput.module.css +3 -3
  32. package/src/components/interaction/form/SegmentedControl/SegmentedControl.mdx +1 -0
  33. package/src/components/interaction/form/SegmentedControl/SegmentedControl.module.css +1 -1
  34. package/src/components/interaction/form/Slider/Slider.mdx +4 -0
  35. package/src/components/interaction/form/Slider/Slider.module.css +8 -8
  36. package/src/components/interaction/form/Switch/Switch.mdx +3 -0
  37. package/src/components/interaction/form/Switch/Switch.module.css +1 -1
  38. package/src/components/interaction/form/Textarea/Textarea.mdx +1 -1
  39. package/src/components/interaction/form/Textarea/Textarea.module.css +1 -1
  40. package/src/components/layout/ButtonGroup/ButtonGroup.mdx +2 -0
  41. package/src/components/layout/Card/Card.mdx +8 -5
  42. package/src/components/layout/Card/Card.module.css +4 -4
  43. package/src/components/layout/SectionHeader/SectionHeader.mdx +10 -2
  44. package/src/components/layout/SectionHeader/SectionHeader.module.css +29 -17
  45. package/src/components/layout/SectionHeader/SectionHeader.spec.tsx +5 -0
  46. package/src/components/layout/SectionHeader/SectionHeader.stories.tsx +2 -1
  47. package/src/components/layout/SectionHeader/SectionHeader.tsx +1 -1
  48. package/src/components/ui/Accordion/Accordion.mdx +1 -0
  49. package/src/components/ui/Accordion/Accordion.module.css +1 -1
  50. package/src/components/ui/Alert/Alert.mdx +6 -3
  51. package/src/components/ui/Alert/Alert.module.css +1 -1
  52. package/src/components/ui/Calendar/Calendar.mdx +5 -0
  53. package/src/components/ui/Calendar/Calendar.module.css +5 -5
  54. package/src/components/ui/Carousel/Carousel.mdx +14 -0
  55. package/src/components/ui/Carousel/Carousel.module.css +1 -1
  56. package/src/components/ui/NotificationBanner/NotificationBanner.mdx +18 -0
  57. package/src/components/ui/NotificationBanner/NotificationBanner.module.css +1 -1
  58. package/src/components/ui/Pagination/Pagination.mdx +21 -0
  59. package/src/components/ui/Pagination/Pagination.module.css +5 -5
  60. package/src/components/ui/Table/Table.mdx +2 -0
  61. package/src/components/ui/Table/Table.module.css +2 -2
  62. package/src/components/ui/Tabs/Tabs.mdx +17 -0
  63. package/src/components/ui/Tabs/Tabs.module.css +3 -3
  64. package/src/css/bdc.css +1 -0
@@ -38,6 +38,8 @@ Slide-in panel from the left or right edge of the viewport. Use for navigation,
38
38
  <tbody>
39
39
  <tr><td>`--drawer_color`</td><td>`var(--bds-color_bg)`</td><td>Panel background colour</td></tr>
40
40
  <tr><td>`--drawer_on-color`</td><td>`var(--bds-color_on-bg)`</td><td>Text colour</td></tr>
41
+ <tr><td>`--drawer_close-radius`</td><td>`var(--bds-border_radius--circle)`</td><td>Close button border radius</td></tr>
42
+ <tr><td>`--drawer_close-bg--hover`</td><td>`var(--bds-color_bg--subtle)`</td><td>Close button background on hover</td></tr>
41
43
  </tbody>
42
44
  </table>
43
45
 
@@ -95,7 +95,7 @@
95
95
 
96
96
  @media (hover: hover) and (pointer: fine) {
97
97
  .closeButton:hover {
98
- background-color: var(--bds-color_bg--subtle);
98
+ background-color: var(--drawer_close-bg--hover, var(--bds-color_bg--subtle));
99
99
  }
100
100
  }
101
101
 
@@ -33,6 +33,25 @@ Floating menu with a list of selectable actions, triggered by a button. Supports
33
33
 
34
34
  <ArgTypes of={Stories} />
35
35
 
36
+ ## CSS variables
37
+
38
+
39
+ <table>
40
+ <thead>
41
+ <tr><th>Variable</th><th>Default</th><th>Description</th></tr>
42
+ </thead>
43
+ <tbody>
44
+ <tr><td>`--dropdown_border`</td><td>`none`</td><td>Menu container border</td></tr>
45
+ <tr><td>`--dropdown_radius`</td><td>`var(--bdc-outline_radius)`</td><td>Menu container corner radius</td></tr>
46
+ <tr><td>`--dropdown_color`</td><td>`var(--bds-color_bg)`</td><td>Menu background colour</td></tr>
47
+ <tr><td>`--dropdown_on-color`</td><td>`var(--bds-color_on-bg)`</td><td>Menu text colour</td></tr>
48
+ <tr><td>`--dropdown_shadow`</td><td>`var(--bds-shadow_m)`</td><td>Menu box shadow</td></tr>
49
+ <tr><td>`--dropdown_item-bg--hover`</td><td>`var(--bds-color_bg--subtle)`</td><td>Menu item background on hover</td></tr>
50
+ <tr><td>`--dropdown_item-color--hover`</td><td>`var(--bds-color_interactive_on-bg)`</td><td>Menu item text colour on hover</td></tr>
51
+ </tbody>
52
+ </table>
53
+
54
+
36
55
  ## Accessibility
37
56
 
38
57
  - Implements ARIA menu pattern: `role="menu"`, `role="menuitem"`
@@ -64,8 +64,8 @@
64
64
 
65
65
  @media (hover: hover) and (pointer: fine) {
66
66
  .item:not(:disabled):hover {
67
- background-color: var(--bds-color_bg--subtle);
68
- color: var(--bds-color_interactive_on-bg);
67
+ background-color: var(--dropdown_item-bg--hover, var(--bds-color_bg--subtle));
68
+ color: var(--dropdown_item-color--hover, var(--bds-color_interactive_on-bg));
69
69
  }
70
70
  }
71
71
 
@@ -32,6 +32,20 @@ Read-only star rating display. Use to show an existing score; for user input, co
32
32
 
33
33
  <ArgTypes of={Stories} />
34
34
 
35
+ ## CSS variables
36
+
37
+
38
+ <table>
39
+ <thead>
40
+ <tr><th>Variable</th><th>Default</th><th>Description</th></tr>
41
+ </thead>
42
+ <tbody>
43
+ <tr><td>`--rating_color`</td><td>`var(--bds-color_bg)`</td><td>Empty star colour</td></tr>
44
+ <tr><td>`--rating_color--filled`</td><td>`var(--bds-color_warning)`</td><td>Filled star colour</td></tr>
45
+ </tbody>
46
+ </table>
47
+
48
+
35
49
  ## Accessibility
36
50
 
37
51
  - Renders as a `<span>` with `role="img"` and `aria-label="X out of Y stars"`
@@ -2,7 +2,7 @@
2
2
  .rating {
3
3
  display: inline-flex;
4
4
  gap: var(--bds-space_xxxs);
5
- color: var(--bds-color_bg);
5
+ color: var(--rating_color, var(--bds-color_bg));
6
6
  }
7
7
 
8
8
  .star {
@@ -11,6 +11,6 @@
11
11
  }
12
12
 
13
13
  .--filled {
14
- color: var(--bds-color_warning);
14
+ color: var(--rating_color--filled, var(--bds-color_warning));
15
15
  }
16
16
  }
@@ -17,20 +17,26 @@ Transient feedback notification that auto-dismisses after 5 seconds. Provided vi
17
17
 
18
18
  ## Setup
19
19
 
20
- Wrap your app (or layout root) once with `ToastProvider`:
20
+ Wrap your app (or layout root) once with `ToastProvider`. Since Toast uses React hooks, it requires a client boundary in Next.js:
21
21
 
22
22
  ```tsx
23
- import { ToastProvider } from '@boostdev/components';
23
+ // Next.js App Router use the /client entry inside a 'use client' boundary:
24
+ import { ToastProvider } from '@boostdev/design-system-components/client';
24
25
 
26
+ // Non-Next.js / bundler apps:
27
+ import { ToastProvider } from '@boostdev/design-system-components';
28
+ ```
29
+
30
+ ```tsx
25
31
  <ToastProvider>
26
32
  <App />
27
33
  </ToastProvider>
28
34
  ```
29
35
 
30
- Then call `showToast` anywhere inside:
36
+ Then call `showToast` anywhere inside a client component:
31
37
 
32
38
  ```tsx
33
- import { useToast } from '@boostdev/components';
39
+ import { useToast } from '@boostdev/design-system-components/client';
34
40
 
35
41
  const { showToast } = useToast();
36
42
 
@@ -39,6 +45,8 @@ showToast('Something went wrong', 'error');
39
45
  showToast('New message received', 'info');
40
46
  ```
41
47
 
48
+ > **Next.js RSC note:** The root entry (`@boostdev/design-system-components`) is safe to import in Server Components for server-safe components like `Typography` or `Badge`. Toast itself is client-only and must be used inside a `'use client'` boundary.
49
+
42
50
  ## Examples
43
51
 
44
52
  ### Success
@@ -59,4 +59,15 @@ describe('Toast', () => {
59
59
  expect(() => render(<Bad />)).toThrow('useToast must be used within a ToastProvider');
60
60
  errorSpy.mockRestore();
61
61
  });
62
+
63
+ it('shares a single lazy-initialised context between provider and consumer (RSC-safe)', () => {
64
+ // The lazy getToastContext() pattern defers createContext() until first render
65
+ // so the module can be safely evaluated in Next.js Server Components.
66
+ // This test verifies provider and consumer share the same context instance.
67
+ let captured: ReturnType<typeof useToast> | undefined;
68
+ const Capture = () => { captured = useToast(); return null; };
69
+ render(<ToastProvider><Capture /></ToastProvider>);
70
+ expect(captured).toBeDefined();
71
+ expect(typeof captured!.showToast).toBe('function');
72
+ });
62
73
  });
@@ -1,4 +1,4 @@
1
- import { useState, useEffect, createContext, useContext, ReactNode, useCallback, useMemo, useRef } from 'react';
1
+ import { useState, useEffect, createContext, useContext, ReactNode, useCallback, useMemo, useRef, Context } from 'react';
2
2
  import css from './Toast.module.css';
3
3
  import { cn } from '@boostdev/design-system-foundation';
4
4
 
@@ -14,9 +14,16 @@ interface ToastContextType {
14
14
  showToast: (message: string, variant: ToastVariant) => void;
15
15
  }
16
16
 
17
- const ToastContext = createContext<ToastContextType | undefined>(undefined);
17
+ // Lazy-initialised so the module can be evaluated in Next.js Server Components
18
+ // without calling `createContext` at import time (which crashes RSC).
19
+ let _ToastContext: Context<ToastContextType | undefined>;
20
+ function getToastContext(): Context<ToastContextType | undefined> {
21
+ _ToastContext ??= createContext<ToastContextType | undefined>(undefined);
22
+ return _ToastContext;
23
+ }
18
24
 
19
25
  export function ToastProvider({ children }: { children: ReactNode }) {
26
+ const ToastContext = getToastContext();
20
27
  const [toasts, setToasts] = useState<Toast[]>([]);
21
28
  const containerRef = useRef<HTMLDivElement>(null);
22
29
 
@@ -84,8 +91,8 @@ function ToastItem({ toast, onRemove }: { toast: Toast; onRemove: () => void })
84
91
  );
85
92
  }
86
93
 
87
- export function useToast() {
88
- const context = useContext(ToastContext);
94
+ export function useToast(): ToastContextType {
95
+ const context = useContext(getToastContext());
89
96
  if (!context) {
90
97
  throw new Error('useToast must be used within a ToastProvider');
91
98
  }
@@ -46,6 +46,8 @@ Searchable select with type-ahead filtering. Combines a text input with a dropdo
46
46
  <tr><td>`--combobox_listbox-border`</td><td>`none`</td><td>Dropdown list border</td></tr>
47
47
  <tr><td>`--combobox_listbox-radius`</td><td>`var(--bdc-outline_radius)`</td><td>Dropdown list corner radius</td></tr>
48
48
  <tr><td>`--combobox_listbox-shadow`</td><td>`var(--bds-shadow_m)`</td><td>Dropdown list box shadow</td></tr>
49
+ <tr><td>`--combobox_option-bg--highlighted`</td><td>`var(--bds-color_bg--subtle)`</td><td>Highlighted option background</td></tr>
50
+ <tr><td>`--combobox_option-color--highlighted`</td><td>`var(--bds-color_interactive_on-bg)`</td><td>Highlighted option text colour</td></tr>
49
51
  </tbody>
50
52
  </table>
51
53
 
@@ -73,7 +73,7 @@
73
73
  padding: var(--bds-space_xxs) 0;
74
74
  border: var(--combobox_listbox-border, none);
75
75
  --bdc_color: currentcolor;
76
- --bdc-outline_radius: var(--bds-border_radius--xs);
76
+ --bdc-outline_radius: var(--bds-border_radius--s);
77
77
 
78
78
  border-radius: var(--combobox_listbox-radius, var(--bdc-outline_radius));
79
79
  background-color: var(--combobox_color, var(--bds-color_bg));
@@ -92,8 +92,8 @@
92
92
  }
93
93
 
94
94
  .option.--highlighted {
95
- background-color: var(--bds-color_bg--subtle);
96
- color: var(--bds-color_interactive_on-bg);
95
+ background-color: var(--combobox_option-bg--highlighted, var(--bds-color_bg--subtle));
96
+ color: var(--combobox_option-color--highlighted, var(--bds-color_interactive_on-bg));
97
97
  }
98
98
 
99
99
  .option.--selected {
@@ -41,6 +41,8 @@ File upload input with styled trigger button, hint, and error support.
41
41
  <tbody>
42
42
  <tr><td>`--fileInput_color`</td><td>`var(--bds-color_on-bg)`</td><td>Text colour</td></tr>
43
43
  <tr><td>`--fileInput_border-color`</td><td>`currentcolor`</td><td>Drop zone border colour</td></tr>
44
+ <tr><td>`--fileInput_border-color--hover`</td><td>`var(--bds-color_interactive)`</td><td>Drop zone border colour on hover</td></tr>
45
+ <tr><td>`--fileInput_bg--hover`</td><td>`rgb(from var(--bds-color_interactive) r g b / 4%)`</td><td>Drop zone background on hover</td></tr>
44
46
  </tbody>
45
47
  </table>
46
48
 
@@ -80,8 +80,8 @@
80
80
 
81
81
  @media (hover: hover) and (pointer: fine) {
82
82
  .dropZone:not(.isDisabled):hover {
83
- border-color: var(--bds-color_interactive);
84
- background-color: rgb(from var(--bds-color_interactive) r g b / 4%);
83
+ border-color: var(--fileInput_border-color--hover, var(--bds-color_interactive));
84
+ background-color: var(--fileInput_bg--hover, rgb(from var(--bds-color_interactive) r g b / 4%));
85
85
  }
86
86
  }
87
87
  }
@@ -43,6 +43,10 @@ Numeric text input with increment/decrement stepper buttons. Enforces `min`, `ma
43
43
  <tr><td>`--numberInput_border`</td><td>`none`</td><td>Border</td></tr>
44
44
  <tr><td>`--numberInput_radius`</td><td>`var(--bdc-outline_radius)`</td><td>Corner radius</td></tr>
45
45
  <tr><td>`--numberInput_shadow`</td><td>`var(--bdc-outline_shadow)`</td><td>Box shadow</td></tr>
46
+ <tr><td>`--numberInput_stepper-color`</td><td>`var(--bds-color_interactive)`</td><td>Stepper button icon colour</td></tr>
47
+ <tr><td>`--numberInput_stepper-bg`</td><td>`var(--bds-color_bg--subtle)`</td><td>Stepper button background</td></tr>
48
+ <tr><td>`--numberInput_stepper-bg--hover`</td><td>`var(--bds-color_bg--subtle)`</td><td>Stepper button background on hover</td></tr>
49
+ <tr><td>`--numberInput_stepper-opacity--hover`</td><td>`0.7`</td><td>Stepper button opacity on hover</td></tr>
46
50
  </tbody>
47
51
  </table>
48
52
 
@@ -58,7 +58,7 @@
58
58
  justify-content: center;
59
59
  padding: var(--bds-space_xs);
60
60
  margin: 1px;
61
- background-color: var(--bds-color_bg--subtle);
61
+ background-color: var(--numberInput_stepper-bg, var(--bds-color_bg--subtle));
62
62
  color: var(--numberInput_color, var(--bds-color_on-bg));
63
63
  cursor: pointer;
64
64
  transition: var(--bds-animation_transition);
@@ -88,8 +88,8 @@
88
88
 
89
89
  @media (hover: hover) and (pointer: fine) {
90
90
  .stepper:not(:disabled):hover {
91
- background-color: var(--bds-color_bg--subtle);
92
- opacity: 0.7;
91
+ background-color: var(--numberInput_stepper-bg--hover, var(--bds-color_bg--subtle));
92
+ opacity: var(--numberInput_stepper-opacity--hover, 0.7);
93
93
  }
94
94
  }
95
95
  }
@@ -103,6 +103,7 @@ When `selectedIndex` is omitted, the component auto-detects the active item from
103
103
  | `--control_label-color` | `var(--bds-color_on-bg--subtle)` | Inactive item text colour |
104
104
  | `--control_label-color--active` | `var(--bds-color_on-interactive)` (filled) / `var(--bds-color_interactive)` (outline) | Active item text colour |
105
105
  | `--control_label-color--hover` | `var(--bds-color_on-bg)` | Hovered inactive item text colour |
106
+ | `--control_indicator-color` | `var(--bds-color_interactive)` | Outline indicator border colour (outline variant) |
106
107
 
107
108
  ## Accessibility
108
109
 
@@ -109,7 +109,7 @@
109
109
 
110
110
  .control.--variant_outline .indicator {
111
111
  display: block;
112
- box-shadow: inset 0 0 0 2px var(--bds-color_interactive);
112
+ box-shadow: inset 0 0 0 2px var(--control_indicator-color, var(--bds-color_interactive));
113
113
  }
114
114
 
115
115
  @media (hover: hover) and (pointer: fine) {
@@ -47,6 +47,10 @@ Range input for selecting a numeric value within a bounded range.
47
47
  </thead>
48
48
  <tbody>
49
49
  <tr><td>`--slider_color-active`</td><td>`var(--bdc-color_active)`</td><td>Filled track and thumb colour</td></tr>
50
+ <tr><td>`--slider_track-bg`</td><td>`var(--bds-color_bg--subtle)`</td><td>Unfilled track background</td></tr>
51
+ <tr><td>`--slider_track-radius`</td><td>`var(--bds-border_radius--full)`</td><td>Track border radius</td></tr>
52
+ <tr><td>`--slider_thumb-radius`</td><td>`var(--bds-border_radius--circle)`</td><td>Thumb border radius</td></tr>
53
+ <tr><td>`--slider_color--error`</td><td>`var(--bds-color_error)`</td><td>Track and thumb colour in error state</td></tr>
50
54
  </tbody>
51
55
  </table>
52
56
 
@@ -31,8 +31,8 @@
31
31
  to right,
32
32
  var(--slider_color-active, var(--bdc-color_active)) 0%,
33
33
  var(--slider_color-active, var(--bdc-color_active)) var(--slider_fill),
34
- var(--bds-color_bg--subtle) var(--slider_fill),
35
- var(--bds-color_bg--subtle) 100%
34
+ var(--slider_track-bg, var(--bds-color_bg--subtle)) var(--slider_fill),
35
+ var(--slider_track-bg, var(--bds-color_bg--subtle)) 100%
36
36
  );
37
37
  cursor: pointer;
38
38
  transition: var(--bds-animation_transition);
@@ -75,19 +75,19 @@
75
75
  .sliderError {
76
76
  background: linear-gradient(
77
77
  to right,
78
- var(--bds-color_error) 0%,
79
- var(--bds-color_error) var(--slider_fill),
80
- var(--bds-color_bg--subtle) var(--slider_fill),
81
- var(--bds-color_bg--subtle) 100%
78
+ var(--slider_color--error, var(--bds-color_error)) 0%,
79
+ var(--slider_color--error, var(--bds-color_error)) var(--slider_fill),
80
+ var(--slider_track-bg, var(--bds-color_bg--subtle)) var(--slider_fill),
81
+ var(--slider_track-bg, var(--bds-color_bg--subtle)) 100%
82
82
  );
83
83
  }
84
84
 
85
85
  .sliderError::-webkit-slider-thumb {
86
- background-color: var(--bds-color_error);
86
+ background-color: var(--slider_color--error, var(--bds-color_error));
87
87
  }
88
88
 
89
89
  .sliderError::-moz-range-thumb {
90
- background-color: var(--bds-color_error);
90
+ background-color: var(--slider_color--error, var(--bds-color_error));
91
91
  }
92
92
 
93
93
  @media (prefers-reduced-motion: reduce) {
@@ -56,6 +56,9 @@ Toggle control for binary settings that take immediate effect — without requir
56
56
  <tr><td>`--switch_thumb-bg`</td><td>`var(--bds-color_grey)`</td><td>Thumb colour when off (also track outline)</td></tr>
57
57
  <tr><td>`--switch_track-bg--active`</td><td>`var(--bdc-color_active--subtle)`</td><td>Track background when on</td></tr>
58
58
  <tr><td>`--switch_thumb-bg--active`</td><td>`var(--bdc-color_active--strong)`</td><td>Thumb colour when on (also track outline)</td></tr>
59
+ <tr><td>`--switch_track-radius`</td><td>`var(--bds-border_radius--full)`</td><td>Track border radius</td></tr>
60
+ <tr><td>`--switch_thumb-radius`</td><td>`var(--bds-border_radius--circle)`</td><td>Thumb border radius</td></tr>
61
+ <tr><td>`--switch_border-color--error`</td><td>`var(--bds-color_error)`</td><td>Track outline colour in error state</td></tr>
59
62
  </tbody>
60
63
  </table>
61
64
 
@@ -78,7 +78,7 @@
78
78
 
79
79
  /* Error state — declared before checked/focus so higher-specificity states can override */
80
80
  .switch.switchError + .track {
81
- --bdc_color: var(--bds-color_error);
81
+ --bdc_color: var(--switch_border-color--error, var(--bds-color_error));
82
82
  }
83
83
 
84
84
  /* Checked state via CSS sibling combinator */
@@ -45,7 +45,7 @@ Multi-line text input with label, hint, and error support.
45
45
  <tr><td>`--textarea_color_bg`</td><td>`var(--bds-color_bg)`</td><td>Background colour</td></tr>
46
46
  <tr><td>`--textarea_color`</td><td>`var(--bds-color_on-bg)`</td><td>Text colour</td></tr>
47
47
  <tr><td>`--textarea_border`</td><td>`none`</td><td>Border</td></tr>
48
- <tr><td>`--textarea_radius`</td><td>`var(--bdc-outline_radius)`</td><td>Corner radius</td></tr>
48
+ <tr><td>`--textarea_radius`</td><td>`var(--bdc-outline_radius--l)` (1.5em)</td><td>Corner radius</td></tr>
49
49
  <tr><td>`--textarea_shadow`</td><td>`var(--bdc-outline_shadow)`</td><td>Box shadow</td></tr>
50
50
  </tbody>
51
51
  </table>
@@ -11,7 +11,7 @@
11
11
  padding: var(--bds-space_s);
12
12
  border: var(--textarea_border, none);
13
13
  --bdc_color: currentcolor;
14
- --bdc-outline_radius: var(--bds-border_radius--xs);
14
+ --bdc-outline_radius: var(--bdc-outline_radius--l);
15
15
 
16
16
  border-radius: var(--textarea_radius, var(--bdc-outline_radius));
17
17
  box-shadow: inset 0 0 0 var(--bdc-outline_width) var(--bdc_color), var(--textarea_shadow, var(--bdc-outline_shadow));
@@ -7,6 +7,8 @@ import * as Stories from './ButtonGroup.stories';
7
7
 
8
8
  Layout wrapper that arranges `Button` children according to a contextual variant. Handles spacing, alignment, and direction.
9
9
 
10
+ > **Recommended:** Always wrap buttons in a `ButtonGroup` when they appear inside a form. This ensures consistent spacing and alignment for form actions like submit, cancel, and navigation.
11
+
10
12
  ## Variants
11
13
 
12
14
 
@@ -40,13 +40,16 @@ Contained surface for grouping related content. Three visual variants provide di
40
40
 
41
41
  <table>
42
42
  <thead>
43
- <tr><th>Variable</th><th>Description</th></tr>
43
+ <tr><th>Variable</th><th>Default</th><th>Description</th></tr>
44
44
  </thead>
45
45
  <tbody>
46
- <tr><td>`--card_bg`</td><td>Card background colour</td></tr>
47
- <tr><td>`--card_on-bg`</td><td>Card text colour</td></tr>
48
- <tr><td>`--card_border-color`</td><td>Border colour (outlined variant)</td></tr>
49
- <tr><td>`--card_shadow`</td><td>Box shadow (elevated variant)</td></tr>
46
+ <tr><td>`--card_color`</td><td>`var(--bds-color_bg)`</td><td>Card background colour</td></tr>
47
+ <tr><td>`--card_on-color`</td><td>`var(--bds-color_on-bg)`</td><td>Card text colour</td></tr>
48
+ <tr><td>`--card_border`</td><td>`none`</td><td>Border (outlined variant)</td></tr>
49
+ <tr><td>`--card_shadow--clickable-hover`</td><td>`var(--bds-shadow_xl)`</td><td>Box shadow on hover for clickable cards</td></tr>
50
+ <tr><td>`--card_shadow--default-hover`</td><td>`var(--bds-shadow_m)`</td><td>Box shadow on hover for default variant</td></tr>
51
+ <tr><td>`--card_shadow--elevated-hover`</td><td>`var(--bds-shadow_2xl)`</td><td>Box shadow on hover for elevated variant</td></tr>
52
+ <tr><td>`--card_shadow--outlined-hover`</td><td>`var(--bds-shadow_s)`</td><td>Box shadow on hover for outlined variant</td></tr>
50
53
  </tbody>
51
54
  </table>
52
55
 
@@ -67,19 +67,19 @@
67
67
  @media (hover: hover) and (pointer: fine) {
68
68
  .card.--clickable:hover {
69
69
  transform: translateY(-2px);
70
- box-shadow: var(--bds-shadow_xl);
70
+ box-shadow: var(--card_shadow--clickable-hover, var(--bds-shadow_xl));
71
71
  }
72
72
 
73
73
  .card.--default:hover {
74
- box-shadow: var(--bds-shadow_m);
74
+ box-shadow: var(--card_shadow--default-hover, var(--bds-shadow_m));
75
75
  }
76
76
 
77
77
  .card.--elevated:hover {
78
- box-shadow: var(--bds-shadow_2xl);
78
+ box-shadow: var(--card_shadow--elevated-hover, var(--bds-shadow_2xl));
79
79
  }
80
80
 
81
81
  .card.--outlined:hover {
82
- box-shadow: var(--bds-shadow_s);
82
+ box-shadow: var(--card_shadow--outlined-hover, var(--bds-shadow_s));
83
83
  }
84
84
  }
85
85
  }
@@ -19,12 +19,15 @@ Heading block with optional subtitle for introducing a content section.
19
19
  ### Without subtitle
20
20
  <Canvas of={Stories.WithoutSubtitle} />
21
21
 
22
- ### Large
23
- <Canvas of={Stories.Large} />
22
+ ### Extra Small
23
+ <Canvas of={Stories.ExtraSmall} />
24
24
 
25
25
  ### Small
26
26
  <Canvas of={Stories.Small} />
27
27
 
28
+ ### Large
29
+ <Canvas of={Stories.Large} />
30
+
28
31
  ### Centered
29
32
  <Canvas of={Stories.Centered} />
30
33
 
@@ -40,7 +43,12 @@ Heading block with optional subtitle for introducing a content section.
40
43
  <tr><th>Variable</th><th>Default</th><th>Description</th></tr>
41
44
  </thead>
42
45
  <tbody>
46
+ <tr><td>`--sectionHeader-title-color`</td><td>`var(--bds-color_on-bg)`</td><td>Title text colour</td></tr>
47
+ <tr><td>`--sectionHeader_title-size`</td><td>varies by `size` prop</td><td>Title font-size (overrides the variant default)</td></tr>
48
+ <tr><td>`--sectionHeader_title-line-height`</td><td>varies by `size` prop</td><td>Title line-height</td></tr>
49
+ <tr><td>`--sectionHeader_title-weight`</td><td>`var(--bds-font_weight--bold)`</td><td>Title font-weight</td></tr>
43
50
  <tr><td>`--sectionHeader_subtitle-color`</td><td>`var(--bds-color_grey--strong)`</td><td>Subtitle text colour</td></tr>
51
+ <tr><td>`--sectionHeader_subtitle-size`</td><td>varies by `size` prop</td><td>Subtitle font-size</td></tr>
44
52
  </tbody>
45
53
  </table>
46
54
 
@@ -34,37 +34,49 @@
34
34
  text-align: end;
35
35
  }
36
36
 
37
- .sectionHeader.--small .title {
38
- font-size: var(--bds-font_size--heading-1);
39
- line-height: var(--bds-font_line-height--heading);
40
- font-weight: var(--bds-font_weight--bold);
37
+ /* medium first — default size, so MCP extraction picks up its fallbacks */
38
+ .sectionHeader.--medium .title {
39
+ font-size: var(--sectionHeader_title-size, var(--bds-font_size--display));
40
+ line-height: var(--sectionHeader_title-line-height, var(--bds-font_line-height--display));
41
+ font-weight: var(--sectionHeader_title-weight, var(--bds-font_weight--bold));
41
42
  }
42
43
 
43
- .sectionHeader.--small .subtitle {
44
- font-size: var(--bds-font_size--body);
44
+ .sectionHeader.--medium .subtitle {
45
+ font-size: var(--sectionHeader_subtitle-size, var(--bds-font_size--heading-3));
46
+ line-height: 1.3;
47
+ }
48
+
49
+ .sectionHeader.--xs .title {
50
+ font-size: var(--sectionHeader_title-size, 1.5em);
51
+ line-height: var(--sectionHeader_title-line-height, var(--bds-font_line-height--heading));
52
+ font-weight: var(--sectionHeader_title-weight, var(--bds-font_weight--bold));
53
+ }
54
+
55
+ .sectionHeader.--xs .subtitle {
56
+ font-size: var(--sectionHeader_subtitle-size, var(--bds-font_size--body));
45
57
  line-height: 1.4;
46
58
  }
47
59
 
48
- .sectionHeader.--medium .title {
49
- font-size: var(--bds-font_size--display);
50
- line-height: var(--bds-font_line-height--display);
51
- font-weight: var(--bds-font_weight--bold);
60
+ .sectionHeader.--small .title {
61
+ font-size: var(--sectionHeader_title-size, var(--bds-font_size--heading-1));
62
+ line-height: var(--sectionHeader_title-line-height, var(--bds-font_line-height--heading));
63
+ font-weight: var(--sectionHeader_title-weight, var(--bds-font_weight--bold));
52
64
  }
53
65
 
54
- .sectionHeader.--medium .subtitle {
55
- font-size: var(--bds-font_size--heading-3);
56
- line-height: 1.3;
66
+ .sectionHeader.--small .subtitle {
67
+ font-size: var(--sectionHeader_subtitle-size, var(--bds-font_size--body));
68
+ line-height: 1.4;
57
69
  }
58
70
 
59
71
  .sectionHeader.--large .title {
60
- font-size: var(--bds-font_size--display);
61
- line-height: var(--bds-font_line-height--display);
62
- font-weight: var(--bds-font_weight--bold);
72
+ font-size: var(--sectionHeader_title-size, var(--bds-font_size--display));
73
+ line-height: var(--sectionHeader_title-line-height, var(--bds-font_line-height--display));
74
+ font-weight: var(--sectionHeader_title-weight, var(--bds-font_weight--bold));
63
75
  letter-spacing: var(--bds-font_tracking--tight);
64
76
  }
65
77
 
66
78
  .sectionHeader.--large .subtitle {
67
- font-size: var(--bds-font_size--heading-2);
79
+ font-size: var(--sectionHeader_subtitle-size, var(--bds-font_size--heading-2));
68
80
  line-height: 1.3;
69
81
  font-weight: var(--bds-font_weight--medium);
70
82
  }
@@ -28,4 +28,9 @@ describe('SectionHeader', () => {
28
28
  const { container } = render(<SectionHeader title="Title" className="custom" />);
29
29
  expect(container.firstChild).toHaveClass('custom');
30
30
  });
31
+
32
+ it('renders the xs size variant', () => {
33
+ const { container } = render(<SectionHeader title="XS Title" size="xs" />);
34
+ expect(container.firstChild).toHaveClass('--xs');
35
+ });
31
36
  });
@@ -6,7 +6,7 @@ const meta = {
6
6
  component: SectionHeader,
7
7
  argTypes: {
8
8
  alignment: { control: 'select', options: ['start', 'center', 'end'] },
9
- size: { control: 'select', options: ['small', 'medium', 'large'] },
9
+ size: { control: 'select', options: ['xs', 'small', 'medium', 'large'] },
10
10
  },
11
11
  } satisfies Meta<typeof SectionHeader>;
12
12
 
@@ -16,5 +16,6 @@ type Story = StoryObj<typeof meta>;
16
16
  export const Default: Story = { args: { title: 'Section Title', subtitle: 'A descriptive subtitle.' } };
17
17
  export const WithoutSubtitle: Story = { args: { title: 'Title Only' } };
18
18
  export const Centered: Story = { args: { title: 'Centered Title', subtitle: 'Centered subtitle.', alignment: 'center' } };
19
+ export const ExtraSmall: Story = { args: { title: 'Extra Small Header', subtitle: 'Extra small size.', size: 'xs' } };
19
20
  export const Small: Story = { args: { title: 'Small Header', subtitle: 'Small size.', size: 'small' } };
20
21
  export const Large: Story = { args: { title: 'Large Header', subtitle: 'Large size.', size: 'large' } };
@@ -9,7 +9,7 @@ type SectionHeaderProps = WithClassName & Omit<HTMLAttributes<HTMLDivElement>, '
9
9
  title: string;
10
10
  subtitle?: string;
11
11
  alignment?: 'start' | 'center' | 'end';
12
- size?: 'small' | 'medium' | 'large';
12
+ size?: 'xs' | 'small' | 'medium' | 'large';
13
13
  titleAs?: IntrinsicElement;
14
14
  };
15
15
 
@@ -43,6 +43,7 @@ Vertically stacked sections that can be expanded and collapsed independently.
43
43
  <tbody>
44
44
  <tr><td>`--accordion_border`</td><td>`none`</td><td>Container border</td></tr>
45
45
  <tr><td>`--accordion_radius`</td><td>`var(--bdc-outline_radius)`</td><td>Container corner radius</td></tr>
46
+ <tr><td>`--accordion_trigger-bg--hover`</td><td>`var(--bds-color_bg--subtle)`</td><td>Trigger button background on hover</td></tr>
46
47
  </tbody>
47
48
  </table>
48
49
 
@@ -52,7 +52,7 @@
52
52
 
53
53
  @media (hover: hover) and (pointer: fine) {
54
54
  .trigger:not(:disabled):hover {
55
- background-color: var(--bds-color_bg--subtle);
55
+ background-color: var(--accordion_trigger-bg--hover, var(--bds-color_bg--subtle));
56
56
  }
57
57
  }
58
58
 
@@ -47,11 +47,14 @@ Inline contextual feedback message. Use for confirmations, warnings, errors, and
47
47
 
48
48
  <table>
49
49
  <thead>
50
- <tr><th>Variable</th><th>Description</th></tr>
50
+ <tr><th>Variable</th><th>Default</th><th>Description</th></tr>
51
51
  </thead>
52
52
  <tbody>
53
- <tr><td>`--alert_color`</td><td>Background colour (defaults to variant semantic token)</td></tr>
54
- <tr><td>`--alert_on-color`</td><td>Text and icon colour</td></tr>
53
+ <tr><td>`--alert_color`</td><td>Per variant</td><td>Background colour (defaults to variant semantic token)</td></tr>
54
+ <tr><td>`--alert_on-color`</td><td>Per variant</td><td>Text and icon colour</td></tr>
55
+ <tr><td>`--alert_dismiss-border`</td><td>`none`</td><td>Dismiss button border</td></tr>
56
+ <tr><td>`--alert_dismiss-radius`</td><td>`var(--bds-border_radius--circle)`</td><td>Dismiss button border radius</td></tr>
57
+ <tr><td>`--alert_dismiss-opacity--hover`</td><td>`0.7`</td><td>Dismiss button opacity on hover</td></tr>
55
58
  </tbody>
56
59
  </table>
57
60