@boostdev/design-system-components 0.1.18 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. package/AGENTS.md +65 -27
  2. package/README.md +64 -29
  3. package/dist/client.cjs +412 -241
  4. package/dist/client.css +1378 -1186
  5. package/dist/client.d.cts +43 -16
  6. package/dist/client.d.ts +43 -16
  7. package/dist/client.js +414 -245
  8. package/dist/index.cjs +412 -241
  9. package/dist/index.css +1378 -1186
  10. package/dist/index.d.cts +43 -16
  11. package/dist/index.d.ts +43 -16
  12. package/dist/index.js +414 -245
  13. package/package.json +9 -4
  14. package/src/components/interaction/Button/Button.mdx +2 -5
  15. package/src/components/interaction/Button/Button.module.css +74 -44
  16. package/src/components/interaction/Button/Button.stories.tsx +4 -4
  17. package/src/components/interaction/Button/Button.tsx +5 -5
  18. package/src/components/interaction/Button/index.ts +1 -0
  19. package/src/components/interaction/Command/Command.module.css +53 -38
  20. package/src/components/interaction/Command/Command.spec.tsx +24 -0
  21. package/src/components/interaction/Command/Command.tsx +5 -0
  22. package/src/components/interaction/Dialog/Dialog.mdx +2 -2
  23. package/src/components/interaction/Dialog/Dialog.module.css +20 -10
  24. package/src/components/interaction/Dialog/Dialog.spec.tsx +19 -0
  25. package/src/components/interaction/Dialog/Dialog.tsx +22 -0
  26. package/src/components/interaction/Drawer/Drawer.module.css +11 -11
  27. package/src/components/interaction/Drawer/Drawer.spec.tsx +30 -0
  28. package/src/components/interaction/Drawer/Drawer.tsx +7 -3
  29. package/src/components/interaction/DropdownMenu/DropdownMenu.module.css +24 -19
  30. package/src/components/interaction/DropdownMenu/DropdownMenu.stories.tsx +4 -4
  31. package/src/components/interaction/Popover/Popover.module.css +17 -12
  32. package/src/components/interaction/Popover/Popover.spec.tsx +25 -4
  33. package/src/components/interaction/Popover/Popover.stories.tsx +1 -1
  34. package/src/components/interaction/Popover/Popover.tsx +5 -2
  35. package/src/components/interaction/Rating/Rating.module.css +3 -3
  36. package/src/components/interaction/Toast/Toast.module.css +19 -19
  37. package/src/components/interaction/Toast/Toast.tsx +1 -1
  38. package/src/components/interaction/form/Checkbox/Checkbox.mdx +2 -2
  39. package/src/components/interaction/form/Checkbox/Checkbox.module.css +22 -18
  40. package/src/components/interaction/form/Checkbox/Checkbox.tsx +2 -2
  41. package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.module.css +29 -0
  42. package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.spec.tsx +87 -0
  43. package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.stories.tsx +62 -0
  44. package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.tsx +46 -0
  45. package/src/components/interaction/form/CheckboxGroup/index.ts +2 -0
  46. package/src/components/interaction/form/Combobox/Combobox.module.css +44 -34
  47. package/src/components/interaction/form/Combobox/Combobox.tsx +0 -1
  48. package/src/components/interaction/form/FileInput/FileInput.module.css +24 -16
  49. package/src/components/interaction/form/FileInput/FileInput.tsx +5 -2
  50. package/src/components/interaction/form/FormInput/FormInput.module.css +21 -16
  51. package/src/components/interaction/form/FormInput/FormInput.tsx +3 -0
  52. package/src/components/interaction/form/NumberInput/NumberInput.module.css +25 -19
  53. package/src/components/interaction/form/NumberInput/NumberInput.tsx +5 -2
  54. package/src/components/interaction/form/Radio/Radio.mdx +3 -3
  55. package/src/components/interaction/form/Radio/Radio.module.css +28 -24
  56. package/src/components/interaction/form/Radio/Radio.stories.tsx +1 -1
  57. package/src/components/interaction/form/Radio/Radio.tsx +2 -2
  58. package/src/components/interaction/form/RadioGroup/RadioGroup.module.css +29 -0
  59. package/src/components/interaction/form/RadioGroup/RadioGroup.spec.tsx +75 -0
  60. package/src/components/interaction/form/RadioGroup/RadioGroup.stories.tsx +64 -0
  61. package/src/components/interaction/form/RadioGroup/RadioGroup.tsx +46 -0
  62. package/src/components/interaction/form/RadioGroup/index.ts +2 -0
  63. package/src/components/interaction/form/SegmentedControl/SegmentedControl.mdx +5 -5
  64. package/src/components/interaction/form/SegmentedControl/SegmentedControl.module.css +26 -26
  65. package/src/components/interaction/form/SegmentedControl/SegmentedControl.tsx +4 -0
  66. package/src/components/interaction/form/Select/Select.module.css +24 -19
  67. package/src/components/interaction/form/Select/Select.tsx +3 -0
  68. package/src/components/interaction/form/Slider/Slider.mdx +1 -1
  69. package/src/components/interaction/form/Slider/Slider.module.css +24 -24
  70. package/src/components/interaction/form/Slider/Slider.tsx +1 -0
  71. package/src/components/interaction/form/Switch/Switch.mdx +4 -4
  72. package/src/components/interaction/form/Switch/Switch.module.css +22 -16
  73. package/src/components/interaction/form/Switch/Switch.tsx +1 -1
  74. package/src/components/interaction/form/Textarea/Textarea.module.css +23 -18
  75. package/src/components/interaction/form/Textarea/Textarea.tsx +3 -0
  76. package/src/components/interaction/form/atoms/InputContainer.module.css +2 -2
  77. package/src/components/interaction/form/atoms/Label.module.css +2 -2
  78. package/src/components/interaction/form/atoms/Message.module.css +2 -2
  79. package/src/components/layout/ButtonGroup/ButtonGroup.module.css +2 -2
  80. package/src/components/layout/ButtonGroup/ButtonGroup.stories.tsx +2 -2
  81. package/src/components/layout/ButtonGroup/ButtonGroup.tsx +8 -3
  82. package/src/components/layout/ButtonGroup/index.ts +1 -0
  83. package/src/components/layout/Card/Card.module.css +30 -16
  84. package/src/components/layout/Card/Card.tsx +1 -1
  85. package/src/components/layout/IconWrapper/IconWrapper.mdx +2 -2
  86. package/src/components/layout/IconWrapper/IconWrapper.module.css +5 -5
  87. package/src/components/layout/IconWrapper/IconWrapper.tsx +4 -3
  88. package/src/components/layout/IconWrapper/index.ts +1 -0
  89. package/src/components/layout/SectionHeader/SectionHeader.module.css +23 -23
  90. package/src/components/layout/SectionHeader/SectionHeader.spec.tsx +2 -2
  91. package/src/components/layout/SectionHeader/SectionHeader.tsx +2 -2
  92. package/src/components/ui/Accordion/Accordion.module.css +23 -18
  93. package/src/components/ui/Alert/Alert.module.css +31 -27
  94. package/src/components/ui/Avatar/Avatar.module.css +6 -6
  95. package/src/components/ui/Avatar/Avatar.tsx +1 -1
  96. package/src/components/ui/Badge/Badge.mdx +2 -2
  97. package/src/components/ui/Badge/Badge.module.css +15 -15
  98. package/src/components/ui/Breadcrumb/Breadcrumb.module.css +11 -11
  99. package/src/components/ui/Calendar/Calendar.module.css +39 -29
  100. package/src/components/ui/Calendar/Calendar.tsx +6 -2
  101. package/src/components/ui/Carousel/Carousel.module.css +15 -10
  102. package/src/components/ui/Carousel/Carousel.stories.tsx +1 -1
  103. package/src/components/ui/Collapsible/Collapsible.mdx +6 -6
  104. package/src/components/ui/Collapsible/Collapsible.module.css +18 -18
  105. package/src/components/ui/DescriptionList/DescriptionList.module.css +8 -8
  106. package/src/components/ui/Link/Link.module.css +14 -14
  107. package/src/components/ui/Loading/Loading.module.css +8 -2
  108. package/src/components/ui/NotificationBanner/NotificationBanner.module.css +27 -23
  109. package/src/components/ui/Pagination/Pagination.module.css +22 -17
  110. package/src/components/ui/Progress/Progress.mdx +1 -1
  111. package/src/components/ui/Progress/Progress.module.css +10 -10
  112. package/src/components/ui/ProgressCircle/ProgressCircle.module.css +8 -8
  113. package/src/components/ui/Separator/Separator.module.css +1 -1
  114. package/src/components/ui/Separator/Separator.tsx +1 -1
  115. package/src/components/ui/Skeleton/Skeleton.module.css +5 -5
  116. package/src/components/ui/SkipLink/SkipLink.module.css +17 -12
  117. package/src/components/ui/Table/Table.module.css +35 -30
  118. package/src/components/ui/Table/Table.tsx +2 -1
  119. package/src/components/ui/Tabs/Tabs.module.css +17 -17
  120. package/src/components/ui/Tabs/Tabs.tsx +0 -1
  121. package/src/components/ui/Tooltip/Tooltip.module.css +12 -12
  122. package/src/components/ui/Tooltip/Tooltip.spec.tsx +3 -3
  123. package/src/components/ui/Tooltip/Tooltip.tsx +10 -2
  124. package/src/components/ui/Typography/Typography.module.css +18 -18
  125. package/src/css/bdc.css +61 -0
  126. package/src/css/index.css +5 -0
  127. package/src/index.ts +7 -0
  128. package/src/stories/DesignSystem/Borders.mdx +158 -0
  129. package/src/stories/DesignSystem/Colors.mdx +196 -0
  130. package/src/stories/DesignSystem/Elevation.mdx +127 -0
  131. package/src/stories/DesignSystem/Grid.mdx +140 -0
  132. package/src/stories/DesignSystem/Motion.mdx +96 -0
  133. package/src/stories/DesignSystem/Overview.mdx +99 -0
  134. package/src/stories/DesignSystem/Spacing.mdx +74 -0
  135. package/src/stories/DesignSystem/Typography.mdx +110 -0
  136. package/src/stories/Introduction.css +2 -2
  137. package/src/stories/Introduction.mdx +7 -7
