@boostdev/design-system-components 2.16.0 → 2.17.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 (48) hide show
  1. package/AGENTS.md +3 -1
  2. package/dist/client.cjs +52 -52
  3. package/dist/client.css +637 -633
  4. package/dist/client.js +52 -52
  5. package/dist/index.cjs +52 -52
  6. package/dist/index.css +637 -633
  7. package/dist/index.js +52 -52
  8. package/dist/web-components/{chunk-SYNLFKD3.js → chunk-3LQKFSMR.js} +6 -0
  9. package/dist/web-components/{chunk-RZH5IVB5.js → chunk-5ATTKUCP.js} +2 -2
  10. package/dist/web-components/{chunk-BPYKZVDK.js → chunk-SJLMW2VR.js} +2 -2
  11. package/dist/web-components/{chunk-2MJTO2IW.js → chunk-WWWJCSXN.js} +2 -2
  12. package/dist/web-components/index.js +4 -4
  13. package/dist/web-components/ui/bds-alert.js +1 -1
  14. package/dist/web-components/ui/bds-badge.js +1 -1
  15. package/dist/web-components/ui/bds-notification-banner.js +1 -1
  16. package/dist/web-components/ui/bds-rating.js +1 -1
  17. package/package.json +1 -1
  18. package/src/components/interaction/Rating/Rating.mdx +4 -1
  19. package/src/components/interaction/Rating/Rating.module.css +9 -0
  20. package/src/components/interaction/Rating/Rating.spec.tsx +9 -0
  21. package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.mdx +1 -1
  22. package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.module.css +1 -1
  23. package/src/components/interaction/form/CheckboxGroup/CheckboxGroup.spec.tsx +5 -0
  24. package/src/components/interaction/form/RadioGroup/RadioGroup.mdx +1 -1
  25. package/src/components/interaction/form/RadioGroup/RadioGroup.module.css +1 -1
  26. package/src/components/interaction/form/RadioGroup/RadioGroup.spec.tsx +5 -0
  27. package/src/components/ui/Alert/Alert.mdx +1 -1
  28. package/src/components/ui/Alert/Alert.module.css +2 -2
  29. package/src/components/ui/Alert/Alert.spec.tsx +6 -0
  30. package/src/components/ui/Badge/Badge.mdx +1 -1
  31. package/src/components/ui/Badge/Badge.module.css +2 -2
  32. package/src/components/ui/Badge/Badge.spec.tsx +8 -0
  33. package/src/components/ui/NotificationBanner/NotificationBanner.mdx +13 -1
  34. package/src/components/ui/NotificationBanner/NotificationBanner.module.css +2 -2
  35. package/src/components/ui/NotificationBanner/NotificationBanner.spec.tsx +6 -0
  36. package/src/test/token-contract.spec.ts +1 -0
  37. package/src/web-components/ui/BdsAlert.mdx +1 -0
  38. package/src/web-components/ui/BdsBadge.mdx +1 -0
  39. package/src/web-components/ui/BdsNotificationBanner.mdx +1 -1
  40. package/src/web-components/ui/BdsRating.mdx +4 -1
  41. package/src/web-components/ui/bds-alert.spec.ts +7 -0
  42. package/src/web-components/ui/bds-alert.ts +2 -2
  43. package/src/web-components/ui/bds-badge.spec.ts +6 -0
  44. package/src/web-components/ui/bds-badge.ts +2 -2
  45. package/src/web-components/ui/bds-notification-banner.spec.ts +7 -0
  46. package/src/web-components/ui/bds-notification-banner.ts +2 -2
  47. package/src/web-components/ui/bds-rating.spec.ts +7 -0
  48. package/src/web-components/ui/bds-rating.ts +6 -0
@@ -109,7 +109,7 @@ import {
109
109
  } from "./chunk-7ZOJ7N4E.js";
110
110
  import {
111
111
  BdsRating
112
- } from "./chunk-SYNLFKD3.js";
112
+ } from "./chunk-3LQKFSMR.js";
113
113
  import {
114
114
  BdsSectionHeader
115
115
  } from "./chunk-DGOCPKHI.js";
@@ -158,17 +158,17 @@ import {
158
158
  } from "./chunk-AIBOHNDU.js";
