@boostdev/design-system-components 2.5.1 → 2.7.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 (60) hide show
  1. package/dist/client.cjs +257 -219
  2. package/dist/client.css +673 -626
  3. package/dist/client.d.cts +27 -1
  4. package/dist/client.d.ts +27 -1
  5. package/dist/client.js +220 -183
  6. package/dist/index.cjs +257 -219
  7. package/dist/index.css +673 -626
  8. package/dist/index.d.cts +27 -1
  9. package/dist/index.d.ts +27 -1
  10. package/dist/index.js +220 -183
  11. package/dist/web-components/{chunk-N3TN6WCH.js → chunk-GER5UJOF.js} +22 -15
  12. package/dist/web-components/chunk-QWPACK5L.js +72 -0
  13. package/dist/web-components/{chunk-YRXCVKHV.js → chunk-RTOS7LLG.js} +9 -7
  14. package/dist/web-components/{chunk-BX3IPVOB.js → chunk-ZNKEZIYE.js} +20 -16
  15. package/dist/web-components/index.d.ts +56 -1
  16. package/dist/web-components/index.js +121 -4
  17. package/dist/web-components/interaction/bds-button.js +1 -1
  18. package/dist/web-components/ui/bds-alert.js +1 -1
  19. package/dist/web-components/ui/bds-badge.js +1 -1
  20. package/dist/web-components/ui/bds-card.js +1 -1
  21. package/package.json +3 -2
  22. package/src/components/interaction/Button/Button.mdx +87 -13
  23. package/src/components/interaction/Button/Button.module.css +22 -17
  24. package/src/components/interaction/Toast/Toast.mdx +22 -3
  25. package/src/components/interaction/Toast/Toast.module.css +13 -10
  26. package/src/components/interaction/form/FieldGroup/FieldGroup.mdx +113 -0
  27. package/src/components/interaction/form/FieldGroup/FieldGroup.module.css +96 -0
  28. package/src/components/interaction/form/FieldGroup/FieldGroup.spec.tsx +196 -0
  29. package/src/components/interaction/form/FieldGroup/FieldGroup.stories.tsx +99 -0
  30. package/src/components/interaction/form/FieldGroup/FieldGroup.tsx +64 -0
  31. package/src/components/interaction/form/FieldGroup/index.ts +2 -0
  32. package/src/components/interaction/form/atoms/Message.module.css +4 -0
  33. package/src/components/layout/Card/Card.mdx +20 -8
  34. package/src/components/layout/Card/Card.module.css +5 -3
  35. package/src/components/ui/Alert/Alert.mdx +39 -5
  36. package/src/components/ui/Alert/Alert.module.css +21 -15
  37. package/src/components/ui/Badge/Badge.mdx +23 -3
  38. package/src/components/ui/Badge/Badge.module.css +15 -12
  39. package/src/components/ui/Link/Link.mdx +20 -2
  40. package/src/components/ui/Link/Link.module.css +12 -8
  41. package/src/components/ui/NotificationBanner/NotificationBanner.mdx +25 -6
  42. package/src/components/ui/NotificationBanner/NotificationBanner.module.css +18 -15
  43. package/src/components/ui/Pagination/Pagination.mdx +22 -9
  44. package/src/components/ui/Pagination/Pagination.module.css +10 -8
  45. package/src/components/ui/Tabs/Tabs.mdx +20 -5
  46. package/src/components/ui/Tabs/Tabs.module.css +8 -5
  47. package/src/index.ts +2 -0
  48. package/src/web-components/index.ts +2 -0
  49. package/src/web-components/interaction/bds-button.ts +22 -15
  50. package/src/web-components/interaction/form/BdsFieldGroup.mdx +67 -0
  51. package/src/web-components/interaction/form/BdsFieldGroup.stories.tsx +110 -0
  52. package/src/web-components/interaction/form/bds-checkbox-group.ts +1 -0
  53. package/src/web-components/interaction/form/bds-field-group.spec.ts +64 -0
  54. package/src/web-components/interaction/form/bds-field-group.ts +157 -0
  55. package/src/web-components/interaction/form/bds-form-input.ts +1 -0
  56. package/src/web-components/interaction/form/bds-radio-group.ts +1 -0
  57. package/src/web-components/ui/bds-alert.ts +20 -16
  58. package/src/web-components/ui/bds-badge.ts +16 -13
  59. package/src/web-components/ui/bds-card.ts +9 -7
  60. package/dist/web-components/chunk-OHUTLSIQ.js +0 -69