package/AGENTS.md CHANGED
@@ -16,10 +16,10 @@ Or individual token layers. All component styles live inside `@layer component`.
16
16
 
17
17
  ## Component categories
18
18
 
19
- - **ui/**: Pure display Badge, Typography, Loading, Skeleton, Collapsible
20
- - **interaction/**: Interactive — Button, Dialog, Toast (with Provider + hook), Rating
21
- - **interaction/form/**: Form fields FormInput, Checkbox, Radio, Switch, SegmentedControl (+ atom primitives Label, Message, InputContainer)
22
- - **layout/**: Layout helpers — ButtonGroup, Card, SectionHeader, IconWrapper
19
+ - **ui/**: Accordion, Alert, Avatar, Badge, Breadcrumb, Calendar, Carousel, Collapsible, DescriptionList, Link, Loading, NotificationBanner, Pagination, Progress, ProgressCircle, Separator, Skeleton, SkipLink, Table, Tabs, Tooltip, Typography
20
+ - **interaction/**: Button, Command, Dialog, Drawer, DropdownMenu, Popover, Rating, Toast (ToastProvider + useToast hook)
21
+ - **interaction/form/**: Checkbox, CheckboxGroup, Combobox, FileInput, FormInput, NumberInput, Radio, RadioGroup, SegmentedControl, Select, Slider, Switch, Textarea (+ atom primitives: Label, Message, InputContainer)
22
+ - **layout/**: ButtonGroup, Card, IconWrapper, SectionHeader
23
23
 
24
24
  ## Styling conventions
25
25
 
@@ -39,36 +39,61 @@ Component-scoped variables use **inline fallbacks**, not top-level declarations.
39
39
  border: 1px solid var(--input_border-color, currentcolor);
40
40
  }
41
41
  .input:focus {
42
- --input_border-color: var(--color_interactive);
42
+ --input_border-color: var(--bds-interactive);
43
43
  }
44
44
 
45
45
  /* ❌ wrong — declaring defaults at the element level */