159
159
  import {
160
160
  BdsNotificationBanner
161
- } from "./chunk-2MJTO2IW.js";
161
+ } from "./chunk-WWWJCSXN.js";
162
162
  import "./chunk-7VXRMCAL.js";
163
163
  import {
164
164
  BdsAlert
165
- } from "./chunk-RZH5IVB5.js";
165
+ } from "./chunk-5ATTKUCP.js";
166
166
  import {
167
167
  BdsAvatar
168
168
  } from "./chunk-IKAJLROF.js";
169
169
  import {
170
170
  BdsBadge
171
- } from "./chunk-BPYKZVDK.js";
171
+ } from "./chunk-SJLMW2VR.js";
172
172
  import {
173
173
  BdsBreadcrumb
174
174
  } from "./chunk-62NK3ZSC.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  BdsAlert
3
- } from "../chunk-RZH5IVB5.js";
3
+ } from "../chunk-5ATTKUCP.js";
4
4
  import "../chunk-LGEZYFUU.js";
5
5
  export {
6
6
  BdsAlert
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  BdsBadge
3
- } from "../chunk-BPYKZVDK.js";
3
+ } from "../chunk-SJLMW2VR.js";
4
4
  import "../chunk-LGEZYFUU.js";
5
5
  export {
6
6
  BdsBadge
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  BdsNotificationBanner
3
- } from "../chunk-2MJTO2IW.js";
3
+ } from "../chunk-WWWJCSXN.js";
4
4
  import "../chunk-LGEZYFUU.js";
5
5
  export {
6
6
  BdsNotificationBanner
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  BdsRating
3
- } from "../chunk-SYNLFKD3.js";
3
+ } from "../chunk-3LQKFSMR.js";
4
4
  import "../chunk-LGEZYFUU.js";
5
5
  export {
6
6
  BdsRating
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@boostdev/design-system-components",
3
- "version": "2.16.0",
3
+ "version": "2.17.0",
4
4
  "description": "BoostDev React component library: accessible, token-driven components built on @boostdev/design-system-foundation",
5
5
  "keywords": [
6
6
  "React",
@@ -40,8 +40,11 @@ Read-only star rating display. Use to show an existing score; for user input, co
40
40
  <tr><th>Variable</th><th>Default</th><th>Description</th></tr>
41
41
  </thead>
42
42
  <tbody>
43
- <tr><td>`--rating_color`</td><td>`var(--bds-color_bg)`</td><td>Empty star colour</td></tr>
43
+ <tr><td>`--rating_color`</td><td>`var(--bds-color_bg)`</td><td>Empty star fill</td></tr>
44
44
  <tr><td>`--rating_color--filled`</td><td>`var(--bds-color_warning)`</td><td>Filled star colour</td></tr>
45
+ <tr><td>`--rating_stroke-color`</td><td>`var(--bds-color_on-bg--as-surface)`</td><td>Empty star outline, a non-text mark (falls back to `--bds-color_on-bg--border`, then `--bds-color_on-bg`, on foundations before 2.3.0)</td></tr>
46
+ <tr><td>`--rating_stroke-color--filled`</td><td>`currentcolor`</td><td>Filled star outline, the filled colour by default so both kinds keep the same size</td></tr>
47
+ <tr><td>`--rating_stroke-width`</td><td>`var(--bdc-outline_width)`</td><td>Outline width, in the star's 24-unit viewBox</td></tr>
45
48
  </tbody>
46
49
  </table>
47
50
 
@@ -5,12 +5,21 @@
5
5
  color: var(--rating_color, var(--bds-color_bg));
6
6
  }
7
7
 
8
+ /* Empty stars are outlined, filled stars solid: the two differ in shape, not
9
+ only in hue, because the as-surface grey and the warning fill are close in
10
+ lightness. The outline is a non-text mark, so it takes the as-surface
11
+ member (>= 3:1 on the page). Filled stars stroke in their own colour so
12
+ both kinds keep the same size. */
8
13
  .star {
9
14
  inline-size: 1.5em;
10
15
  block-size: 1.5em;
16
+ stroke: var(--rating_stroke-color, var(--bds-color_on-bg--as-surface, var(--bds-color_on-bg--border, var(--bds-color_on-bg))));
17
+ stroke-width: var(--rating_stroke-width, var(--bdc-outline_width));
18
+ stroke-linejoin: round;
11
19
  }
12
20
 
13
21
  .--filled {
14
22
  color: var(--rating_color--filled, var(--bds-color_warning));
23
+ stroke: var(--rating_stroke-color--filled, currentcolor);
15
24
  }
16
25
  }