@@ -0,0 +1,64 @@
1
+ import { Children, CSSProperties, FieldsetHTMLAttributes, ReactNode } from 'react';
2
+ import { cn } from '@boostdev/design-system-foundation';
3
+ import css from './FieldGroup.module.css';
4
+ import type { WithClassName } from '../../../../types';
5
+
6
+ /**
7
+ * Layout variants for FieldGroup.
8
+ *
9
+ * - `horizontal` (default) — fields flow into a row, each claiming at least
10
+ * `--fieldGroup_min-field-width`. When the container's inline-size is too
11
+ * narrow to fit the row, a CSS container query collapses the layout to a
12
+ * single column.
13
+ * - `vertical` — fields always stack one per row.
14
+ */
15
+ export type FieldGroupVariant = 'horizontal' | 'vertical';
16
+
17
+ export interface FieldGroupProps
18
+ extends WithClassName,
19
+ FieldsetHTMLAttributes<HTMLFieldSetElement> {
20
+ /** Layout direction. Defaults to `horizontal`. */
21
+ variant?: FieldGroupVariant;
22
+ /**
23
+ * Optional legend rendered above the fields. When omitted, set
24
+ * `aria-label` or `aria-labelledby` on the fieldset for accessibility.
25
+ */
26
+ legend?: ReactNode;
27
+ }
28
+
29
+ /**
30
+ * `FieldGroup` semantically groups related form fields under a single
31
+ * `<fieldset>` and lays them out either horizontally (with container-query
32
+ * fallback to vertical) or vertically.
33
+ */
34
+ export function FieldGroup({
35
+ variant = 'horizontal',
36
+ legend,
37
+ children,
38
+ className,
39
+ style,
40
+ ...rest
41
+ }: Readonly<FieldGroupProps>) {
42
+ // Surface the field count to CSS so the @container collapse threshold
43
+ // scales with the actual content. The CSS uses
44
+ // N * --fieldGroup_min-field-width + (N - 1) * --fieldGroup_gap
45
+ // which is exactly the inline-size required to lay all fields out at
46
+ // their minimum width with the configured gap. When the FieldGroup's own
47
+ // inline-size drops below that, the layout collapses to a single column.
48
+ const fieldCount = Children.count(children);
49
+ const styleWithCount = {
50
+ ...style,
51
+ '--fieldGroup_field-count': fieldCount,
52
+ } as CSSProperties;
53
+
54
+ return (
55
+ <fieldset
56
+ {...rest}
57
+ style={styleWithCount}
58
+ className={cn(css.fieldGroup, css[`--variant_${variant}`], className)}
59
+ >
60
+ {legend !== undefined && <legend className={css.legend}>{legend}</legend>}
61
+ <div className={css.fields}>{children}</div>
62
+ </fieldset>
63
+ );
64
+ }
@@ -0,0 +1,2 @@
1
+ export { FieldGroup } from './FieldGroup';
2
+ export type { FieldGroupProps, FieldGroupVariant } from './FieldGroup';
@@ -8,4 +8,8 @@
8
8
  .error {
9
9
  color: var(--bds-color_error_on-bg);
10
10
  }
11
+
12
+ .hint {
13
+ font-style: italic;
14
+ }
11
15
  }
@@ -43,23 +43,35 @@ Contained surface for grouping related content. Three visual variants provide di
43
43
 
44
44
  ## CSS variables
45
45
 
46
+ ### Card surface
46
47
 
47
48
  <table>
48
49
  <thead>
49
50
  <tr><th>Variable</th><th>Default</th><th>Description</th></tr>
50
51
  </thead>
51
52
  <tbody>
52
- <tr><td>`--card_color`</td><td>`var(--bds-color_bg)`</td><td>Card background colour</td></tr>
53
- <tr><td>`--card_on-color`</td><td>`var(--bds-color_on-bg)`</td><td>Card text colour</td></tr>
54
- <tr><td>`--card_padding`</td><td>varies by `padding` prop</td><td>Card padding (overrides the variant default)</td></tr>
55
- <tr><td>`--card_border`</td><td>`none`</td><td>Border (outlined variant)</td></tr>
56
- <tr><td>`--card_shadow--clickable-hover`</td><td>`var(--bds-shadow_xl)`</td><td>Box shadow on hover for clickable cards</td></tr>
57
- <tr><td>`--card_shadow--default-hover`</td><td>`var(--bds-shadow_m)`</td><td>Box shadow on hover for default variant</td></tr>
58
- <tr><td>`--card_shadow--elevated-hover`</td><td>`var(--bds-shadow_2xl)`</td><td>Box shadow on hover for elevated variant</td></tr>
59
- <tr><td>`--card_shadow--outlined-hover`</td><td>`var(--bds-shadow_s)`</td><td>Box shadow on hover for outlined variant</td></tr>
53
+ <tr><td>`--card_color`</td><td>`var(--bds-color_bg)`</td><td>Card background colour.</td></tr>
54
+ <tr><td>`--card_on-color`</td><td>`var(--bds-color_on-bg)`</td><td>Card text colour.</td></tr>
55
+ <tr><td>`--card_padding`</td><td>varies by `padding` prop</td><td>Card padding (overrides the prop default).</td></tr>
56
+ <tr><td>`--card_border`</td><td>`none`</td><td>Border (outlined variant).</td></tr>
60
57
  </tbody>
61
58
  </table>
62
59
 