46
46
  .input {
47
- --input_border-color: var(--color_on-bg);
47
+ --input_border-color: var(--bds-on-bg);
48
48
  border: 1px solid var(--input_border-color);
49
49
  }
50
50
  ```
51
51
 
52
52
  For **border colours** that should match surrounding text/icon colour, use `currentcolor` as the fallback rather than a specific token.
53
53
 
54
+ ### bdc border tokens
55
+
56
+ Components use `outline` (not `border`) for all visual frame edges via `--bdc_*` tokens defined in `src/css/bdc.css`. Set local values on the component rule:
57
+
58
+ ```css
59
+ .myElement {
60
+ border: var(--myComponent_border, none);
61
+ --bdc_color: currentcolor;
62
+ --bdc_radius: var(--bds-border_radius--xs);
63
+
64
+ outline: var(--bdc_width) solid var(--bdc_color);
65
+ outline-offset: var(--bdc_offset);
66
+ border-radius: var(--myComponent_radius, var(--bdc_radius));
67
+ box-shadow: var(--myComponent_shadow, var(--bdc_shadow));
68
+ transition: --bdc_color var(--bds-animation_transition-duration) var(--bds-animation_easing);
69
+ }
70
+
71
+ .myElement:focus {
72
+ --bdc_color: var(--bdc_color--focus); /* transitions smoothly */
73
+ }
74
+ ```
75
+
76
+ Focus state uses `--bdc_color--focus` (= `--bds-interactive`) for mouse focus, and `var(--bds-outline_default)` for `:focus-visible` keyboard focus.
77
+
54
78
  ### Two-level fallback for active/selected state
55
79
 
56
80
  Components that express an active, checked, or filled state use a two-level chain so consumers can override at component level or globally:
57
81
 
58
82
  ```css