@@ -1,3 +1,5 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { resolve } from 'node:path';
1
3
  import { render, screen } from '@testing-library/react';
2
4
  import { Rating } from './Rating';
3
5
 
@@ -27,4 +29,11 @@ describe('Rating', () => {
27
29
  render(<Rating value={3} className="custom" />);
28
30
  expect(screen.getByRole('img')).toHaveClass('custom');
29
31
  });
32
+
33
+ it('outlines empty stars with the as-surface mark colour and strokes filled stars in their own colour', () => {
34
+ const css = readFileSync(resolve(process.cwd(), 'src/components/interaction/Rating/Rating.module.css'), 'utf8');
35
+ expect(css).toMatch(/\.star \{[^}]*stroke:\s*var\(--rating_stroke-color,\s*var\(--bds-color_on-bg--as-surface,\s*var\(--bds-color_on-bg--border,\s*var\(--bds-color_on-bg\)\)\)\)/);
36
+ expect(css).toMatch(/\.star \{[^}]*stroke-width:\s*var\(--rating_stroke-width,\s*var\(--bdc-outline_width\)\)/);
37
+ expect(css).toMatch(/\.--filled \{[^}]*stroke:\s*var\(--rating_stroke-color--filled,\s*currentcolor\)/);
38
+ });
30
39
  });
@@ -46,7 +46,7 @@ All public override tokens. Set on the CheckboxGroup or any ancestor; they casca
46
46
  | `--checkboxGroup_items-gap` | `var(--bds-space_xs)` | Gap between the child checkboxes. |
47
47
  | `--checkboxGroup_legend-color` | `var(--bds-color_on-bg)` | Legend text colour. |
48
48
  | `--checkboxGroup_legend-font-family` | `var(--bds-font_family--body)` | Legend font family. |
49
- | `--checkboxGroup_legend-font-size` | `var(--bds-font_size--body--s)` | Legend font size. |
49
+ | `--checkboxGroup_legend-font-size` | `var(--bds-font_size--body)` | Legend font size, the same as the labels of the other fields. |
50
50
  | `--checkboxGroup_legend-font-weight` | `var(--bds-font_weight--medium)` | Legend font weight. |
51
51
  | `--checkboxGroup_legend-gap` | `var(--bds-space_xs)` | Space below the legend before the items. |
52
52
  | `--checkboxGroup_required-color` | `var(--bds-color_error)` | Colour of the visible `*` required marker. |
@@ -10,7 +10,7 @@
10
10
 
11
11
  .legend {
12
12
  font-family: var(--checkboxGroup_legend-font-family, var(--bds-font_family--body));
13
- font-size: var(--checkboxGroup_legend-font-size, var(--bds-font_size--body--s));
13
+ font-size: var(--checkboxGroup_legend-font-size, var(--bds-font_size--body));
14
14
  font-weight: var(--checkboxGroup_legend-font-weight, var(--bds-font_weight--medium));
15
15
  color: var(--checkboxGroup_legend-color, var(--bds-color_on-bg));
16
16
  padding: 0;
@@ -136,4 +136,9 @@ describe('CheckboxGroup', () => {
136
136
  );
137
137
  expect(screen.getByRole('group', { name: 'Pick' }).className).not.toContain('groupError');
138
138
  });
139
+
140
+ it('sizes the legend like the labels of the other fields', () => {
141
+ const css = readFileSync(resolve(process.cwd(), 'src/components/interaction/form/CheckboxGroup/CheckboxGroup.module.css'), 'utf8');
142
+ expect(css).toMatch(/\.legend \{[^}]*font-size:\s*var\(--checkboxGroup_legend-font-size,\s*var\(--bds-font_size--body\)\)/);
143
+ });
139
144
  });
@@ -46,7 +46,7 @@ All public override tokens. Set on the RadioGroup or any ancestor; they cascade.
46
46
  | `--radioGroup_items-gap` | `var(--bds-space_xs)` | Gap between the child radios. |
47
47
  | `--radioGroup_legend-color` | `var(--bds-color_on-bg)` | Legend text colour. |