60
+ ### Per-variant box-shadow (resting + hover)
61
+
62
+ <table>
63
+ <thead>
64
+ <tr><th>Variant</th><th>Resting shadow</th><th>Hover shadow</th></tr>
65
+ </thead>
66
+ <tbody>
67
+ <tr><td>`default`</td><td>`--card_shadow--default` (`var(--bds-shadow_s)`)</td><td>`--card_shadow--default-hover` (`var(--bds-shadow_m)`)</td></tr>
68
+ <tr><td>`elevated`</td><td>`--card_shadow--elevated` (`var(--bds-shadow_m)`)</td><td>`--card_shadow--elevated-hover` (`var(--bds-shadow_2xl)`)</td></tr>
69
+ <tr><td>`outlined`</td><td>`--card_shadow--outlined` (inset border + `var(--bds-shadow_s)`)</td><td>`--card_shadow--outlined-hover` (`var(--bds-shadow_s)`)</td></tr>
70
+ </tbody>
71
+ </table>
72
+
73
+ Plus `--card_shadow--clickable-hover` (`var(--bds-shadow_xl)`) for hover on any clickable card.
74
+
63
75
 
64
76
  ## Accessibility
65
77
 
@@ -7,19 +7,21 @@
7
7
  position: relative;
8
8
  }
9
9
 
10
+ /* Resting shadows — consumers can override per-variant via
11
+ --card_shadow--default / --card_shadow--elevated / --card_shadow--outlined. */
10
12
  .card.--default {
11
- box-shadow: var(--bds-shadow_s);
13
+ box-shadow: var(--card_shadow--default, var(--bds-shadow_s));
12
14
  }
13
15
 
14
16
  .card.--elevated {
15
- box-shadow: var(--bds-shadow_m);
17
+ box-shadow: var(--card_shadow--elevated, var(--bds-shadow_m));
16
18
  }
17
19
 
18
20
  .card.--outlined {
19
21
  border: var(--card_border, none);
20
22
  --bdc_color: currentcolor;
21
23
 
22
- box-shadow: inset 0 0 0 var(--bdc-outline_width) var(--bdc_color), var(--bds-shadow_s);
24
+ box-shadow: var(--card_shadow--outlined, inset 0 0 0 var(--bdc-outline_width) var(--bdc_color), var(--bds-shadow_s));
23
25
  }
24
26
 
25
27
  .card.--clickable {
@@ -44,20 +44,54 @@ Inline contextual feedback message. Use for confirmations, warnings, errors, and
44
44
 
45
45
  ## CSS variables
46
46
 
47
+ The override surface is **layered**. Setting a public token on the alert (or any ancestor) themes every variant; setting a per-variant token themes only that one variant.
48
+
49
+ ```css
50
+ /* Brand every alert (regardless of variant) */
51
+ .brand-alerts {
52
+ --alert_bg: var(--brand-bg);
53
+ --alert_text: var(--brand-text);
54
+ --alert_border: var(--brand-border);
55
+ }
56
+
57
+ /* Or target a single variant */
58
+ .brand-alerts {
59
+ --alert_bg--success: var(--brand-success);
60
+ }
61
+ ```
62
+
63
+ ### Public override tokens (win over variant defaults)
47
64
 
48
65
  <table>
49
66
  <thead>
50
67
  <tr><th>Variable</th><th>Default</th><th>Description</th></tr>
51
68
  </thead>
52
69
  <tbody>
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>
70
+ <tr><td>`--alert_bg`</td><td>per variant</td><td>Background colour. Set this to theme every variant at once.</td></tr>
71
+ <tr><td>`--alert_text`</td><td>per variant</td><td>Text and icon colour.</td></tr>
72
+ <tr><td>`--alert_border`</td><td>per variant</td><td>Inline-start border (the coloured strip).</td></tr>
73
+ <tr><td>`--alert_dismiss-border`</td><td>`none`</td><td>Dismiss button border.</td></tr>
74
+ <tr><td>`--alert_dismiss-radius`</td><td>`var(--bds-border_radius--circle)`</td><td>Dismiss button border radius.</td></tr>
75
+ <tr><td>`--alert_dismiss-opacity--hover`</td><td>`0.7`</td><td>Dismiss button opacity on hover.</td></tr>
76
+ </tbody>
77
+ </table>
78
+
79
+ ### Per-variant overrides
80
+
81
+ <table>
82
+ <thead>
83
+ <tr><th>Variant</th><th>Background</th><th>Text</th><th>Border</th></tr>
84
+ </thead>
85
+ <tbody>
86
+ <tr><td>`info`</td><td>`--alert_bg--info`</td><td>`--alert_text--info`</td><td>`--alert_border--info`</td></tr>
87
+ <tr><td>`success`</td><td>`--alert_bg--success`</td><td>`--alert_text--success`</td><td>`--alert_border--success`</td></tr>
88
+ <tr><td>`warning`</td><td>`--alert_bg--warning`</td><td>`--alert_text--warning`</td><td>`--alert_border--warning`</td></tr>
89
+ <tr><td>`error`</td><td>`--alert_bg--error`</td><td>`--alert_text--error`</td><td>`--alert_border--error`</td></tr>
58
90
  </tbody>
59
91
  </table>
60
92
 
93
+ Defaults resolve to the corresponding `--bds-color_{variant}--subtle` / `--bds-color_on-{variant}--subtle` / `--bds-color_{variant}` foundation tokens.
94
+
61
95
 
62
96
  ## Accessibility
63
97
 
@@ -5,35 +5,41 @@
5
5
  gap: var(--bds-space_s);
6
6
  padding: var(--bds-space_m);
7
7
  border-radius: var(--bds-border_radius--s);
8
- border-inline-start: var(--bds-space_s) solid var(--alert_border, var(--bds-color_blue));
9
- background-color: var(--alert_bg, var(--bds-color_blue--subtle));
10
- color: var(--alert_text, var(--bds-color_on-blue--subtle));
8
+
9
+ /* Layered cascade: public overrides (--alert_bg, --alert_text, --alert_border)
10
+ are read OUTERMOST so an ancestor-set value always wins over variant
11
+ defaults. Variants write to the inner --alert_*--variant slot. */
12
+ background-color: var(--alert_bg, var(--alert_bg--variant, var(--bds-color_blue--subtle)));
13
+ color: var(--alert_text, var(--alert_text--variant, var(--bds-color_on-blue--subtle)));
14
+ border-inline-start: var(--bds-space_s) solid var(--alert_border, var(--alert_border--variant, var(--bds-color_blue)));
11
15
  font-size: var(--bds-font_size--body);
12
16
  line-height: var(--bds-font_line-height--body);
13
17
  }