59
83
  /* component var → global semantic token */
60
- background-color: var(--checkbox_color-active, var(--color_active));
61
- border-color: var(--checkbox_color-active, var(--color_active));
62
- border: solid var(--checkbox_color-on-active, var(--color_on-active));
84
+ background-color: var(--checkbox_color-active, var(--bds-active));
85
+ border-color: var(--checkbox_color-active, var(--bds-active));
86
+ border: solid var(--checkbox_color-on-active, var(--bds-on-active));
63
87
  ```
64
88
 
65
89
  Apply this pattern to any component with a visually distinct active/selected/filled state (checkboxes, radio buttons, sliders, progress bars, switch thumbs, etc.).
66
90
 
67
91
  ## Token usage rules (from @boostdev/design-system-foundation)
68
92
 
93
+ - Token names use `--bds-` prefix (e.g. `--bds-bg`, `--bds-space_m`). Color tokens dropped the `color_` group: `var(--bds-cta)` not `var(--bds-color_cta)`.
69
94
  - Colour surfaces always pair with their `on-` content token
70
- - Space: use named scale tokens (`--space_xs`, `--space_m`, etc.), never raw px/rem
71
- - Shadow: use elevation scale (`--shadow_s` … `--shadow_2xl`)
95
+ - Space: use named scale tokens (`--bds-space_xs`, `--bds-space_m`, etc.), never raw px/rem
96
+ - Shadow: use elevation scale (`--bds-shadow_s` … `--bds-shadow_2xl`)
72
97
  - Z-index: use named role tokens, never raw integers
73
98
 
74
99
  ### Semantic tokens for state colours
@@ -77,20 +102,20 @@ Prefer semantic tokens over palette tokens. Key tokens for component states:
77
102
 
78
103
  | Token | Meaning | Used in |
79
104
  |-------|---------|---------|
80
- | `--color_active` | Active / checked / filled state | Checkbox, Radio, Slider, Progress, ProgressCircle |
81
- | `--color_on-active` | Content on `--color_active` | Checkbox tick, Radio inner dot |
82
- | `--color_active--subtle` | Subtle background for active track | Switch (`--switch_track-bg--active`) |
83
- | `--color_active--strong` | Strong foreground for active thumb | Switch (`--switch_thumb-bg--active`) |
84
- | `--color_success--subtle` | Subtle background for success variant | Alert, NotificationBanner |
85
- | `--color_on-success--subtle` | Text on success subtle background | Alert, NotificationBanner |
86
- | `--color_interactive` | Focus ring colour | All focusable inputs |
87
- | `--color_error` | Error state | All form components |
105
+ | `--bds-active` | Active / checked / filled state | Checkbox, Radio, Slider, Progress, ProgressCircle |
106
+ | `--bds-on-active` | Content on `--bds-active` | Checkbox tick, Radio inner dot |
107
+ | `--bds-active--subtle` | Subtle background for active track | Switch (`--switch_track-bg--active`) |
108
+ | `--bds-active--strong` | Strong foreground for active thumb | Switch (`--switch_thumb-bg--active`) |
109
+ | `--bds-success--subtle` | Subtle background for success variant | Alert, NotificationBanner |
110
+ | `--bds-on-success--subtle` | Text on success subtle background | Alert, NotificationBanner |
111
+ | `--bds-interactive` | Focus ring colour | All focusable inputs |
112
+ | `--bds-error` | Error state | All form components |
88
113
 
89
114
  Focus rings must use the relative-colour formula for consistency:
90
115
  ```css