48
48
  | `--radioGroup_legend-font-family` | `var(--bds-font_family--body)` | Legend font family. |
49
- | `--radioGroup_legend-font-size` | `var(--bds-font_size--body--s)` | Legend font size. |
49
+ | `--radioGroup_legend-font-size` | `var(--bds-font_size--body)` | Legend font size, the same as the labels of the other fields. |
50
50
  | `--radioGroup_legend-font-weight` | `var(--bds-font_weight--medium)` | Legend font weight. |
51
51
  | `--radioGroup_legend-gap` | `var(--bds-space_xs)` | Space below the legend before the items. |
52
52
  | `--radioGroup_required-color` | `var(--bds-color_error)` | Colour of the visible `*` required marker. |
@@ -10,7 +10,7 @@
10
10
 
11
11
  .legend {
12
12
  font-family: var(--radioGroup_legend-font-family, var(--bds-font_family--body));
13
- font-size: var(--radioGroup_legend-font-size, var(--bds-font_size--body--s));
13
+ font-size: var(--radioGroup_legend-font-size, var(--bds-font_size--body));
14
14
  font-weight: var(--radioGroup_legend-font-weight, var(--bds-font_weight--medium));
15
15
  color: var(--radioGroup_legend-color, var(--bds-color_on-bg));
16
16
  padding: 0;
@@ -124,4 +124,9 @@ describe('RadioGroup', () => {
124
124
  );
125
125
  expect(screen.getByRole('group', { name: 'Pick' }).className).not.toContain('groupError');
126
126
  });
127
+
128
+ it('sizes the legend like the labels of the other fields', () => {
129
+ const css = readFileSync(resolve(process.cwd(), 'src/components/interaction/form/RadioGroup/RadioGroup.module.css'), 'utf8');
130
+ expect(css).toMatch(/\.legend \{[^}]*font-size:\s*var\(--radioGroup_legend-font-size,\s*var\(--bds-font_size--body\)\)/);
131
+ });
127
132
  });
@@ -116,7 +116,7 @@ Each variant's actual default resolution:
116
116
  <tr><td>`info`</td><td>`--bds-color_blue--subtle`</td><td>`--bds-color_on-blue--subtle`</td><td>`--bds-color_blue`</td></tr>
117
117
  <tr><td>`success`</td><td>`--bds-color_success--subtle`</td><td>`--bds-color_on-success--subtle`</td><td>`--bds-color_success`</td></tr>
118
118
  <tr><td>`warning`</td><td>`--bds-color_orange--subtle`</td><td>`--bds-color_on-orange--subtle`</td><td>`--bds-color_warning`</td></tr>
119
- <tr><td>`error`</td><td>relative-colour mix of `--bds-color_error` (12% alpha)</td><td>`--bds-color_on-bg`</td><td>`--bds-color_error`</td></tr>
119
+ <tr><td>`error`</td><td>`--bds-color_error--subtle`</td><td>`--bds-color_on-error--subtle`</td><td>`--bds-color_error`</td></tr>
120
120
  </tbody>
121
121
  </table>
122
122
 
@@ -40,8 +40,8 @@
40
40
  }
41
41
 
42
42
  .--variant_error {
43
- --alert_bg--variant: var(--alert_bg--error, rgb(from var(--bds-color_error) r g b / 12%));
44
- --alert_text--variant: var(--alert_text--error, var(--bds-color_on-bg));
43
+ --alert_bg--variant: var(--alert_bg--error, var(--bds-color_error--subtle));
44
+ --alert_text--variant: var(--alert_text--error, var(--bds-color_on-error--subtle));
45
45
  --alert_border--variant: var(--alert_border--error, var(--bds-color_error));
46
46
  }
47
47
 
@@ -101,4 +101,10 @@ describe('Alert', () => {
101
101
  expect(cssSource).toContain(`--alert_accent--${v}`);
102
102
  });
103
103
  });
104
+
105
+ it('paints the error variant with the error subtle pair, like the other variants', () => {
106
+ expect(cssSource).toMatch(/\.--variant_error \{[^}]*--alert_bg--variant:\s*var\(--alert_bg--error,\s*var\(--bds-color_error--subtle\)\)/);
107
+ expect(cssSource).toMatch(/\.--variant_error \{[^}]*--alert_text--variant:\s*var\(--alert_text--error,\s*var\(--bds-color_on-error--subtle\)\)/);
108
+ expect(cssSource).not.toContain('rgb(from var(--bds-color_error)');
109
+ });
104
110
  });