14
18
 
19
+ /* Per-variant resting overrides — consumers can theme per-variant via
20
+ --alert_bg--info / --alert_bg--success / ... */
15
21
  .--variant_info {
16
- --alert_bg: var(--bds-color_blue--subtle);
17
- --alert_text: var(--bds-color_on-blue--subtle);
18
- --alert_border: var(--bds-color_blue);
22
+ --alert_bg--variant: var(--alert_bg--info, var(--bds-color_blue--subtle));
23
+ --alert_text--variant: var(--alert_text--info, var(--bds-color_on-blue--subtle));
24
+ --alert_border--variant: var(--alert_border--info, var(--bds-color_blue));
19
25
  }
20
26
 
21
27
  .--variant_success {
22
- --alert_bg: var(--bds-color_success--subtle);
23
- --alert_text: var(--bds-color_on-success--subtle);
24
- --alert_border: var(--bds-color_success);
28
+ --alert_bg--variant: var(--alert_bg--success, var(--bds-color_success--subtle));
29
+ --alert_text--variant: var(--alert_text--success, var(--bds-color_on-success--subtle));
30
+ --alert_border--variant: var(--alert_border--success, var(--bds-color_success));
25
31
  }
26
32
 
27
33
  .--variant_warning {
28
- --alert_bg: var(--bds-color_orange--subtle);
29
- --alert_text: var(--bds-color_on-orange--subtle);
30
- --alert_border: var(--bds-color_warning);
34
+ --alert_bg--variant: var(--alert_bg--warning, var(--bds-color_orange--subtle));
35
+ --alert_text--variant: var(--alert_text--warning, var(--bds-color_on-orange--subtle));
36
+ --alert_border--variant: var(--alert_border--warning, var(--bds-color_warning));
31
37
  }
32
38
 
33
39
  .--variant_error {
34
- --alert_bg: rgb(from var(--bds-color_error) r g b / 12%);
35
- --alert_text: var(--bds-color_on-bg);
36
- --alert_border: var(--bds-color_error);
40
+ --alert_bg--variant: var(--alert_bg--error, rgb(from var(--bds-color_error) r g b / 12%));
41
+ --alert_text--variant: var(--alert_text--error, var(--bds-color_on-bg));
42
+ --alert_border--variant: var(--alert_border--error, var(--bds-color_error));
37
43
  }
38
44
 