91
- box-shadow: var(--component_focus-ring, 0 0 0 2px rgb(from var(--color_interactive) r g b / 20%));
116
+ box-shadow: var(--component_focus-ring, 0 0 0 2px rgb(from var(--bds-interactive) r g b / 20%));
92
117
  ```
93
- Error focus rings substitute `--color_error` for `--color_interactive`.
118
+ Error focus rings substitute `--bds-error` for `--bds-interactive`.
94
119
 
95
120
  ## Import paths
96
121
 
@@ -109,26 +134,39 @@ import '@boostdev/components/css';
109
134
 
110
135
  Every component must meet WCAG 2.1 Level AA:
111
136
 
112
- - **Semantic HTML** — use the correct element (`<button>`, `<a>`, `<nav>`, `<dialog>`, etc.)
137
+ - **Semantic HTML** — use the correct element (`<button>`, `<a>`, `<nav>`, `<dialog>`, etc.); never `<div onClick>`
113
138
  - **Keyboard navigable** — all interactive elements reachable and operable via keyboard
114
139
  - **Focus visible** — visible focus indicator on every interactive element (WCAG 2.4.7)
115
140
  - **ARIA** — add `aria-label` / `aria-labelledby` / `role` where native semantics are insufficient; no redundant ARIA
141
+ - **Modal dialogs** — `<dialog>` elements must have `aria-modal="true"`, trap Tab focus within the dialog, and restore focus to the trigger element on close
142
+ - **Form inputs** — each input needs one `<label htmlFor>` association (no duplicates); set `aria-required`, `aria-invalid`, and `aria-describedby` explicitly rather than relying solely on HTML attributes in spread props
143
+ - **Form groups** — group related checkboxes/radios with `CheckboxGroup`/`RadioGroup` (renders `<fieldset>`/`<legend>`); group segmented controls with `role="group"` + `aria-label`
116
144
  - **Colour contrast** — minimum 4.5:1 for text, 3:1 for large text and UI components (WCAG 1.4.3 / 1.4.11)
117
145
  - **Touch targets** — minimum 44×44px interactive area (WCAG 2.5.5)
118
- - **State communication** — disabled, loading, error, and expanded states communicated via ARIA attributes
119
- - **No motion harm** — respect `prefers-reduced-motion` for animations/transitions
146
+ - **State communication** — disabled, loading, error, and expanded states communicated via ARIA attributes; live regions (`aria-live`, `aria-atomic`) on dynamically updated content
147
+ - **No motion harm** — respect `prefers-reduced-motion` for animations/transitions; use `@media (prefers-reduced-motion: reduce)` to disable or reduce all `animation` and `transition` effects
148
+ - **Backdrop token** — use `var(--color_backdrop, rgb(0 0 0 / 50%))` for overlay backdrops; never hardcode `rgb()` values
120
149
 
121
150
  References: https://developer.mozilla.org/en-US/docs/Web/Accessibility | https://www.w3.org/WAI/WCAG21/quickref/
122
151
 
152
+ ## Key decisions
153
+
154
+ - **Button variants**: `default` (filled) and `ghost` (transparent, outlined). Renamed from `primary`/`secondary`.
155
+ - **Button colour model**: `--button_color` + `--button_on-color` are the two theming inputs. All other button CSS vars derive from these.
156
+ - **`bdc` border token system**: All component frame borders use `outline` (not `border`) via `--bdc_color`, `--bdc_width`, `--bdc_offset`, `--bdc_radius`, `--bdc_shadow` custom properties registered with `@property`. Default `border: none`. The `--bdc_color` `<color>` registration enables smooth CSS transitions on focus/error state changes without JavaScript.
157
+ - **`--bdc_offset: -1px`** (inset) makes outline appear like a traditional inset border. Switch uses `var(--bds-outline_offset)` (2px outside) — keep distinct.
158
+ - **Backdrop token**: `var(--color_backdrop, rgb(0 0 0 / 50%))` — never hardcode rgba. (`--color_backdrop` is a library hook token, not a foundation token.)
159
+
123
160
  ## Adding new components
124
161
 
125
162
  1. Create `src/components/{category}/{ComponentName}/`
126
163
  2. Add `ComponentName.tsx`, `ComponentName.module.css`, `index.ts`
127
164
  3. Wrap all CSS rules in `@layer component { ... }`
128
165
  4. Use only design token custom properties for colours, spacing, typography
129
- 5. Re-export from the category barrel and from `src/index.ts`
130
- 6. Meet all accessibility requirements listed above
131
- 7. After changes: `pnpm build`, `pnpm typecheck`, `pnpm lint`, `pnpm lint:css`, `pnpm test`
166
+ 5. Export the props interface (`export interface ComponentNameProps`) from the component file
167
+ 6. Re-export component and props type from the local `index.ts` and from `src/index.ts`
168
+ 7. Meet all accessibility requirements listed above
169
+ 8. After changes: `pnpm build`, `pnpm typecheck`, `pnpm lint`, `pnpm lint:css`, `pnpm test`
132
170
 
133
171
  ## MCP server
134
172
 
package/README.md CHANGED
@@ -149,7 +149,7 @@ Renders an `aria-hidden` shimmer block. Size it with a `className` or inline sty
149
149
  import { Button } from '@boostdev/components';
150
150
 
151
151
  <Button>Click me</Button>
152
- <Button variant="secondary">Cancel</Button>
152
+ <Button variant="ghost">Cancel</Button>
153
153
  <Button size="small">Small</Button>
154
154
  <Button href="/dashboard">Link button</Button>
155
155
  <Button iconStart={<Icon />} aria-label="Delete" />
@@ -158,7 +158,7 @@ import { Button } from '@boostdev/components';
158
158
 
159
159
  | Prop | Type | Default |
160
160
  |---|---|---|
161
- | `variant` | `'primary' \| 'secondary'` | `'primary'` |
161
+ | `variant` | `'default' \| 'ghost'` | `'default'` |
162
162
  | `size` | `'small' \| 'medium' \| 'large'` | `'medium'` |
163
163
  | `href` | `string` | — renders an `<a>` |
164
164
  | `iconStart` | `ReactNode` | — |
@@ -166,6 +166,19 @@ import { Button } from '@boostdev/components';
166
166
  | `hasPulse` | `boolean` | `false` |
167
167
  | `disabled` | `boolean` | `false` |
168
168
 
169
+ **Variants:**
170
+ - `default` — filled with `--button_color` (CTA green). Hover transitions to an outlined state.
171
+ - `ghost` — transparent background, border and text use `--button_color`. Hover fills.
172
+
173
+ **Re-theming** — set two CSS custom properties to change the colour of both variants:
174
+
175
+ ```css
176
+ .danger-zone .my-button {
177
+ --button_color: var(--bds-error);
178
+ --button_on-color: var(--bds-on-error);
179
+ }
180
+ ```
181
+
169
182
  ---
170
183
 
171
184
  #### Dialog
@@ -180,9 +193,10 @@ import { Dialog } from '@boostdev/components';
180
193
  ```