@@ -75,7 +75,7 @@ The override surface is **layered**. Setting a public token on the badge (or any
75
75
  </tbody>
76
76
  </table>
77
77
 
78
- Defaults resolve to foundation tokens per variant: `success`/`error`/`warning` map directly to `--bds-color_{variant}` / `--bds-color_on-{variant}`. `primary` maps to `--bds-color_interactive` / `--bds-color_on-interactive`, and `secondary` maps to `--bds-color_bg` / `--bds-color_on-bg` — neither follows the generic `{variant}` naming.
78
+ Defaults resolve to foundation tokens per variant: `success`/`error`/`warning` map directly to `--bds-color_{variant}` / `--bds-color_on-{variant}`. `primary` maps to `--bds-color_interactive` / `--bds-color_on-interactive`, and `secondary` maps to the neutral `--bds-color_grey` / `--bds-color_on-grey`, so it has a solid surface like the other variants. Neither follows the generic `{variant}` naming.
79
79
 
80
80
 
81
81
  ## Accessibility
@@ -22,8 +22,8 @@
22
22
  }
23
23
 
24
24
  .--variant_secondary {
25
- --badge_bg--variant: var(--badge_bg--secondary, var(--bds-color_bg));
26
- --badge_text--variant: var(--badge_text--secondary, var(--bds-color_on-bg));
25
+ --badge_bg--variant: var(--badge_bg--secondary, var(--bds-color_grey));
26
+ --badge_text--variant: var(--badge_text--secondary, var(--bds-color_on-grey));
27
27
  }
28
28
 
29
29
  .--variant_success {
@@ -1,3 +1,5 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { resolve } from 'node:path';
1
3
  import { render, screen } from '@testing-library/react';
2
4
  import { Badge } from './Badge';
3
5
 
@@ -16,4 +18,10 @@ describe('Badge', () => {
16
18
  render(<Badge className="custom">Test</Badge>);
17
19
  expect(screen.getByText('Test')).toHaveClass('custom');
18
20
  });
21
+
22
+ it('gives the secondary variant a solid neutral surface through its own hooks', () => {
23
+ const css = readFileSync(resolve(process.cwd(), 'src/components/ui/Badge/Badge.module.css'), 'utf8');
24
+ expect(css).toMatch(/\.--variant_secondary \{[^}]*--badge_bg--variant:\s*var\(--badge_bg--secondary,\s*var\(--bds-color_grey\)\)/);
25
+ expect(css).toMatch(/\.--variant_secondary \{[^}]*--badge_text--variant:\s*var\(--badge_text--secondary,\s*var\(--bds-color_on-grey\)\)/);
26
+ });
19
27
  });
@@ -90,7 +90,19 @@ The override surface is **layered**. Setting a public token on the banner (or an
90
90
  </tbody>
91
91
  </table>
92
92
 
93
- Defaults resolve to the corresponding foundation tokens.
93
+ Each variant's actual default resolution:
94
+
95
+ <table>
96
+ <thead>
97
+ <tr><th>Variant</th><th>Background default</th><th>Text default</th><th>Border default</th></tr>
98
+ </thead>
99
+ <tbody>
100
+ <tr><td>`info`</td><td>`--bds-color_blue--subtle`</td><td>`--bds-color_on-blue--subtle`</td><td>`--bds-color_blue`</td></tr>
101
+ <tr><td>`success`</td><td>`--bds-color_success--subtle`</td><td>`--bds-color_on-success--subtle`</td><td>`--bds-color_success`</td></tr>
102
+ <tr><td>`warning`</td><td>`--bds-color_orange--subtle`</td><td>`--bds-color_on-orange--subtle`</td><td>`--bds-color_warning`</td></tr>
103
+ <tr><td>`error`</td><td>`--bds-color_error--subtle`</td><td>`--bds-color_on-error--subtle`</td><td>`--bds-color_error`</td></tr>
104
+ </tbody>
105
+ </table>
94
106
 
95
107
 
96
108
  ## Accessibility
@@ -34,8 +34,8 @@
34
34
  }
35
35
 