39
45
  .icon {
@@ -42,19 +42,39 @@ Compact inline label for status, category, or count. Renders a `<span>` with a s
42
42
 
43
43
  ## CSS variables
44
44
 
45
- Override these on a parent element to customise the badge without touching global tokens:
45
+ The override surface is **layered**. Setting a public token on the badge (or any ancestor) themes every variant; setting a per-variant token themes only that one variant.
46
46
 
47
+ ### Public override tokens (win over variant defaults)
47
48
 
48
49
  <table>
49
50
  <thead>
50
51
  <tr><th>Variable</th><th>Default</th><th>Description</th></tr>
51
52
  </thead>
52
53
  <tbody>
53
- <tr><td>`--badge_bg`</td><td>`var(--bds-color_blue)`</td><td>Background colour</td></tr>
54
- <tr><td>`--badge_text`</td><td>`var(--bds-color_on-blue)`</td><td>Text colour</td></tr>
54
+ <tr><td>`--badge_bg`</td><td>per variant</td><td>Background colour. Set to theme every variant at once.</td></tr>
55
+ <tr><td>`--badge_text`</td><td>per variant</td><td>Text colour.</td></tr>
56
+ <tr><td>`--badge_radius`</td><td>`var(--bds-border_radius--full)`</td><td>Badge border radius.</td></tr>
57
+ <tr><td>`--badge_font-size`</td><td>`var(--bds-font_size--body--s)`</td><td>Badge font size.</td></tr>
55
58
  </tbody>
56
59
  </table>
57
60
 
61
+ ### Per-variant overrides
62
+
63
+ <table>
64
+ <thead>
65
+ <tr><th>Variant</th><th>Background</th><th>Text</th></tr>
66
+ </thead>
67
+ <tbody>
68
+ <tr><td>`primary`</td><td>`--badge_bg--primary`</td><td>`--badge_text--primary`</td></tr>
69
+ <tr><td>`secondary`</td><td>`--badge_bg--secondary`</td><td>`--badge_text--secondary`</td></tr>
70
+ <tr><td>`success`</td><td>`--badge_bg--success`</td><td>`--badge_text--success`</td></tr>
71
+ <tr><td>`error`</td><td>`--badge_bg--error`</td><td>`--badge_text--error`</td></tr>
72
+ <tr><td>`warning`</td><td>`--badge_bg--warning`</td><td>`--badge_text--warning`</td></tr>
73
+ </tbody>
74
+ </table>
75
+
76
+ Defaults resolve to the corresponding `--bds-color_{variant}` / `--bds-color_on-{variant}` foundation tokens.
77
+
58
78
 
59
79
  ## Accessibility
60
80
 
@@ -9,32 +9,35 @@
9
9
  font-weight: var(--bds-font_weight--semibold);
10
10
  line-height: 1;
11
11
  white-space: nowrap;
12
- background-color: var(--badge_bg, var(--bds-color_blue));
13
- color: var(--badge_text, var(--bds-color_on-blue));
12
+
13
+ /* Layered cascade: public overrides (--badge_bg, --badge_text) win over
14
+ per-variant defaults. Variants write to the inner --badge_*--variant slot. */
15
+ background-color: var(--badge_bg, var(--badge_bg--variant, var(--bds-color_blue)));
16
+ color: var(--badge_text, var(--badge_text--variant, var(--bds-color_on-blue)));
14
17
  }
15
18
 
16
19
  .--variant_primary {
17
- --badge_bg: var(--bds-color_interactive);
18
- --badge_text: var(--bds-color_on-interactive);
20
+ --badge_bg--variant: var(--badge_bg--primary, var(--bds-color_interactive));
21
+ --badge_text--variant: var(--badge_text--primary, var(--bds-color_on-interactive));
19
22
  }
20
23
 
21
24
  .--variant_secondary {
22
- --badge_bg: var(--bds-color_bg);
23
- --badge_text: var(--bds-color_on-bg);
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));
24
27
  }
25
28
 
26
29
  .--variant_success {
27
- --badge_bg: var(--bds-color_success);
28
- --badge_text: var(--bds-color_on-success);
30
+ --badge_bg--variant: var(--badge_bg--success, var(--bds-color_success));
31
+ --badge_text--variant: var(--badge_text--success, var(--bds-color_on-success));
29
32
  }
30
33
 
31
34
  .--variant_error {
32
- --badge_bg: var(--bds-color_error);
33
- --badge_text: var(--bds-color_on-error);
35
+ --badge_bg--variant: var(--badge_bg--error, var(--bds-color_error));
36
+ --badge_text--variant: var(--badge_text--error, var(--bds-color_on-error));
34
37
  }
35
38
 
36
39
  .--variant_warning {
37
- --badge_bg: var(--bds-color_warning);
38
- --badge_text: var(--bds-color_on-warning);
40
+ --badge_bg--variant: var(--badge_bg--warning, var(--bds-color_warning));
41
+ --badge_text--variant: var(--badge_text--warning, var(--bds-color_on-warning));
39
42
  }
40
43
  }
@@ -40,17 +40,35 @@ Styled anchor element with three visual variants. Renders as `<a>` by default, b
40
40
 
41
41
  ## CSS variables
42
42
 
43
+ Resting and hover are **independent** — setting `--link_color` themes only resting; setting `--link_color-hover` themes only hover. Setting either as a per-variant token (`--link_color--subtle`, `--link_color-hover--standalone`, etc.) targets a single variant.
44
+
45
+ ### Public override tokens (win over variant defaults)
43
46
 
44
47
  <table>
45
48
  <thead>
46
49
  <tr><th>Variable</th><th>Default</th><th>Description</th></tr>
47
50
  </thead>
48
51
  <tbody>
49
- <tr><td>`--link_color`</td><td>`var(--bds-color_interactive_on-bg)`</td><td>Link text colour</td></tr>
50
- <tr><td>`--link_color-hover`</td><td>`var(--bds-color_blue--strong)`</td><td>Link text colour on hover</td></tr>
52
+ <tr><td>`--link_color`</td><td>per variant</td><td>Link text colour at rest.</td></tr>
53
+ <tr><td>`--link_color-hover`</td><td>per variant</td><td>Link text colour on hover.</td></tr>
54
+ </tbody>
55
+ </table>
56
+
57
+ ### Per-variant overrides
58
+
59
+ <table>
60
+ <thead>
61
+ <tr><th>Variant</th><th>Resting</th><th>Hover</th></tr>
62
+ </thead>
63
+ <tbody>
64
+ <tr><td>`default`</td><td>`--link_color--default`</td><td>`--link_color-hover--default`</td></tr>
65
+ <tr><td>`subtle`</td><td>`--link_color--subtle`</td><td>`--link_color-hover--subtle`</td></tr>
66
+ <tr><td>`standalone`</td><td>`--link_color--standalone`</td><td>`--link_color-hover--standalone`</td></tr>
51
67
  </tbody>