181
194
 
182
195
  Renders a native `<dialog>` element with a dimmed, blurred backdrop. `isOpen` controls open/close;
183
- `onClose` is called when the close button is pressed or the backdrop is clicked.
196
+ `onClose` is called when the close button is pressed or the backdrop is clicked. Dialog traps focus
197
+ while open and restores focus to the triggering element on close.
184
198
 
185
- Override the backdrop colour via `--dialog_backdrop-color` (default: `rgb(0 0 0 / 50%)`).
199
+ Override the backdrop colour via `--color_backdrop` (default: `rgb(0 0 0 / 50%)`).
186
200
 
187
201
  ---
188
202
 
@@ -248,7 +262,7 @@ import { FormInput } from '@boostdev/components';
248
262
  #### Checkbox
249
263
 
250
264
  ```tsx
251
- import { Checkbox } from '@boostdev/components';
265
+ import { Checkbox, CheckboxGroup } from '@boostdev/components';
252
266
 
253
267
  <Checkbox
254
268
  label="I agree to the terms"
@@ -257,13 +271,25 @@ import { Checkbox } from '@boostdev/components';
257
271
  />
258
272
  ```
259
273
 
274
+ Group multiple checkboxes with a shared label using `CheckboxGroup`:
275
+
276
+ ```tsx
277
+ <CheckboxGroup legend="Notifications" required error={errors.notifications}>
278
+ <Checkbox label="Email" name="notify_email" />
279
+ <Checkbox label="SMS" name="notify_sms" />
280
+ <Checkbox label="Push" name="notify_push" />
281
+ </CheckboxGroup>
282
+ ```
283
+
260
284
  #### Radio