36
36
  .--variant_error {
37
- --banner_bg--variant: var(--banner_bg--error, rgb(from var(--bds-color_error) r g b / 12%));
38
- --banner_text--variant: var(--banner_text--error, var(--bds-color_on-bg));
37
+ --banner_bg--variant: var(--banner_bg--error, var(--bds-color_error--subtle));
38
+ --banner_text--variant: var(--banner_text--error, var(--bds-color_on-error--subtle));
39
39
  --banner_border--variant: var(--banner_border--error, var(--bds-color_error));
40
40
  }
41
41
 
@@ -88,4 +88,10 @@ describe('NotificationBanner', () => {
88
88
  expect(cssSource).toContain(`--banner_accent--${v}`);
89
89
  });
90
90
  });
91
+
92
+ it('paints the error variant with the error subtle pair, like the other variants', () => {
93
+ expect(cssSource).toMatch(/\.--variant_error \{[^}]*--banner_bg--variant:\s*var\(--banner_bg--error,\s*var\(--bds-color_error--subtle\)\)/);
94
+ expect(cssSource).toMatch(/\.--variant_error \{[^}]*--banner_text--variant:\s*var\(--banner_text--error,\s*var\(--bds-color_on-error--subtle\)\)/);
95
+ expect(cssSource).not.toContain('rgb(from var(--bds-color_error)');
96
+ });
91
97
  });
@@ -96,6 +96,7 @@ const NON_TEXT_MARKS: { file: string; rule: string }[] = [
96
96
  { file: 'components/ui/Accordion/Accordion.module.css', rule: '.item' },
97
97
  { file: 'components/ui/Tabs/Tabs.module.css', rule: '.tabList' },
98
98
  { file: 'components/ui/Table/Table.module.css', rule: '.th' },
99
+ { file: 'components/interaction/Rating/Rating.module.css', rule: '.star' },
99
100
  ];
100
101
 
101
102
  describe('non-text marks use the as-surface member of the colour set', () => {
@@ -67,6 +67,7 @@ import '@boostdev/design-system-components/web-components';
67
67
  | Property | Default | Description |
68
68
  |----------|---------|-------------|
69
69
  | `--alert_bg` / `--alert_text` / `--alert_border` | per variant | Colours for all variants. Per-variant forms: `--alert_bg--info`, `--alert_text--info`, `--alert_border--info` (and `success`, `warning`, `error`). |
70
+ | `--alert_bg--error` / `--alert_text--error` / `--alert_border--error` | `var(--bds-color_error--subtle)` / `var(--bds-color_on-error--subtle)` / `var(--bds-color_error)` | Error variant colours, the subtle pair like the other variants |
70
71
  | `--alert_border-width` | `var(--bds-space_s)` (`3px` with `appearance="gradient"`) | Width of the inline-start accent line |
71
72
  | `--alert_gradient` | `linear-gradient(100deg, transparent 35%, var(--bds-color_bg--strong, var(--bds-color_bg)) 100%)` | Gradient over the variant background, `appearance="gradient"` only |
72
73
  | `--alert_shadow` | `var(--bds-shadow_s)` | Box shadow, `appearance="gradient"` only |
@@ -57,6 +57,7 @@ import '@boostdev/design-system-components/web-components';
57
57
  |----------|-------------|
58
58
  | `--badge_bg` | Badge background colour |
59
59
  | `--badge_text` | Badge text colour |
60
+ | `--badge_bg--secondary` / `--badge_text--secondary` | `secondary` variant colours (defaults `--bds-color_grey`, `--bds-color_on-grey`). The other variants have the same pair: `--badge_bg--{variant}` / `--badge_text--{variant}`. |
60
61
  | `--badge_font-size` | Font size |
61
62
  | `--badge_radius` | Border radius |
62
63
 
@@ -78,7 +78,7 @@ import '@boostdev/design-system-components/web-components';
78
78
  | `--banner_bg--info` / `--banner_text--info` / `--banner_border--info` | Info variant colours |
79
79
  | `--banner_bg--success` / `--banner_text--success` / `--banner_border--success` | Success variant colours |
80
80
  | `--banner_bg--warning` / `--banner_text--warning` / `--banner_border--warning` | Warning variant colours |
81
- | `--banner_bg--error` / `--banner_text--error` / `--banner_border--error` | Error variant colours |
81
+ | `--banner_bg--error` / `--banner_text--error` / `--banner_border--error` | Error variant colours (defaults `--bds-color_error--subtle`, `--bds-color_on-error--subtle`, `--bds-color_error`) |
82
82
  | `--banner_border-width` | Width of the block-end accent line (default `3px`) |
83
83
  | `--banner_gradient` | Gradient over the variant background, `appearance="gradient"` only (default `linear-gradient(100deg, transparent 35%, var(--bds-color_bg--strong, var(--bds-color_bg)) 100%)`) |
84
84
  | `--banner_shadow` | Box shadow, `appearance="gradient"` only (default `var(--bds-shadow_s)`) |
@@ -59,8 +59,11 @@ import '@boostdev/design-system-components/web-components';
59
59
 
60
60
  | Variable | Default | Description |
61
61
  |----------|---------|--------------|
62
- | `--rating_color` | `var(--bds-color_bg)` | Colour of unfilled stars |
62
+ | `--rating_color` | `var(--bds-color_bg)` | Fill of unfilled stars |
63
63
  | `--rating_color--filled` | `var(--bds-color_warning)` | Colour of filled stars |
64
+ | `--rating_stroke-color` | `var(--bds-color_on-bg--as-surface)` | Outline of unfilled stars, a non-text mark (falls back to `--bds-color_on-bg--border`, then `--bds-color_on-bg`, on foundations before 2.3.0) |
65
+ | `--rating_stroke-color--filled` | `currentcolor` | Outline of filled stars, the filled colour by default so both kinds keep the same size |
66
+ | `--rating_stroke-width` | `var(--bdc-outline_width)` | Outline width, in the star's 24-unit viewBox |
64
67
 
65
68
  ## Accessibility
66
69
 
@@ -148,4 +148,11 @@ describe('bds-alert', () => {
148
148
  expect(styles).toContain(`--alert_accent--${v}`);
149
149
  });
150
150
  });