52
68
  </table>
53
69
 
70
+ Defaults: `default` and `standalone` resolve to `--bds-color_interactive_on-bg` (resting) / `--bds-color_blue--strong` (hover); `subtle` resolves to `--bds-color_on-bg` / `--bds-color_interactive_on-bg`.
71
+
54
72
 
55
73
  ## Accessibility
56
74
 
@@ -1,6 +1,10 @@
1
1
  @layer boostdev.component {
2
2
  .link {
3
- color: var(--link_color, var(--bds-color_interactive_on-bg));
3
+ /* Layered cascade: public override (--link_color) wins over per-variant defaults.
4
+ Variants write to the inner --link_color--variant slot.
5
+ Resting and hover have INDEPENDENT public tokens — setting --link_color on an
6
+ ancestor themes only resting; setting --link_color-hover themes only hover. */
7
+ color: var(--link_color, var(--link_color--variant, var(--bds-color_interactive_on-bg)));
4
8
  text-decoration: underline;
5
9
  text-underline-offset: 0.2em;
6
10
  transition: var(--bds-animation_transition);
@@ -15,23 +19,23 @@
15
19
 
16
20
  @media (hover: hover) and (pointer: fine) {
17
21
  .link:hover {
18
- --link_color: var(--link_color-hover, var(--bds-color_blue--strong));
22
+ color: var(--link_color-hover, var(--link_color-hover--variant, var(--bds-color_blue--strong)));
19
23
  }
20
24
  }
21
25
 
22
26
  .--variant_default {
23
- --link_color: var(--bds-color_interactive_on-bg);
24
- --link_color-hover: var(--bds-color_blue--strong);
27
+ --link_color--variant: var(--link_color--default, var(--bds-color_interactive_on-bg));
28
+ --link_color-hover--variant: var(--link_color-hover--default, var(--bds-color_blue--strong));
25
29
  }
26
30
 
27
31
  .--variant_subtle {
28
- --link_color: var(--bds-color_on-bg);
29
- --link_color-hover: var(--bds-color_interactive_on-bg);
32
+ --link_color--variant: var(--link_color--subtle, var(--bds-color_on-bg));
33
+ --link_color-hover--variant: var(--link_color-hover--subtle, var(--bds-color_interactive_on-bg));
30
34
  }
31
35
 
32
36
  .--variant_standalone {
33
- --link_color: var(--bds-color_interactive_on-bg);
34
- --link_color-hover: var(--bds-color_blue--strong);
37
+ --link_color--variant: var(--link_color--standalone, var(--bds-color_interactive_on-bg));
38
+ --link_color-hover--variant: var(--link_color-hover--standalone, var(--bds-color_blue--strong));
35
39
 
36
40
  display: inline-flex;
37
41
  align-items: center;
@@ -41,21 +41,40 @@ Full-width banner for page-level system messages. Sits at the top of the page or
41
41
 
42
42
  ## CSS variables
43
43
 
44
+ The override surface is **layered**. Setting a public token on the banner (or any ancestor) themes every variant; setting a per-variant token themes only that one variant.
45
+
46
+ ### Public override tokens (win over variant defaults)
44
47
 
45
48
  <table>
46
49
  <thead>
47
50
  <tr><th>Variable</th><th>Default</th><th>Description</th></tr>
48
51
  </thead>
49
52
  <tbody>
50
- <tr><td>`--banner_bg`</td><td>Per variant</td><td>Banner background colour</td></tr>
51
- <tr><td>`--banner_text`</td><td>Per variant</td><td>Banner text colour</td></tr>
52
- <tr><td>`--banner_border`</td><td>Per variant</td><td>Banner bottom border colour</td></tr>
53
- <tr><td>`--banner_dismiss-radius`</td><td>`var(--bds-border_radius--circle)`</td><td>Dismiss button border radius</td></tr>
54
- <tr><td>`--banner_dismiss-border`</td><td>`none`</td><td>Dismiss button border</td></tr>
55
- <tr><td>`--banner_dismiss-opacity--hover`</td><td>`0.7`</td><td>Dismiss button opacity on hover</td></tr>
53
+ <tr><td>`--banner_bg`</td><td>per variant</td><td>Banner background colour. Set to theme every variant at once.</td></tr>
54
+ <tr><td>`--banner_text`</td><td>per variant</td><td>Banner text colour.</td></tr>
55
+ <tr><td>`--banner_border`</td><td>per variant</td><td>Banner block-end border colour.</td></tr>
56
+ <tr><td>`--banner_dismiss-radius`</td><td>`var(--bds-border_radius--circle)`</td><td>Dismiss button border radius.</td></tr>
57
+ <tr><td>`--banner_dismiss-border`</td><td>`none`</td><td>Dismiss button border.</td></tr>
58
+ <tr><td>`--banner_dismiss-opacity--hover`</td><td>`0.7`</td><td>Dismiss button opacity on hover.</td></tr>
59
+ </tbody>
60
+ </table>
61
+
62
+ ### Per-variant overrides
63
+
64
+ <table>
65
+ <thead>
66
+ <tr><th>Variant</th><th>Background</th><th>Text</th><th>Border</th></tr>
67
+ </thead>
68
+ <tbody>
69
+ <tr><td>`info`</td><td>`--banner_bg--info`</td><td>`--banner_text--info`</td><td>`--banner_border--info`</td></tr>
70
+ <tr><td>`success`</td><td>`--banner_bg--success`</td><td>`--banner_text--success`</td><td>`--banner_border--success`</td></tr>
71
+ <tr><td>`warning`</td><td>`--banner_bg--warning`</td><td>`--banner_text--warning`</td><td>`--banner_border--warning`</td></tr>
72
+ <tr><td>`error`</td><td>`--banner_bg--error`</td><td>`--banner_text--error`</td><td>`--banner_border--error`</td></tr>
56
73
  </tbody>
57
74
  </table>
58
75
 
76
+ Defaults resolve to the corresponding foundation tokens.
77
+
59
78
 
60
79
  ## Accessibility
61
80
 
@@ -4,36 +4,39 @@
4
4
  align-items: center;
5
5
  gap: var(--bds-space_m);
6
6
  padding: var(--bds-space_s) var(--bds-space_m);
7
- background-color: var(--banner_bg, var(--bds-color_blue--subtle));
8
- color: var(--banner_text, var(--bds-color_on-blue--subtle));
9
- border-block-end: 3px solid var(--banner_border, var(--bds-color_blue));
7
+
8
+ /* Layered cascade: public overrides (--banner_bg, --banner_text, --banner_border)
9
+ win over per-variant defaults. Variants write to the inner --banner_*--variant slot. */
10
+ background-color: var(--banner_bg, var(--banner_bg--variant, var(--bds-color_blue--subtle)));
11
+ color: var(--banner_text, var(--banner_text--variant, var(--bds-color_on-blue--subtle)));
12
+ border-block-end: 3px solid var(--banner_border, var(--banner_border--variant, var(--bds-color_blue)));
10
13
  font-size: var(--bds-font_size--body);
11
14
  line-height: var(--bds-font_line-height--body);
12
15
  inline-size: 100%;
13
16
  }
14
17
 
15
18
  .--variant_info {
16
- --banner_bg: var(--bds-color_blue--subtle);
17
- --banner_text: var(--bds-color_on-blue--subtle);
18
- --banner_border: var(--bds-color_blue);
19
+ --banner_bg--variant: var(--banner_bg--info, var(--bds-color_blue--subtle));
20
+ --banner_text--variant: var(--banner_text--info, var(--bds-color_on-blue--subtle));
21
+ --banner_border--variant: var(--banner_border--info, var(--bds-color_blue));
19
22
  }
20
23
 
21
24
  .--variant_success {
22
- --banner_bg: var(--bds-color_success--subtle);
23
- --banner_text: var(--bds-color_on-success--subtle);
24
- --banner_border: var(--bds-color_success);
25
+ --banner_bg--variant: var(--banner_bg--success, var(--bds-color_success--subtle));
26
+ --banner_text--variant: var(--banner_text--success, var(--bds-color_on-success--subtle));
27
+ --banner_border--variant: var(--banner_border--success, var(--bds-color_success));
25
28
  }
26
29
 
27
30
  .--variant_warning {
28
- --banner_bg: var(--bds-color_orange--subtle);
29
- --banner_text: var(--bds-color_on-orange--subtle);
30
- --banner_border: var(--bds-color_warning);
31
+ --banner_bg--variant: var(--banner_bg--warning, var(--bds-color_orange--subtle));
32
+ --banner_text--variant: var(--banner_text--warning, var(--bds-color_on-orange--subtle));
33
+ --banner_border--variant: var(--banner_border--warning, var(--bds-color_warning));
31
34
  }
32
35
 
33
36
  .--variant_error {
34
- --banner_bg: rgb(from var(--bds-color_error) r g b / 12%);
35
- --banner_text: var(--bds-color_on-bg);
36
- --banner_border: var(--bds-color_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));
39
+ --banner_border--variant: var(--banner_border--error, var(--bds-color_error));
37
40
  }
38
41
 
39
42
  .content {
@@ -34,24 +34,37 @@ Navigation control for paged data sets. Renders prev/next buttons plus numbered
34
34
 
35
35
  ## CSS variables
36
36
 
37
+ The override surface is **layered**. Setting `--btn_bg` / `--btn_color` / `--btn_border` on the pagination (or any ancestor) wins in every state — resting, hover, and active. Setting per-state tokens targets only that one state.
38
+
39
+ ### Public override tokens (win over per-state defaults)
37
40
 
38
41
  <table>
39
42
  <thead>
40
43
  <tr><th>Variable</th><th>Default</th><th>Description</th></tr>
41
44
  </thead>
42
45
  <tbody>
43
- <tr><td>`--pagination_radius`</td><td>`var(--bds-border_radius--full)`</td><td>Page button border radius</td></tr>
44
- <tr><td>`--btn_bg`</td><td>`transparent`</td><td>Default button background</td></tr>
45
- <tr><td>`--btn_color`</td><td>`var(--bds-color_on-bg)`</td><td>Default button text colour</td></tr>
46
- <tr><td>`--btn_border`</td><td>`var(--bds-color_bg--subtle)`</td><td>Default button border colour</td></tr>
47
- <tr><td>`--btn_bg--hover`</td><td>`var(--bds-color_bg--subtle)`</td><td>Button background on hover</td></tr>
48
- <tr><td>`--btn_color--hover`</td><td>`var(--bds-color_interactive_on-bg)`</td><td>Button text colour on hover</td></tr>
49
- <tr><td>`--btn_bg--active`</td><td>`var(--bds-color_interactive)`</td><td>Active (current page) button background</td></tr>
50
- <tr><td>`--btn_color--active`</td><td>`var(--bds-color_on-interactive)`</td><td>Active (current page) button text colour</td></tr>
51
- <tr><td>`--btn_border--active`</td><td>`var(--bds-color_interactive)`</td><td>Active (current page) button border colour</td></tr>
46
+ <tr><td>`--pagination_radius`</td><td>`var(--bds-border_radius--full)`</td><td>Page button border radius.</td></tr>
47
+ <tr><td>`--btn_bg`</td><td>`transparent` (per state)</td><td>Button background. Set to theme every state at once.</td></tr>
48
+ <tr><td>`--btn_color`</td><td>per state</td><td>Button text colour.</td></tr>
49
+ <tr><td>`--btn_border`</td><td>per state</td><td>Button border colour.</td></tr>
50
+ </tbody>
51
+ </table>
52
+
53
+ ### Per-state overrides
54
+
55
+ <table>
56
+ <thead>
57
+ <tr><th>State</th><th>Background</th><th>Text</th><th>Border</th></tr>
58
+ </thead>
59
+ <tbody>
60
+ <tr><td>resting</td><td>(`transparent`)</td><td>(`var(--bds-color_on-bg)`)</td><td>(`var(--bds-color_bg--subtle)`)</td></tr>
61
+ <tr><td>hover</td><td>`--btn_bg--hover`</td><td>`--btn_color--hover`</td><td>—</td></tr>
62
+ <tr><td>active (current page)</td><td>`--btn_bg--active`</td><td>`--btn_color--active`</td><td>`--btn_border--active`</td></tr>
52
63
  </tbody>
53
64
  </table>
54
65
 
66
+ Defaults: hover resolves to `--bds-color_bg--subtle` / `--bds-color_interactive_on-bg`; active resolves to `--bds-color_interactive` / `--bds-color_on-interactive`.
67
+
55
68
 
56
69
  ## Accessibility
57
70
 
@@ -26,13 +26,15 @@
26
26
  block-size: 2.25rem;
27
27
  padding-inline: var(--bds-space_xs);
28
28
  border-radius: var(--pagination_radius, var(--bds-border_radius--full));
29
- background-color: var(--btn_bg, transparent);
30
29
 
31
- --bdc_color: var(--btn_border, var(--bds-color_bg--subtle));
30
+ /* Layered cascade: public overrides (--btn_bg, --btn_color, --btn_border) win
31
+ over per-state defaults. Hover/active write to the inner --btn_*--state slot. */
32
+ background-color: var(--btn_bg, var(--btn_bg--state, transparent));
33
+ color: var(--btn_color, var(--btn_color--state, var(--bds-color_on-bg)));
34
+ --bdc_color: var(--btn_border, var(--btn_border--state, var(--bds-color_bg--subtle)));
32
35
 
33
36
  border: none;
34
37
  box-shadow: inset 0 0 0 var(--bdc-outline_width) var(--bdc_color);
35
- color: var(--btn_color, var(--bds-color_on-bg));
36
38
  font-family: var(--bds-font_family--body);
37
39
  font-size: var(--bds-font_size--body);
38
40
  font-variant-numeric: tabular-nums;
@@ -53,15 +55,15 @@
53
55
 
54
56
  @media (hover: hover) and (pointer: fine) {
55
57
  .button:not(:disabled, .--active):hover {
56
- --btn_bg: var(--btn_bg--hover, var(--bds-color_bg--subtle));
57
- --btn_color: var(--btn_color--hover, var(--bds-color_interactive_on-bg));
58
+ --btn_bg--state: var(--btn_bg--hover, var(--bds-color_bg--subtle));
59
+ --btn_color--state: var(--btn_color--hover, var(--bds-color_interactive_on-bg));
58
60
  }
59
61
  }
60
62
 
61
63
  .button.--active {
62
- --btn_bg: var(--btn_bg--active, var(--bds-color_interactive));
63
- --btn_color: var(--btn_color--active, var(--bds-color_on-interactive));
64
- --btn_border: var(--btn_border--active, var(--bds-color_interactive));
64
+ --btn_bg--state: var(--btn_bg--active, var(--bds-color_interactive));
65
+ --btn_color--state: var(--btn_color--active, var(--bds-color_on-interactive));
66
+ --btn_border--state: var(--btn_border--active, var(--bds-color_interactive));
65
67
  }
66
68
 
67
69
  .button.--nav svg {