@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.
- package/AGENTS.md +25 -6
- package/dist/client.cjs +57 -52
- package/dist/client.css +546 -536
- package/dist/client.d.cts +1 -1
- package/dist/client.d.ts +1 -1
- package/dist/client.js +57 -52
- package/dist/index.cjs +57 -52
- package/dist/index.css +546 -536
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +57 -52
- package/package.json +1 -1
- package/src/components/interaction/Button/Button.mdx +11 -3
- package/src/components/interaction/Button/Button.module.css +5 -5
- package/src/components/interaction/Command/Command.mdx +1 -0
- package/src/components/interaction/Command/Command.module.css +1 -1
- package/src/components/interaction/Drawer/Drawer.mdx +2 -0
- package/src/components/interaction/Drawer/Drawer.module.css +1 -1
- package/src/components/interaction/DropdownMenu/DropdownMenu.mdx +19 -0
- package/src/components/interaction/DropdownMenu/DropdownMenu.module.css +2 -2
- package/src/components/interaction/Rating/Rating.mdx +14 -0
- package/src/components/interaction/Rating/Rating.module.css +2 -2
- package/src/components/interaction/Toast/Toast.mdx +12 -4
- package/src/components/interaction/Toast/Toast.spec.tsx +11 -0
- package/src/components/interaction/Toast/Toast.tsx +11 -4
- package/src/components/interaction/form/Combobox/Combobox.mdx +2 -0
- package/src/components/interaction/form/Combobox/Combobox.module.css +3 -3
- package/src/components/interaction/form/FileInput/FileInput.mdx +2 -0
- package/src/components/interaction/form/FileInput/FileInput.module.css +2 -2
- package/src/components/interaction/form/NumberInput/NumberInput.mdx +4 -0
- package/src/components/interaction/form/NumberInput/NumberInput.module.css +3 -3
- package/src/components/interaction/form/SegmentedControl/SegmentedControl.mdx +1 -0
- package/src/components/interaction/form/SegmentedControl/SegmentedControl.module.css +1 -1
- package/src/components/interaction/form/Slider/Slider.mdx +4 -0
- package/src/components/interaction/form/Slider/Slider.module.css +8 -8
- package/src/components/interaction/form/Switch/Switch.mdx +3 -0
- package/src/components/interaction/form/Switch/Switch.module.css +1 -1
- package/src/components/interaction/form/Textarea/Textarea.mdx +1 -1
- package/src/components/interaction/form/Textarea/Textarea.module.css +1 -1
- package/src/components/layout/ButtonGroup/ButtonGroup.mdx +2 -0
- package/src/components/layout/Card/Card.mdx +8 -5
- package/src/components/layout/Card/Card.module.css +4 -4
- package/src/components/layout/SectionHeader/SectionHeader.mdx +10 -2
- package/src/components/layout/SectionHeader/SectionHeader.module.css +29 -17
- package/src/components/layout/SectionHeader/SectionHeader.spec.tsx +5 -0
- package/src/components/layout/SectionHeader/SectionHeader.stories.tsx +2 -1
- package/src/components/layout/SectionHeader/SectionHeader.tsx +1 -1
- package/src/components/ui/Accordion/Accordion.mdx +1 -0
- package/src/components/ui/Accordion/Accordion.module.css +1 -1
- package/src/components/ui/Alert/Alert.mdx +6 -3
- package/src/components/ui/Alert/Alert.module.css +1 -1
- package/src/components/ui/Calendar/Calendar.mdx +5 -0
- package/src/components/ui/Calendar/Calendar.module.css +5 -5
- package/src/components/ui/Carousel/Carousel.mdx +14 -0
- package/src/components/ui/Carousel/Carousel.module.css +1 -1
- package/src/components/ui/NotificationBanner/NotificationBanner.mdx +18 -0
- package/src/components/ui/NotificationBanner/NotificationBanner.module.css +1 -1
- package/src/components/ui/Pagination/Pagination.mdx +21 -0
- package/src/components/ui/Pagination/Pagination.module.css +5 -5
- package/src/components/ui/Table/Table.mdx +2 -0
- package/src/components/ui/Table/Table.module.css +2 -2
- package/src/components/ui/Tabs/Tabs.mdx +17 -0
- package/src/components/ui/Tabs/Tabs.module.css +3 -3
- 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
|
|
|
@@ -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
|
-
|
|
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
|
-
|
|
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(
|
|
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--
|
|
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)
|
|
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(--
|
|
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>`--
|
|
47
|
-
<tr><td>`--card_on-bg`</td><td>Card text colour</td></tr>
|
|
48
|
-
<tr><td>`--card_border
|
|
49
|
-
<tr><td>`--card_shadow`</td><td>Box shadow
|
|
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
|
-
###
|
|
23
|
-
<Canvas of={Stories.
|
|
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
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
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.--
|
|
44
|
-
font-size: var(--bds-font_size--
|
|
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.--
|
|
49
|
-
font-size: var(--bds-font_size--
|
|
50
|
-
line-height: var(--bds-font_line-height--
|
|
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.--
|
|
55
|
-
font-size: var(--bds-font_size--
|
|
56
|
-
line-height: 1.
|
|
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
|
|
|
@@ -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
|
|