@boostdev/design-system-components 0.1.18 → 1.0.1

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 +419 -242
  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 +421 -246
  8. package/dist/index.cjs +419 -242
  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 +421 -246
  13. package/package.json +9 -4
  14. package/src/components/interaction/Button/Button.mdx +8 -11
  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 +12 -3
  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 +66 -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
@@ -0,0 +1,158 @@
1
+ import { Meta } from '@storybook/blocks';
2
+
3
+ <Meta title="Design System/Borders" />
4
+
5
+ export const BorderDemo = ({ label, token, color = 'currentcolor', offset = '-1px', width = '1px' }) => (
6
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '0.75rem', alignItems: 'center' }}>
7
+ <div style={{
8
+ width: '8rem',
9
+ height: '5rem',
10
+ background: 'var(--bds-bg)',
11
+ borderRadius: '0.5rem',
12
+ outline: `${width} solid ${color}`,
13
+ outlineOffset: offset,
14
+ }} />
15
+ <div style={{ textAlign: 'center' }}>
16
+ <div style={{ fontSize: '0.8rem', fontWeight: 600 }}>{label}</div>
17
+ <div style={{ fontSize: '0.7rem', fontFamily: 'monospace', opacity: 0.6, marginTop: '0.1rem' }}>{token}</div>
18
+ </div>
19
+ </div>
20
+ );
21
+
22
+ export const TokenRow = ({ token, type, defaultValue, description }) => (
23
+ <tr>
24
+ <td><code>{token}</code></td>
25
+ <td style={{ fontFamily: 'monospace' }}>{type}</td>
26
+ <td style={{ fontFamily: 'monospace' }}>{defaultValue}</td>
27
+ <td>{description}</td>
28
+ </tr>
29
+ );
30
+
31
+ # Borders
32
+
33
+ The `bdc` system unifies all component borders behind five registered CSS custom properties. Every form control, card, and interactive surface draws its border from these tokens — ensuring consistent visual weight, smooth animated state transitions, and a single override point for theming.
34
+
35
+ ## Why outline, not border?
36
+
37
+ Components use `outline` rather than `border` for their decorative edge. The reasons:
38
+
39
+ - **Zero layout impact** — `outline` lives outside the box model, so changing width or color never shifts surrounding elements.
40
+ - **Inset appearance** — `outline-offset: -1px` pulls the ring inside the element, making it visually indistinguishable from a traditional border.
41
+ - **Animatable colour** — `@property --bdc_color { syntax: '<color>'; }` registers the token as a typed custom property, which lets the browser interpolate it directly. A single `transition: --bdc_color 150ms ease-out` handles focus, hover, and error state changes without JavaScript.
42
+
43
+ ## Tokens
44
+
45
+ <table>
46
+ <thead>
47
+ <tr>
48
+ <th>Token</th>
49
+ <th>Type</th>
50
+ <th>Default</th>
51
+ <th>Description</th>
52
+ </tr>
53
+ </thead>
54
+ <tbody>
55
+ <TokenRow token="--bdc_color" type="<color>" defaultValue="currentcolor" description="Border colour — transitions smoothly between states" />
56
+ <TokenRow token="--bdc-outline_width" type="<length>" defaultValue="1px" description="Border width" />
57
+ <TokenRow token="--bdc-outline_offset" type="<length>" defaultValue="-1px" description="Negative = inset (border-like); positive = outer halo" />
58
+ <TokenRow token="--bdc-outline_radius" type="<length-percentage>" defaultValue="0" description="Border radius, synced with the element's own radius" />
59
+ <TokenRow token="--bdc-outline_shadow" type="*" defaultValue="none" description="Box shadow — opt-in accent, e.g. focus glow" />
60
+ </tbody>
61
+ </table>
62
+
63
+ ---
64
+
65
+ ## Visual examples
66
+
67
+ <div style={{ display: 'flex', gap: '2.5rem', flexWrap: 'wrap', padding: '2rem', background: 'var(--bds-bg--subtle)', borderRadius: '0.75rem', marginBottom: '2rem' }}>
68
+ <BorderDemo label="Default" token="currentcolor" color="currentcolor" />
69
+ <BorderDemo label="Focus" token="--bdc_color--focus" color="var(--bds-interactive)" />
70
+ <BorderDemo label="Error" token="--bdc_color--error" color="var(--bds-error)" />
71
+ <BorderDemo label="Outer halo" token="--bdc-outline_offset: 2px" color="var(--bds-interactive)" offset="2px" width="2px" />
72
+ </div>
73
+
74
+ | State | `--bdc_color` resolves to | Trigger |
75
+ |-------|--------------------------|---------|
76
+ | Default | `currentcolor` | — |
77
+ | Focus | `var(--bdc_color--focus)` → `--bds-interactive` | `:focus` |
78
+ | Error | `var(--bdc_color--error)` → `--bds-error` | `[aria-invalid="true"]` |
79
+ | Keyboard ring | `var(--bds-outline_default)` | `:focus-visible` |
80
+
81
+ ---
82
+
83
+ ## Component pattern
84
+
85
+ Every component that renders a bordered element follows this CSS pattern:
86
+
87
+ ```css
88
+ .element {
89
+ /* Suppress any browser default border — consumer can re-enable
90
+ via the --component_border custom property if needed. */
91
+ border: none;
92
+
93
+ /* bdc defaults */
94
+ --bdc_color: currentcolor;
95
+
96
+ /* Rendered border (zero layout impact) */
97
+ outline: var(--bdc-outline_width) solid var(--bdc_color);
98
+ outline-offset: var(--bdc-outline_offset);
99
+ border-radius: var(--bdc-outline_radius);
100
+ box-shadow: var(--bdc-outline_shadow);
101
+
102
+ /* Smooth colour transitions via registered @property */
103
+ transition: --bdc_color 150ms ease-out;
104
+ }
105
+
106
+ /* State overrides — only the colour token changes */
107
+ .element:focus { --bdc_color: var(--bdc_color--focus); }
108
+ .element[aria-invalid="true"] { --bdc_color: var(--bdc_color--error); }
109
+
110
+ /* Keyboard accessibility ring — replaces outline on focus-visible */
111
+ .element:focus-visible {
112
+ outline: var(--bds-outline_default);
113
+ outline-offset: var(--bds-outline_offset);
114
+ }
115
+ ```
116
+
117
+ ---
118
+
119
+ ## Consumer overrides
120
+
121
+ Override a component's border colour for a specific context by reassigning `--bdc_color`:
122
+
123
+ ```css
124
+ /* Scoped to a single component instance */
125
+ .my-context .my-input {
126
+ --bdc_color: var(--bds-warning);
127
+ }
128
+
129
+ /* Override globally via the token layer */
130
+ @layer tokens.override {
131
+ :root {
132
+ --bdc_color: var(--bds-brand);
133
+ }
134
+ }
135
+ ```
136
+
137
+ To change width or radius independently:
138
+
139
+ ```css
140
+ .my-card {
141
+ --bdc-outline_width: 2px;
142
+ --bdc-outline_radius: var(--bds-border_radius--m);
143
+ }
144
+ ```
145
+
146
+ ---
147
+
148
+ ## Import
149
+
150
+ The `bdc` tokens are included automatically when you import the component stylesheet:
151
+
152
+ ```css
153
+ /* Included automatically with the full component CSS */
154
+ @import '@boostdev/components/css';
155
+
156
+ /* Or load the token layer standalone */
157
+ @import '@boostdev/components/css/bdc';
158
+ ```
@@ -0,0 +1,196 @@
1
+ import { Meta } from '@storybook/blocks';
2
+
3
+ <Meta title="Design System/Colors" />
4
+
5
+ export const Swatch = ({ label, bg, text, token }) => (
6
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '0.5rem', minWidth: '9rem' }}>
7
+ <div style={{
8
+ background: bg,
9
+ color: text,
10
+ height: '4rem',
11
+ borderRadius: '0.5rem',
12
+ border: '1px solid rgba(0,0,0,0.08)',
13
+ display: 'flex',
14
+ alignItems: 'flex-end',
15
+ padding: '0.375rem 0.5rem',
16
+ fontSize: '0.7rem',
17
+ fontFamily: 'monospace',
18
+ gap: '0.25rem',
19
+ }}>
20
+ {text && <span style={{ opacity: 0.8 }}>Aa</span>}
21
+ </div>
22
+ <div style={{ fontSize: '0.75rem', lineHeight: 1.3 }}>
23
+ <div style={{ fontWeight: 600 }}>{label}</div>
24
+ <div style={{ fontFamily: 'monospace', opacity: 0.65, fontSize: '0.7rem' }}>{token}</div>
25
+ </div>
26
+ </div>
27
+ );
28
+
29
+ export const SwatchRow = ({ children }) => (
30
+ <div style={{ display: 'flex', flexWrap: 'wrap', gap: '1rem', marginBottom: '2rem' }}>
31
+ {children}
32
+ </div>
33
+ );
34
+
35
+ export const TokenRow = ({ token, description }) => (
36
+ <tr>
37
+ <td><code>{token}</code></td>
38
+ <td>
39
+ <div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem' }}>
40
+ <div style={{ width: '1.5rem', height: '1.5rem', background: `var(${token})`, borderRadius: '0.25rem', border: '1px solid rgba(0,0,0,0.1)', flexShrink: 0 }} />
41
+ {description}
42
+ </div>
43
+ </td>
44
+ </tr>
45
+ );
46
+
47
+ # Colours
48
+
49
+ Colours are the most visible part of the design system.
50
+ Every colour token comes in surface–content pairs: for every `--bds-*` there is a `--bds-on-*` that guarantees WCAG AA contrast.
51
+
52
+ ```css
53
+ .badge {
54
+ background-color: var(--bds-success--subtle);
55
+ color: var(--bds-on-success--subtle); /* always legible */
56
+ }
57
+ ```
58
+
59
+ ## Semantic colours
60
+
61
+ These are the tokens you should use in component CSS. They adapt automatically to light and dark mode.
62
+
63
+ ### Brand & intent
64
+
65
+ <SwatchRow>
66
+ <Swatch label="CTA / Active" token="--bds-cta" bg="var(--bds-cta)" text="var(--bds-on-cta)" />
67
+ <Swatch label="Interactive" token="--bds-interactive" bg="var(--bds-interactive)" text="var(--bds-on-interactive)" />
68
+ <Swatch label="Brand" token="--bds-brand" bg="var(--bds-brand)" text="var(--bds-on-brand)" />
69
+ </SwatchRow>
70
+
71
+ ### Status
72
+
73
+ <SwatchRow>
74
+ <Swatch label="Success" token="--bds-success" bg="var(--bds-success)" text="var(--bds-on-success)" />
75
+ <Swatch label="Warning" token="--bds-warning" bg="var(--bds-warning)" text="var(--bds-on-warning)" />
76
+ <Swatch label="Error" token="--bds-error" bg="var(--bds-error)" text="var(--bds-on-error)" />
77
+ <Swatch label="Important" token="--bds-important" bg="var(--bds-important)" text="var(--bds-on-important)" />
78
+ </SwatchRow>
79
+
80
+ ### Surface
81
+
82
+ <SwatchRow>
83
+ <Swatch label="Background" token="--bds-bg" bg="var(--bds-bg)" text="var(--bds-on-bg)" />
84
+ <Swatch label="Subtle background" token="--bds-bg--subtle" bg="var(--bds-bg--subtle)" text="var(--bds-on-bg--subtle)" />
85
+ </SwatchRow>
86
+
87
+ ### Neutral grey scale
88
+
89
+ <SwatchRow>
90
+ <Swatch label="Grey subtle" token="--bds-grey--subtle" bg="var(--bds-grey--subtle)" text="var(--bds-on-grey--subtle)" />
91
+ <Swatch label="Grey" token="--bds-grey" bg="var(--bds-grey)" text="var(--bds-on-grey)" />
92
+ <Swatch label="Grey strong" token="--bds-grey--strong" bg="var(--bds-grey--strong)" text="var(--bds-on-grey--strong)" />
93
+ </SwatchRow>
94
+
95
+ ### Green scale
96
+
97
+ <SwatchRow>
98
+ <Swatch label="Green subtle" token="--bds-green--subtle" bg="var(--bds-green--subtle)" text="var(--bds-on-green--subtle)" />
99
+ <Swatch label="Green" token="--bds-green" bg="var(--bds-green)" text="var(--bds-on-green)" />
100
+ <Swatch label="Green strong" token="--bds-green--strong" bg="var(--bds-green--strong)" text="var(--bds-on-green--strong)" />
101
+ </SwatchRow>
102
+
103
+ ### Blue scale
104
+
105
+ <SwatchRow>
106
+ <Swatch label="Blue subtle" token="--bds-blue--subtle" bg="var(--bds-blue--subtle)" text="var(--bds-on-blue--subtle)" />
107
+ <Swatch label="Blue" token="--bds-blue" bg="var(--bds-blue)" text="var(--bds-on-blue)" />
108
+ <Swatch label="Blue strong" token="--bds-blue--strong" bg="var(--bds-blue--strong)" text="var(--bds-on-blue--strong)" />
109
+ </SwatchRow>
110
+
111
+ ### Orange scale
112
+
113
+ <SwatchRow>
114
+ <Swatch label="Orange subtle" token="--bds-orange--subtle" bg="var(--bds-orange--subtle)" text="var(--bds-on-orange--subtle)" />
115
+ <Swatch label="Orange" token="--bds-orange" bg="var(--bds-orange)" text="var(--bds-on-orange)" />
116
+ <Swatch label="Orange strong" token="--bds-orange--strong" bg="var(--bds-orange--strong)" text="var(--bds-on-orange--strong)" />
117
+ </SwatchRow>
118
+
119
+ ---
120
+
121
+ ## Base palette
122
+
123
+ These `--bds-BASE__color--*` tokens are the primitive values. **Do not use them directly** in component CSS — always use semantic tokens so themes work correctly.
124
+
125
+ ### Grey
126
+
127
+ <SwatchRow>
128
+ <Swatch label="grey-100" token="--bds-BASE__color--grey--100" bg="var(--bds-BASE__color--grey--100)" />
129
+ <Swatch label="grey-200" token="--bds-BASE__color--grey--200" bg="var(--bds-BASE__color--grey--200)" />
130
+ <Swatch label="grey-300" token="--bds-BASE__color--grey--300" bg="var(--bds-BASE__color--grey--300)" />
131
+ <Swatch label="grey-400" token="--bds-BASE__color--grey--400" bg="var(--bds-BASE__color--grey--400)" />
132
+ <Swatch label="grey-500" token="--bds-BASE__color--grey" bg="var(--bds-BASE__color--grey)" text="white" />
133
+ <Swatch label="grey-600" token="--bds-BASE__color--grey--600" bg="var(--bds-BASE__color--grey--600)" text="white" />
134
+ <Swatch label="grey-700" token="--bds-BASE__color--grey--700" bg="var(--bds-BASE__color--grey--700)" text="white" />
135
+ <Swatch label="grey-800" token="--bds-BASE__color--grey--800" bg="var(--bds-BASE__color--grey--800)" text="white" />
136
+ <Swatch label="grey-900" token="--bds-BASE__color--grey--900" bg="var(--bds-BASE__color--grey--900)" text="white" />
137
+ </SwatchRow>
138
+
139
+ ### Green
140
+
141
+ <SwatchRow>
142
+ <Swatch label="green-100" token="--bds-BASE__color--green--100" bg="var(--bds-BASE__color--green--100)" />
143
+ <Swatch label="green-200" token="--bds-BASE__color--green--200" bg="var(--bds-BASE__color--green--200)" />
144
+ <Swatch label="green-300" token="--bds-BASE__color--green--300" bg="var(--bds-BASE__color--green--300)" />
145
+ <Swatch label="green-400" token="--bds-BASE__color--green--400" bg="var(--bds-BASE__color--green--400)" />
146
+ <Swatch label="green-500" token="--bds-BASE__color--green" bg="var(--bds-BASE__color--green)" />
147
+ <Swatch label="green-600" token="--bds-BASE__color--green--600" bg="var(--bds-BASE__color--green--600)" />
148
+ <Swatch label="green-700" token="--bds-BASE__color--green--700" bg="var(--bds-BASE__color--green--700)" text="white" />
149
+ <Swatch label="green-800" token="--bds-BASE__color--green--800" bg="var(--bds-BASE__color--green--800)" text="white" />
150
+ <Swatch label="green-900" token="--bds-BASE__color--green--900" bg="var(--bds-BASE__color--green--900)" text="white" />
151
+ </SwatchRow>
152
+
153
+ ### Blue
154
+
155
+ <SwatchRow>
156
+ <Swatch label="blue-100" token="--bds-BASE__color--blue--100" bg="var(--bds-BASE__color--blue--100)" />
157
+ <Swatch label="blue-200" token="--bds-BASE__color--blue--200" bg="var(--bds-BASE__color--blue--200)" />
158
+ <Swatch label="blue-300" token="--bds-BASE__color--blue--300" bg="var(--bds-BASE__color--blue--300)" />
159
+ <Swatch label="blue-400" token="--bds-BASE__color--blue--400" bg="var(--bds-BASE__color--blue--400)" />
160
+ <Swatch label="blue-500" token="--bds-BASE__color--blue" bg="var(--bds-BASE__color--blue)" text="white" />
161
+ <Swatch label="blue-600" token="--bds-BASE__color--blue--600" bg="var(--bds-BASE__color--blue--600)" text="white" />
162
+ <Swatch label="blue-700" token="--bds-BASE__color--blue--700" bg="var(--bds-BASE__color--blue--700)" text="white" />
163
+ <Swatch label="blue-800" token="--bds-BASE__color--blue--800" bg="var(--bds-BASE__color--blue--800)" text="white" />
164
+ <Swatch label="blue-900" token="--bds-BASE__color--blue--900" bg="var(--bds-BASE__color--blue--900)" text="white" />
165
+ </SwatchRow>
166
+
167
+ ### Orange
168
+
169
+ <SwatchRow>
170
+ <Swatch label="orange-100" token="--bds-BASE__color--orange--100" bg="var(--bds-BASE__color--orange--100)" />
171
+ <Swatch label="orange-200" token="--bds-BASE__color--orange--200" bg="var(--bds-BASE__color--orange--200)" />
172
+ <Swatch label="orange-300" token="--bds-BASE__color--orange--300" bg="var(--bds-BASE__color--orange--300)" />
173
+ <Swatch label="orange-400" token="--bds-BASE__color--orange--400" bg="var(--bds-BASE__color--orange--400)" />
174
+ <Swatch label="orange-500" token="--bds-BASE__color--orange" bg="var(--bds-BASE__color--orange)" />
175
+ <Swatch label="orange-600" token="--bds-BASE__color--orange--600" bg="var(--bds-BASE__color--orange--600)" text="white" />
176
+ <Swatch label="orange-700" token="--bds-BASE__color--orange--700" bg="var(--bds-BASE__color--orange--700)" text="white" />
177
+ <Swatch label="orange-800" token="--bds-BASE__color--orange--800" bg="var(--bds-BASE__color--orange--800)" text="white" />
178
+ <Swatch label="orange-900" token="--bds-BASE__color--orange--900" bg="var(--bds-BASE__color--orange--900)" text="white" />
179
+ </SwatchRow>
180
+
181
+ ---
182
+
183
+ ## Theming
184
+
185
+ Override `--bds-cta` (and its `on-` pair) to change the primary action colour globally:
186
+
187
+ ```css
188
+ @layer tokens.override {
189
+ :root {
190
+ --bds-cta: var(--bds-BASE__color--blue);
191
+ --bds-on-cta: var(--bds-BASE__color--white);
192
+ --bds-interactive: var(--bds-BASE__color--blue);
193
+ --bds-on-interactive: var(--bds-BASE__color--white);
194
+ }
195
+ }
196
+ ```
@@ -0,0 +1,127 @@
1
+ import { Meta } from '@storybook/blocks';
2
+
3
+ <Meta title="Design System/Elevation" />
4
+
5
+ export const ShadowCard = ({ token, label }) => (
6
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '0.75rem', alignItems: 'center' }}>
7
+ <div style={{
8
+ width: '8rem',
9
+ height: '5rem',
10
+ background: 'var(--bds-bg)',
11
+ borderRadius: '0.75rem',
12
+ boxShadow: `var(${token})`,
13
+ }} />
14
+ <div style={{ textAlign: 'center' }}>
15
+ <div style={{ fontSize: '0.8rem', fontWeight: 600 }}>{label}</div>
16
+ <div style={{ fontSize: '0.7rem', fontFamily: 'monospace', opacity: 0.6, marginTop: '0.1rem' }}>{token}</div>
17
+ </div>
18
+ </div>
19
+ );
20
+
21
+ export const RadiusBox = ({ token, label, value }) => (
22
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '0.75rem', alignItems: 'center' }}>
23
+ <div style={{
24
+ width: '4rem',
25
+ height: '4rem',
26
+ background: 'var(--bds-interactive)',
27
+ borderRadius: `var(${token})`,
28
+ opacity: 0.8,
29
+ }} />
30
+ <div style={{ textAlign: 'center' }}>
31
+ <div style={{ fontSize: '0.8rem', fontWeight: 600 }}>{label}</div>
32
+ <div style={{ fontSize: '0.7rem', fontFamily: 'monospace', opacity: 0.6 }}>{token}</div>
33
+ <div style={{ fontSize: '0.7rem', opacity: 0.5 }}>{value}</div>
34
+ </div>
35
+ </div>
36
+ );
37
+
38
+ export const ZRow = ({ token, value, description }) => (
39
+ <tr>
40
+ <td><code>{token}</code></td>
41
+ <td style={{ fontFamily: 'monospace' }}>{value}</td>
42
+ <td>{description}</td>
43
+ </tr>
44
+ );
45
+
46
+ # Elevation
47
+
48
+ ## Shadows
49
+
50
+ Five shadow levels from subtle to dramatic. All values adapt to dark mode (higher opacity for visibility against dark surfaces).
51
+
52
+ <div style={{ display: 'flex', gap: '2.5rem', flexWrap: 'wrap', padding: '2rem', background: 'var(--bds-bg--subtle)', borderRadius: '0.75rem', marginBottom: '2rem' }}>
53
+ <ShadowCard token="--bds-shadow_s" label="Small" />
54
+ <ShadowCard token="--bds-shadow_m" label="Medium" />
55
+ <ShadowCard token="--bds-shadow_l" label="Large" />
56
+ <ShadowCard token="--bds-shadow_xl" label="X-Large" />
57
+ <ShadowCard token="--bds-shadow_2xl" label="2X-Large" />
58
+ </div>
59
+
60
+ | Token | Light mode | Dark mode |
61
+ |-------|-----------|-----------|
62
+ | `--bds-shadow_s` | `0 1px 3px rgba(0,0,0,0.05)` | `0 2px 12px rgba(0,0,0,0.40)` |
63
+ | `--bds-shadow_m` | `0 2px 8px rgba(0,0,0,0.10)` | `0 4px 20px rgba(0,0,0,0.50)` |
64
+ | `--bds-shadow_l` | `0 4px 16px rgba(0,0,0,0.12)` | `0 8px 36px rgba(0,0,0,0.60)` |
65
+ | `--bds-shadow_xl` | `0 8px 24px rgba(0,0,0,0.15)` | `0 8px 28px rgba(0,0,0,0.50)` |
66
+ | `--bds-shadow_2xl` | `0 8px 32px rgba(0,0,0,0.16)` | `0 8px 32px rgba(0,0,0,0.65)` |
67
+
68
+ ---
69
+
70
+ ## Border radius
71
+
72
+ <div style={{ display: 'flex', gap: '2rem', flexWrap: 'wrap', padding: '2rem', background: 'var(--bds-bg--subtle)', borderRadius: '0.75rem', marginBottom: '2rem' }}>
73
+ <RadiusBox token="--bds-border_radius--xs" label="X-Small" value="0.25rem / 4px" />
74
+ <RadiusBox token="--bds-border_radius--s" label="Small" value="0.75rem / 12px" />
75
+ <RadiusBox token="--bds-border_radius--m" label="Medium" value="1rem / 16px" />
76
+ </div>
77
+
78
+ ---
79
+
80
+ ## Outline
81
+
82
+ Used for focus rings on interactive elements.
83
+
84
+ | Token | Value |
85
+ |-------|-------|
86
+ | `--bds-outline_default` | `2px dotted var(--bds-outline_color)` |
87
+ | `--bds-outline_color` | grey-600 (light) / grey-400 (dark) |
88
+ | `--bds-outline_offset` | `2px` |
89
+
90
+ ```css
91
+ .my-button:focus-visible {
92
+ outline: var(--bds-outline_default);
93
+ outline-offset: var(--bds-outline_offset);
94
+ }
95
+ ```
96
+
97
+ ---
98
+
99
+ ## Z-index
100
+
101
+ <table>
102
+ <thead>
103
+ <tr>
104
+ <th>Token</th>
105
+ <th>Value</th>
106
+ <th>Purpose</th>
107
+ </tr>
108
+ </thead>
109
+ <tbody>
110
+ <ZRow token="--bds-z-index_below" value="-1" description="Visually behind the page" />
111
+ <ZRow token="--bds-z-index_base" value="0" description="Default stacking context" />
112
+ <ZRow token="--bds-z-index_above" value="1" description="One step above base" />
113
+ <ZRow token="--bds-z-index_s" value="20" description="Sticky headers, minor overlays" />
114
+ <ZRow token="--bds-z-index_m" value="50" description="Dropdowns, popovers" />
115
+ <ZRow token="--bds-z-index_l" value="100" description="Navigation, drawers" />
116
+ <ZRow token="--bds-z-index_xl" value="200" description="Toasts, critical overlays" />
117
+ <ZRow token="--bds-z-index_dropdown" value="50" description="Role alias → m" />
118
+ <ZRow token="--bds-z-index_popover" value="50" description="Role alias → m" />
119
+ <ZRow token="--bds-z-index_nav" value="100" description="Role alias → l" />
120
+ <ZRow token="--bds-z-index_toast" value="200" description="Role alias → xl" />
121
+ </tbody>
122
+ </table>
123
+
124
+ ```css
125
+ .dropdown { z-index: var(--bds-z-index_dropdown); }
126
+ .toast { z-index: var(--bds-z-index_toast); }
127
+ ```
@@ -0,0 +1,140 @@
1
+ import { Meta } from '@storybook/blocks';
2
+
3
+ <Meta title="Design System/Grid" />
4
+
5
+ export const GridCell = ({ span, label, color = 'var(--bds-interactive)' }) => (
6
+ <div style={{
7
+ gridColumn: span,
8
+ background: color,
9
+ color: 'var(--bds-on-interactive)',
10
+ borderRadius: '0.25rem',
11
+ padding: '0.5rem 0.75rem',
12
+ fontSize: '0.75rem',
13
+ fontFamily: 'monospace',
14
+ opacity: 0.85,
15
+ }}>
16
+ {label}
17
+ </div>
18
+ );
19
+
20
+ export const GridDemo = ({ children }) => (
21
+ <div style={{
22
+ display: 'grid',
23
+ gridTemplateColumns: 'repeat(12, 1fr)',
24
+ gap: '0.5rem',
25
+ padding: '1rem',
26
+ background: 'var(--bds-bg--subtle)',
27
+ borderRadius: '0.5rem',
28
+ marginBottom: '1.5rem',
29
+ }}>
30
+ {children}
31
+ </div>
32
+ );
33
+
34
+ # Grid
35
+
36
+ The grid system is responsive and built entirely on CSS custom properties. It adapts from 4 columns on mobile to 12 columns on large screens.
37
+
38
+ ## Breakpoints
39
+
40
+ | Breakpoint | Columns | Gap |
41
+ |------------|---------|-----|
42
+ | `< 48rem` (mobile) | 4 | 1rem |
43
+ | `48rem+` (tablet) | 8 | 1.5rem |
44
+ | `64rem+` (desktop) | 12 | 2rem |
45
+
46
+ ## Tokens
47
+
48
+ | Token | Description |
49
+ |-------|-------------|
50
+ | `--bds-grid_columns` | Current column count (4 / 8 / 12) |
51
+ | `--bds-grid_gap` | Current gap (1rem / 1.5rem / 2rem) |
52
+ | `--bds-grid_template-columns` | `repeat(var(--bds-grid_columns), minmax(1rem, 1fr))` |
53
+ | `--bds-grid_span-100` | `1 / -1` — full width |
54
+ | `--bds-grid_span-75` | Approx. 75% — 3 of 4, 6 of 8, 9 of 12 columns |
55
+ | `--bds-grid_span-66` | Approx. 66% — 2 of 4 / 5 of 8 / 8 of 12 |
56
+ | `--bds-grid_span-50` | Approx. 50% — 2 / 4 / 6 columns |
57
+ | `--bds-grid_span-33` | Approx. 33% — 1 / 3 / 4 columns |
58
+ | `--bds-grid_span-25` | Approx. 25% — 1 / 2 / 3 columns |
59
+
60
+ ## Visual examples (shown at 12-column scale)
61
+
62
+ ### Full width — `--bds-grid_span-100`
63
+
64
+ <GridDemo>
65
+ <GridCell span="1 / -1" label="span 100%" />
66
+ </GridDemo>
67
+
68
+ ### 75% — `--bds-grid_span-75`
69
+
70
+ <GridDemo>
71
+ <GridCell span="span 9" label="span 75%" />
72
+ <GridCell span="span 3" label="25%" color="var(--bds-grey)" />
73
+ </GridDemo>
74
+
75
+ ### Two thirds — `--bds-grid_span-66`
76
+
77
+ <GridDemo>
78
+ <GridCell span="span 8" label="span 66%" />
79
+ <GridCell span="span 4" label="33%" color="var(--bds-grey)" />
80
+ </GridDemo>
81
+
82
+ ### Half and half — `--bds-grid_span-50`
83
+
84
+ <GridDemo>
85
+ <GridCell span="span 6" label="span 50%" />
86
+ <GridCell span="span 6" label="span 50%" />
87
+ </GridDemo>
88
+
89
+ ### Thirds — `--bds-grid_span-33`
90
+
91
+ <GridDemo>
92
+ <GridCell span="span 4" label="33%" />
93
+ <GridCell span="span 4" label="33%" />
94
+ <GridCell span="span 4" label="33%" />
95
+ </GridDemo>
96
+
97
+ ### Quarters — `--bds-grid_span-25`
98
+
99
+ <GridDemo>
100
+ <GridCell span="span 3" label="25%" />
101
+ <GridCell span="span 3" label="25%" />
102
+ <GridCell span="span 3" label="25%" />
103
+ <GridCell span="span 3" label="25%" />
104
+ </GridDemo>
105
+
106
+ ---
107
+
108
+ ## Utility classes
109
+
110
+ Apply the built-in layout utilities to use the grid system without writing CSS:
111
+
112
+ ```html
113
+ <div class="utl-page-grid"> <!-- full-width stacked outer layout -->
114
+ <main class="utl-main-grid"> <!-- responsive CSS grid with padding + max-width -->
115
+ <div class="utl-column" style="--size: var(--bds-grid_span-66)">
116
+ Two thirds content
117
+ </div>
118
+ <aside class="utl-column" style="--size: var(--bds-grid_span-33)">
119
+ One third sidebar
120
+ </aside>
121
+ </main>
122
+ </div>
123
+ ```
124
+
125
+ ## Custom grid usage
126
+
127
+ ```css
128
+ .my-layout {
129
+ display: grid;
130
+ grid-template-columns: var(--bds-grid_template-columns);
131
+ gap: var(--bds-grid_gap);
132
+ }
133
+
134
+ .sidebar { grid-column: var(--bds-grid_span-25); }
135
+ .main { grid-column: var(--bds-grid_span-75); }
136
+ ```
137
+
138
+ ## Sticky position
139
+
140
+ `--bds-sticky_inset-start: 5rem` — the default top offset for sticky elements (accounts for a fixed nav bar).