261
285
 
262
286
  ```tsx
263
- import { Radio } from '@boostdev/components';
287
+ import { Radio, RadioGroup } from '@boostdev/components';
264
288
 
265
- <Radio label="Option A" name="choice" value="a" description="Optional supporting text." />
266
- <Radio label="Option B" name="choice" value="b" />
289
+ <RadioGroup legend="Preferred contact" required>
290
+ <Radio label="Option A" name="choice" value="a" description="Optional supporting text." />
291
+ <Radio label="Option B" name="choice" value="b" />
292
+ </RadioGroup>
267
293
  ```
268
294
 
269
295
  #### Switch
@@ -286,6 +312,7 @@ import { SegmentedControl } from '@boostdev/components';
286
312
  <SegmentedControl
287
313
  name="view"
288
314
  defaultValue="week"
315
+ aria-label="Calendar view"
289
316
  options={[
290
317
  { value: 'day', label: 'Day' },
291
318
  { value: 'week', label: 'Week' },
@@ -306,13 +333,16 @@ Single-select control with a sliding thumb. All options have equal width (sized
306
333
  ```tsx
307
334
  import { ButtonGroup, Button } from '@boostdev/components';
308
335
 
309
- <ButtonGroup variant="flow">
336
+ <ButtonGroup variant="flow" aria-label="Page navigation">
310
337
  <Button>Back</Button>
311
338
  <Button>Next</Button>
312
339
  </ButtonGroup>
313
340
  ```
314
341
 
315
- Variants: `flow` · `card` · `modal` · `content`
342
+ | Prop | Type | Default |
343
+ |---|---|---|
344
+ | `variant` | `'flow' \| 'card' \| 'modal' \| 'content'` | — |
345
+ | `aria-label` | `string` | — recommended when group purpose isn't clear from context |
316
346
 
317
347
  ---
318
348
 
@@ -367,10 +397,15 @@ import { IconWrapper } from '@boostdev/components';
367
397
  <IconWrapper>
368
398
  <svg>...</svg>
369
399
  </IconWrapper>
400
+
401
+ {/* Mark as decorative when accompanied by a visible label */}
402
+ <IconWrapper aria-hidden>
403
+ <svg>...</svg>
404
+ </IconWrapper>
370
405
  ```
371
406
 
372
407
  Renders a circular container sized to its own `font-size`. Override the background colour via the
373
- `--icon-wrapper-color` CSS custom property.
408
+ `--icon-wrapper-color` CSS custom property. Pass `aria-hidden` when the icon is decorative.
374
409
 
375
410
  ---
376
411
 
@@ -395,10 +430,10 @@ Every component exposes CSS custom properties as a styling API. Set them on a pa
395
430
  `style` to adjust the component without writing extra CSS:
396
431
 
397
432
  ```css
398
- /* Override the button background for a specific context */
433
+ /* Override the button colour for a specific context */
399
434
  .hero .button {
400
- --button_bg: var(--color_brand);
401
- --button_text: var(--color_on-brand);
435
+ --button_color: var(--bds-brand);
436
+ --button_on-color: var(--bds-on-brand);
402
437
  }
403
438
  ```
404
439
 
@@ -415,18 +450,18 @@ All component styles sit in `@layer component`. You can also write rules in a hi
415
450
  ### Overriding active/checked state colour
416
451
 
417
452
  Components with a checked or filled state (Checkbox, Radio, Slider, Progress, ProgressCircle)
418
- expose a component-scoped variable that falls back to the global `--color_active` token:
453
+ expose a component-scoped variable that falls back to the global `--bds-active` token:
419
454
 
420
455
  ```css
421
456
  /* Override the active colour for a single checkbox */
422
457
  .my-checkbox {
423
- --checkbox_color-active: var(--color_brand);
424
- --checkbox_color-on-active: var(--color_on-brand);
458
+ --checkbox_color-active: var(--bds-brand);
459
+ --checkbox_color-on-active: var(--bds-on-brand);
425
460
  }
426
461
 
427
462
  /* Override for all sliders in a section */
428
463
  .settings-panel {
429
- --slider_color-active: var(--color_important);
464
+ --slider_color-active: var(--bds-important);
430
465
  }
431
466
  ```
432
467
 
@@ -443,28 +478,28 @@ retheme all components at once:
443
478
  /* tokens.config.css — import after the design system CSS */
444
479
  @layer tokens.override {
445
480
  :root {
446
- --color_cta: var(--BASE__color--orange);
447
- --color_on-cta: var(--BASE__color--white);
448
- --color_interactive: var(--BASE__color--orange);
481
+ --bds-cta: var(--bds-BASE__color--orange);
482
+ --bds-on-cta: var(--bds-BASE__color--white);
483
+ --bds-interactive: var(--bds-BASE__color--orange);
449
484
  }
450
485
  }
451
486
  ```
452
487
 
453
488
  ### Active state tokens
454
489
 
455
- The `--color_active` family controls the checked/filled/selected colour across all form controls
490
+ The `--bds-active` family controls the checked/filled/selected colour across all form controls
456
491
  and progress indicators. Override it once to retheme checkboxes, radio buttons, sliders, progress
457
492
  bars, and the switch thumb simultaneously:
458
493
 
459
494
  ```css
460
495
  @layer tokens.override {
461
496
  :root {
462
- --color_active: var(--BASE__color--blue);
463
- --color_on-active: var(--BASE__color--white);
464
- --color_active--subtle: var(--BASE__color--blue--100); /* Switch track */
465
- --color_on-active--subtle: var(--BASE__color--blue--900);
466
- --color_active--strong: var(--BASE__color--blue--700); /* Switch thumb */
467
- --color_on-active--strong: var(--BASE__color--white);
497
+ --bds-active: var(--bds-BASE__color--blue);
498
+ --bds-on-active: var(--bds-BASE__color--white);
499
+ --bds-active--subtle: var(--bds-BASE__color--blue--100); /* Switch track */
500
+ --bds-on-active--subtle: var(--bds-BASE__color--blue--900);
501
+ --bds-active--strong: var(--bds-BASE__color--blue--700); /* Switch thumb */
502
+ --bds-on-active--strong: var(--bds-BASE__color--white);
468
503
  }
469
504
  }
470
505
  ```
@@ -480,7 +515,7 @@ pnpm build # compile to dist/
480
515
  pnpm typecheck # TypeScript check (library code only)
481
516
  pnpm lint # ESLint
482
517
  pnpm lint:css # Stylelint
483
- pnpm test # Vitest — 329 tests
518
+ pnpm test # Vitest — 364 tests
484
519
  pnpm mcp:start # Start the MCP server locally (http://localhost:3001/api/mcp)
485
520
  pnpm storybook # Storybook dev server on port 6006
486
521
  ```