151
+
152
+ it('paints the error variant with the error subtle pair, matching the React counterpart', () => {
153
+ const styles = String(BdsAlert.styles);
154
+ expect(styles).toMatch(/--alert_bg--variant:\s*var\(--alert_bg--error,\s*var\(--bds-color_error--subtle\)\)/);
155
+ expect(styles).toMatch(/--alert_text--variant:\s*var\(--alert_text--error,\s*var\(--bds-color_on-error--subtle\)\)/);
156
+ expect(styles).not.toContain('rgb(from var(--bds-color_error)');
157
+ });
151
158
  });
@@ -91,8 +91,8 @@ export class BdsAlert extends LitElement {
91
91
  }
92
92
 
93
93
  :host([variant='error']) .alert {
94
- --alert_bg--variant: var(--alert_bg--error, rgb(from var(--bds-color_error) r g b / 12%));
95
- --alert_text--variant: var(--alert_text--error, var(--bds-color_on-bg));
94
+ --alert_bg--variant: var(--alert_bg--error, var(--bds-color_error--subtle));
95
+ --alert_text--variant: var(--alert_text--error, var(--bds-color_on-error--subtle));
96
96
  --alert_border--variant: var(--alert_border--error, var(--bds-color_error));
97
97
  }
98
98
 
@@ -53,4 +53,10 @@ describe('bds-badge', () => {
53
53
  const cssText = BdsBadge.styles.cssText;
54
54
  expect(cssText).toMatch(/border-radius:\s*var\(--badge_radius,\s*var\(--bds-border_radius--full\)\)/);
55
55
  });
56
+
57
+ it('gives the secondary variant a solid neutral surface, matching the React counterpart', () => {
58
+ const cssText = BdsBadge.styles.cssText;
59
+ expect(cssText).toMatch(/:host\(\[variant='secondary'\]\) \.badge \{[^}]*--badge_bg--variant:\s*var\(--badge_bg--secondary,\s*var\(--bds-color_grey\)\)/);
60
+ expect(cssText).toMatch(/:host\(\[variant='secondary'\]\) \.badge \{[^}]*--badge_text--variant:\s*var\(--badge_text--secondary,\s*var\(--bds-color_on-grey\)\)/);
61
+ });
56
62
  });
@@ -54,8 +54,8 @@ export class BdsBadge extends LitElement {
54
54
  }
55
55
 
56
56
  :host([variant='secondary']) .badge {
57
- --badge_bg--variant: var(--badge_bg--secondary, var(--bds-color_bg));
58
- --badge_text--variant: var(--badge_text--secondary, var(--bds-color_on-bg));
57
+ --badge_bg--variant: var(--badge_bg--secondary, var(--bds-color_grey));
58
+ --badge_text--variant: var(--badge_text--secondary, var(--bds-color_on-grey));
59
59
  }
60
60
 
61
61
  :host([variant='success']) .badge {
@@ -137,4 +137,11 @@ describe('bds-notification-banner', () => {
137
137
  expect(plain.shadowRoot!.querySelector('.icon')!.classList.contains('has-content')).toBe(false);
138
138
  cleanup(plain);
139
139
  });
140
+
141
+ it('paints the error variant with the error subtle pair, matching the React counterpart', () => {
142
+ const styles = String(BdsNotificationBanner.styles);
143
+ expect(styles).toMatch(/--banner_bg--variant:\s*var\(--banner_bg--error,\s*var\(--bds-color_error--subtle\)\)/);
144
+ expect(styles).toMatch(/--banner_text--variant:\s*var\(--banner_text--error,\s*var\(--bds-color_on-error--subtle\)\)/);
145
+ expect(styles).not.toContain('rgb(from var(--bds-color_error)');
146
+ });
140
147
  });
@@ -75,8 +75,8 @@ export class BdsNotificationBanner extends LitElement {
75
75
  }
76
76
 
77
77
  :host([variant='error']) .banner {
78
- --banner_bg--variant: var(--banner_bg--error, rgb(from var(--bds-color_error) r g b / 12%));
79
- --banner_text--variant: var(--banner_text--error, var(--bds-color_on-bg));
78
+ --banner_bg--variant: var(--banner_bg--error, var(--bds-color_error--subtle));
79
+ --banner_text--variant: var(--banner_text--error, var(--bds-color_on-error--subtle));
80
80
  --banner_border--variant: var(--banner_border--error, var(--bds-color_error));
81
81
  }
82
82
 
@@ -73,4 +73,11 @@ describe('bds-rating', () => {
73
73
  expect(cssText).toMatch(/color:\s*var\(--rating_color,\s*var\(--bds-color_bg\)\)/);
74
74
  expect(cssText).toMatch(/color:\s*var\(--rating_color--filled,\s*var\(--bds-color_warning\)\)/);
75
75
  });
76
+
77
+ it('outlines empty stars through the same stroke hooks as the React counterpart', () => {
78
+ const cssText = BdsRating.styles.cssText;
79
+ expect(cssText).toMatch(/\.star \{[^}]*stroke:\s*var\(--rating_stroke-color,\s*var\(--bds-color_on-bg--as-surface,\s*var\(--bds-color_on-bg--border,\s*var\(--bds-color_on-bg\)\)\)\)/);
80
+ expect(cssText).toMatch(/\.star \{[^}]*stroke-width:\s*var\(--rating_stroke-width,\s*var\(--bdc-outline_width\)\)/);
81
+ expect(cssText).toMatch(/\.star\.--filled \{[^}]*stroke:\s*var\(--rating_stroke-color--filled,\s*currentcolor\)/);
82
+ });
76
83
  });
@@ -35,13 +35,19 @@ export class BdsRating extends LitElement {
35
35
  color: var(--rating_color, var(--bds-color_bg));
36
36
  }
37
37
 
38
+ /* Empty stars are outlined, filled stars solid, matching the React
39
+ counterpart: shape tells them apart, not only hue. */
38
40
  .star {
39
41
  inline-size: 1.5em;
40
42
  block-size: 1.5em;
43
+ stroke: var(--rating_stroke-color, var(--bds-color_on-bg--as-surface, var(--bds-color_on-bg--border, var(--bds-color_on-bg))));
44
+ stroke-width: var(--rating_stroke-width, var(--bdc-outline_width));
45
+ stroke-linejoin: round;
41
46
  }
42
47
 
43
48
  .star.--filled {
44
49
  color: var(--rating_color--filled, var(--bds-color_warning));
50
+ stroke: var(--rating_stroke-color--filled, currentcolor);
45
51
  }
46
52
  `;
47
53