@gtivr4/a1-design-system-react 0.1.0 → 0.2.4

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 (111) hide show
  1. package/guidelines/Guidelines.md +228 -0
  2. package/package.json +4 -1
  3. package/src/breakpoints.css +29 -0
  4. package/src/color-scheme.css +586 -24
  5. package/src/components/accordion/Accordion.jsx +80 -0
  6. package/src/components/accordion/accordion.css +118 -0
  7. package/src/components/banner/Banner.jsx +66 -0
  8. package/src/components/banner/banner.css +205 -0
  9. package/src/components/bleed/Bleed.jsx +27 -0
  10. package/src/components/bleed/bleed.css +5 -0
  11. package/src/components/blockquote/Blockquote.jsx +40 -0
  12. package/src/components/blockquote/blockquote.css +166 -0
  13. package/src/components/breadcrumb/Breadcrumb.jsx +82 -0
  14. package/src/components/breadcrumb/breadcrumb.css +133 -0
  15. package/src/components/button/button.css +42 -12
  16. package/src/components/button-container/ButtonContainer.jsx +20 -1
  17. package/src/components/button-container/button-container.css +19 -1
  18. package/src/components/calendar/Calendar.jsx +383 -0
  19. package/src/components/calendar/calendar.css +225 -0
  20. package/src/components/card/Card.jsx +50 -12
  21. package/src/components/card/card.css +178 -14
  22. package/src/components/checkbox-group/CheckboxGroup.jsx +120 -0
  23. package/src/components/checkbox-group/checkbox-group.css +304 -0
  24. package/src/components/cluster/Cluster.jsx +52 -0
  25. package/src/components/cluster/cluster.css +9 -0
  26. package/src/components/code/Code.jsx +135 -0
  27. package/src/components/code/code.css +60 -0
  28. package/src/components/data-table/DataTable.jsx +721 -0
  29. package/src/components/data-table/DataTableFilters.jsx +339 -0
  30. package/src/components/data-table/data-table-filters.css +259 -0
  31. package/src/components/data-table/data-table.css +425 -0
  32. package/src/components/dialog/Dialog.jsx +45 -2
  33. package/src/components/dialog/dialog.css +13 -4
  34. package/src/components/divider/Divider.jsx +64 -0
  35. package/src/components/divider/divider.css +170 -0
  36. package/src/components/field/CreditCardField.jsx +131 -0
  37. package/src/components/field/DateField.jsx +11 -0
  38. package/src/components/field/NumberField.jsx +11 -0
  39. package/src/components/field/PhoneField.jsx +107 -0
  40. package/src/components/field/SelectField.jsx +86 -0
  41. package/src/components/field/TextField.jsx +83 -0
  42. package/src/components/field/TextareaField.jsx +147 -0
  43. package/src/components/field/TimeField.jsx +11 -0
  44. package/src/components/field/ZipField.jsx +114 -0
  45. package/src/components/field/credit-card.css +30 -0
  46. package/src/components/field/field.css +380 -0
  47. package/src/components/field/textarea-field.css +185 -0
  48. package/src/components/field-row/FieldRow.jsx +23 -0
  49. package/src/components/field-row/field-row.css +51 -0
  50. package/src/components/fieldset/Fieldset.jsx +49 -0
  51. package/src/components/fieldset/fieldset.css +75 -0
  52. package/src/components/figure/Figure.jsx +63 -0
  53. package/src/components/figure/figure.css +97 -0
  54. package/src/components/grid/Grid.jsx +36 -2
  55. package/src/components/grid/grid.css +129 -4
  56. package/src/components/heading/Heading.jsx +41 -1
  57. package/src/components/heading/heading.css +65 -4
  58. package/src/components/icon/icon.css +1 -0
  59. package/src/components/icon-button/icon-button.css +1 -0
  60. package/src/components/inline/inline.css +51 -0
  61. package/src/components/inline-editable/InlineEditable.jsx +77 -0
  62. package/src/components/inline-editable/inline-editable.css +47 -0
  63. package/src/components/inset/Inset.jsx +27 -0
  64. package/src/components/inset/inset.css +6 -0
  65. package/src/components/labels/Labels.jsx +5 -5
  66. package/src/components/link/Link.jsx +2 -3
  67. package/src/components/link/link.css +30 -1
  68. package/src/components/list/List.jsx +92 -0
  69. package/src/components/list/list.css +178 -0
  70. package/src/components/menu/Menu.jsx +243 -10
  71. package/src/components/menu/menu.css +157 -17
  72. package/src/components/message/Message.jsx +25 -50
  73. package/src/components/message/message.css +50 -33
  74. package/src/components/notification/Notification.jsx +1 -1
  75. package/src/components/page-layout/PageLayout.jsx +16 -1
  76. package/src/components/page-layout/page-layout.css +97 -4
  77. package/src/components/page-nav/PageNav.jsx +110 -0
  78. package/src/components/page-nav/page-nav.css +167 -0
  79. package/src/components/paragraph/Paragraph.jsx +35 -2
  80. package/src/components/paragraph/paragraph.css +38 -1
  81. package/src/components/radio-group/RadioGroup.jsx +121 -0
  82. package/src/components/radio-group/radio-group.css +268 -0
  83. package/src/components/section/Section.jsx +108 -0
  84. package/src/components/section/section.css +280 -0
  85. package/src/components/segmented-control/SegmentedControl.jsx +4 -0
  86. package/src/components/segmented-control/segmented.css +13 -0
  87. package/src/components/side-nav/SideNav.jsx +29 -9
  88. package/src/components/side-nav/scrim.css +1 -1
  89. package/src/components/side-nav/side-nav.css +70 -32
  90. package/src/components/snackbar/Snackbar.jsx +56 -0
  91. package/src/components/snackbar/snackbar.css +113 -0
  92. package/src/components/spacer/Spacer.jsx +36 -0
  93. package/src/components/spacer/spacer.css +44 -0
  94. package/src/components/stack/Stack.jsx +100 -0
  95. package/src/components/stack/stack.css +37 -0
  96. package/src/components/switch/Switch.jsx +114 -0
  97. package/src/components/switch/switch.css +276 -0
  98. package/src/components/system-banner/SystemBanner.jsx +57 -0
  99. package/src/components/system-banner/system-banner.css +118 -0
  100. package/src/components/tabs/Tabs.jsx +96 -28
  101. package/src/components/tabs/tabs.css +352 -15
  102. package/src/components/token-select/TokenSelect.jsx +159 -0
  103. package/src/components/token-select/token-select.css +110 -0
  104. package/src/components/top-header/TopHeader.jsx +641 -0
  105. package/src/components/top-header/top-header.css +337 -0
  106. package/src/illustrations/ComponentThumbnails.jsx +227 -0
  107. package/src/index.js +41 -5
  108. package/src/themes.css +256 -5
  109. package/src/tokens.css +919 -0
  110. package/src/utilities/spacing.css +8 -0
  111. package/src/utilities/sr-only.css +16 -0
@@ -0,0 +1,268 @@
1
+ /* ─── RadioGroup ───────────────────────────────────────────────────────────── */
2
+
3
+ .a1-radio-group {
4
+ border: none;
5
+ margin: 0;
6
+ padding: 0;
7
+ min-width: 0;
8
+
9
+ /* Size tokens — default */
10
+ --a1-rb-size: var(--component-radio-group-control-size);
11
+ --a1-rb-gap: var(--component-radio-group-gap); /* horizontal gap: circle ↔ text */
12
+ --a1-rb-item-gap: var(--component-radio-group-item-gap); /* gap between items */
13
+ --a1-rb-group-gap: var(--component-radio-group-group-gap); /* vertical gap between legend/hint and message */
14
+ --a1-rb-items-top-gap: var(--component-radio-group-items-top-gap); /* extra space between legend/hint and the items stack */
15
+ --a1-rb-input-nudge: var(--component-radio-group-input-nudge); /* top margin aligning circle center with label cap-height */
16
+ --a1-rb-row-py: var(--component-radio-group-row-padding-block); /* vertical padding on each item row */
17
+ --a1-rb-row-px: var(--component-radio-group-row-padding-inline); /* horizontal padding on each item row */
18
+ --a1-rb-legend-size: var(--semantic-font-size-body-sm);
19
+ --a1-rb-label-size: var(--semantic-font-size-body-md);
20
+ --a1-rb-hint-size: var(--semantic-font-size-body-xs);
21
+ --a1-rb-msg-size: var(--semantic-font-size-body-xs);
22
+
23
+ display: flex;
24
+ flex-direction: column;
25
+ gap: var(--a1-rb-group-gap);
26
+ }
27
+
28
+ /* ─── Sizes ───────────────────────────────────────────────────────────────── */
29
+
30
+ .a1-radio-group--comfortable {
31
+ --a1-rb-size: var(--component-radio-group-comfortable-control-size);
32
+ --a1-rb-gap: var(--component-radio-group-comfortable-gap);
33
+ --a1-rb-item-gap: var(--component-radio-group-comfortable-item-gap);
34
+ --a1-rb-group-gap: var(--component-radio-group-comfortable-group-gap);
35
+ --a1-rb-items-top-gap: var(--component-radio-group-comfortable-items-top-gap);
36
+ --a1-rb-input-nudge: var(--component-radio-group-comfortable-input-nudge);
37
+ --a1-rb-row-py: var(--component-radio-group-comfortable-row-padding-block);
38
+ --a1-rb-row-px: var(--component-radio-group-comfortable-row-padding-inline);
39
+ --a1-rb-legend-size: var(--semantic-font-size-body-md);
40
+ --a1-rb-label-size: var(--semantic-font-size-body-md);
41
+ --a1-rb-hint-size: var(--semantic-font-size-body-sm);
42
+ --a1-rb-msg-size: var(--semantic-font-size-body-sm);
43
+ }
44
+
45
+ .a1-radio-group--comfortable .a1-radio-item__label {
46
+ font-weight: var(--base-font-weight-medium);
47
+ }
48
+
49
+ @media (--bp-md-up) {
50
+ .a1-radio-group--comfortable {
51
+ --a1-rb-legend-size: var(--semantic-font-size-body-lg);
52
+ --a1-rb-label-size: var(--semantic-font-size-body-lg);
53
+ --a1-rb-size: var(--component-radio-group-comfortable-control-size-md);
54
+ --a1-rb-input-nudge: var(--component-radio-group-comfortable-input-nudge);
55
+ }
56
+ }
57
+
58
+ .a1-radio-group--compact {
59
+ --a1-rb-size: var(--component-radio-group-compact-control-size);
60
+ --a1-rb-gap: var(--component-radio-group-compact-gap);
61
+ --a1-rb-item-gap: var(--component-radio-group-compact-item-gap);
62
+ --a1-rb-group-gap: var(--component-radio-group-compact-group-gap);
63
+ --a1-rb-items-top-gap: var(--component-radio-group-compact-items-top-gap);
64
+ --a1-rb-input-nudge: var(--component-radio-group-compact-input-nudge);
65
+ --a1-rb-row-py: var(--component-radio-group-compact-row-padding-block);
66
+ --a1-rb-row-px: var(--component-radio-group-compact-row-padding-inline);
67
+ --a1-rb-legend-size: var(--semantic-font-size-body-xs);
68
+ --a1-rb-label-size: var(--semantic-font-size-body-sm);
69
+ --a1-rb-hint-size: var(--semantic-font-size-body-xs);
70
+ --a1-rb-msg-size: var(--semantic-font-size-body-xs);
71
+ }
72
+
73
+ /* ─── Legend ──────────────────────────────────────────────────────────────── */
74
+
75
+ .a1-radio-group__legend {
76
+ display: block;
77
+ width: 100%;
78
+ padding: 0;
79
+ font-family: var(--component-paragraph-font-family);
80
+ font-size: var(--a1-rb-legend-size);
81
+ font-weight: var(--component-field-label-font-weight);
82
+ color: var(--semantic-color-text-default);
83
+ line-height: var(--semantic-font-line-height-body);
84
+ }
85
+
86
+ .a1-radio-group--disabled .a1-radio-group__legend {
87
+ color: var(--semantic-color-text-muted);
88
+ }
89
+
90
+ .a1-radio-group__legend-inner {
91
+ display: inline-flex;
92
+ align-items: center;
93
+ gap: var(--base-spacing-6);
94
+ }
95
+
96
+ /* ─── Group hint / error message ──────────────────────────────────────────── */
97
+
98
+ .a1-radio-group__message {
99
+ margin: 0;
100
+ font-family: var(--component-paragraph-font-family);
101
+ font-size: var(--a1-rb-msg-size);
102
+ line-height: var(--semantic-font-line-height-body);
103
+ }
104
+
105
+ .a1-radio-group__message--hint { color: var(--semantic-color-text-muted); }
106
+ .a1-radio-group__message--error { color: var(--semantic-color-status-error-background); }
107
+
108
+ /* ─── Items stack ─────────────────────────────────────────────────────────── */
109
+
110
+ .a1-radio-group__items {
111
+ display: flex;
112
+ flex-direction: column;
113
+ gap: var(--a1-rb-item-gap);
114
+ margin-top: var(--a1-rb-items-top-gap);
115
+ }
116
+
117
+ /* ─── Individual item ─────────────────────────────────────────────────────── */
118
+
119
+ .a1-radio-item {
120
+ display: flex;
121
+ align-items: flex-start;
122
+ gap: var(--a1-rb-gap);
123
+ padding: var(--a1-rb-row-py) var(--a1-rb-row-px);
124
+ margin-inline: calc(-1 * var(--a1-rb-row-px));
125
+ border-radius: var(--base-radius-md);
126
+ cursor: pointer;
127
+ transition: background-color var(--semantic-motion-duration-fast);
128
+ }
129
+
130
+ .a1-radio-item--disabled {
131
+ cursor: not-allowed;
132
+ }
133
+
134
+ .a1-radio-item__content {
135
+ display: flex;
136
+ flex-direction: column;
137
+ gap: var(--component-radio-group-content-gap);
138
+ }
139
+
140
+ .a1-radio-item__label {
141
+ font-family: var(--component-paragraph-font-family);
142
+ font-size: var(--a1-rb-label-size);
143
+ font-weight: var(--base-font-weight-regular);
144
+ color: var(--semantic-color-text-muted);
145
+ line-height: var(--semantic-font-line-height-body);
146
+ }
147
+
148
+ /* Restore default color when the item is selected */
149
+ .a1-radio-item:has(.a1-radio-item__input:checked) .a1-radio-item__label {
150
+ color: var(--semantic-color-text-default);
151
+ }
152
+
153
+ /* Disabled always stays muted regardless of checked state */
154
+ .a1-radio-item--disabled .a1-radio-item__label {
155
+ color: var(--semantic-color-text-muted);
156
+ }
157
+
158
+ .a1-radio-item__hint {
159
+ font-family: var(--component-paragraph-font-family);
160
+ font-size: var(--a1-rb-hint-size);
161
+ font-weight: var(--base-font-weight-regular);
162
+ color: var(--semantic-color-text-muted);
163
+ line-height: var(--semantic-font-line-height-body);
164
+ }
165
+
166
+ /* ─── Radio input ─────────────────────────────────────────────────────────── */
167
+
168
+ .a1-radio-item__input {
169
+ -webkit-appearance: none;
170
+ appearance: none;
171
+ flex-shrink: 0;
172
+ width: var(--a1-rb-size);
173
+ height: var(--a1-rb-size);
174
+ margin-top: var(--a1-rb-input-nudge);
175
+ border: var(--component-field-border-width) solid var(--semantic-color-border-strong);
176
+ border-radius: 50%;
177
+ background-color: var(--semantic-color-surface-page);
178
+ cursor: pointer;
179
+ transition:
180
+ border-color var(--semantic-motion-duration-fast),
181
+ background-color var(--semantic-motion-duration-fast);
182
+ }
183
+
184
+ /* Selected row — tinted background, no further interaction */
185
+ .a1-radio-item:not(.a1-radio-item--disabled):has(.a1-radio-item__input:checked) {
186
+ background-color: var(--a1-field-hover-background);
187
+ cursor: default;
188
+ }
189
+
190
+ .a1-radio-item:not(.a1-radio-item--disabled):has(.a1-radio-item__input:checked)
191
+ .a1-radio-item__input {
192
+ cursor: default;
193
+ }
194
+
195
+ /* Hover — entire row background (unselected only) */
196
+ .a1-radio-item:not(.a1-radio-item--disabled):not(:has(.a1-radio-item__input:checked)):hover {
197
+ background-color: var(--a1-field-hover-background);
198
+ }
199
+
200
+ /* Darken the input border on row hover (unselected only) */
201
+ .a1-radio-item:not(.a1-radio-item--disabled):not(:has(.a1-radio-item__input:checked)):hover
202
+ .a1-radio-item__input {
203
+ border-color: var(--a1-field-hover-border-color);
204
+ }
205
+
206
+ /* Focus */
207
+ .a1-radio-item__input:focus-visible {
208
+ outline: var(--component-field-focus-ring-width) solid var(--component-field-focus-ring-color);
209
+ outline-offset: var(--component-field-focus-ring-offset);
210
+ }
211
+
212
+ /* Selected */
213
+ .a1-radio-item__input:checked {
214
+ background-color: var(--semantic-color-status-info-background);
215
+ border-color: var(--semantic-color-status-info-background);
216
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 10'%3E%3Ccircle cx='5' cy='5' r='5' fill='%23fafcff'/%3E%3C%2Fsvg%3E");
217
+ background-repeat: no-repeat;
218
+ background-position: center;
219
+ background-size: var(--component-radio-group-dot-size);
220
+ }
221
+
222
+ /* Disabled (unselected) */
223
+ .a1-radio-item__input:disabled {
224
+ background-color: var(--semantic-color-surface-raised);
225
+ border-color: var(--semantic-color-border-subtle);
226
+ cursor: not-allowed;
227
+ }
228
+
229
+ /* Disabled + selected */
230
+ .a1-radio-item__input:checked:disabled {
231
+ background-color: var(--semantic-color-border-default);
232
+ border-color: var(--semantic-color-border-default);
233
+ }
234
+
235
+ /* ─── Inline layout ───────────────────────────────────────────────────────── */
236
+
237
+ .a1-radio-group--inline .a1-radio-group__items {
238
+ flex-direction: row;
239
+ flex-wrap: wrap;
240
+ gap: var(--a1-rb-gap);
241
+ }
242
+
243
+ .a1-radio-group--inline .a1-radio-item {
244
+ margin-inline: 0;
245
+ }
246
+
247
+ /* Inline error — left accent doesn't suit a row layout */
248
+ .a1-radio-group--inline.a1-radio-group--error .a1-radio-group__items {
249
+ border-left: none;
250
+ padding-left: 0;
251
+ }
252
+
253
+ /* ─── Error state ─────────────────────────────────────────────────────────── */
254
+
255
+ .a1-radio-group--error .a1-radio-group__items {
256
+ border-left: var(--component-radio-group-error-accent-width) solid var(--semantic-color-status-error-background);
257
+ padding-left: var(--base-spacing-12);
258
+ }
259
+
260
+ /* Unselected items get a red border */
261
+ .a1-radio-group--error .a1-radio-item__input:not(:checked):not(:disabled) {
262
+ border-color: var(--semantic-color-status-error-border);
263
+ }
264
+
265
+ /* Bolder error message */
266
+ .a1-radio-group__message--error {
267
+ font-weight: var(--component-radio-group-error-message-font-weight);
268
+ }
@@ -0,0 +1,108 @@
1
+ import "../../themes.css";
2
+ import "../../color-scheme.css";
3
+ import "./section.css";
4
+
5
+ const VALID_PADDING = ["lg", "md", "sm", "none"];
6
+ const VALID_SURFACES = ["page", "panel", "raised"];
7
+ const VALID_GAPS = ["xs", "sm", "md", "lg"];
8
+ const VALID_GRADIENTS = ["accent", "highlight", "info", "success", "warn"];
9
+ const VALID_GRADIENT_POSITIONS = [
10
+ "top",
11
+ "top-right",
12
+ "right",
13
+ "bottom-right",
14
+ "bottom",
15
+ "bottom-left",
16
+ "left",
17
+ "top-left",
18
+ "center",
19
+ ];
20
+ const VALID_CONTENT_WIDTHS = ["xs", "sm", "md", "lg", "xl", "2xl"];
21
+ const VALID_HEIGHTS = ["screen", "hero"];
22
+ const VALID_ALIGNMENTS = ["left", "center", "right"];
23
+
24
+ export function Section({
25
+ as: Component = "section",
26
+ padding = "md",
27
+ surface,
28
+ gap,
29
+ gradient,
30
+ gradientPosition = "center",
31
+ inverse = false,
32
+ contentWidth,
33
+ height,
34
+ alignment,
35
+ className = "",
36
+ children,
37
+ ...props
38
+ }) {
39
+ const classes = ["a1-section"];
40
+ const resolvedContentWidth = VALID_CONTENT_WIDTHS.includes(contentWidth) ? contentWidth : null;
41
+
42
+ if (typeof padding === "string") {
43
+ if (VALID_PADDING.includes(padding)) {
44
+ classes.push(`a1-section--padding-${padding}`);
45
+ }
46
+ } else if (padding && typeof padding === "object") {
47
+ for (const [bp, size] of Object.entries(padding)) {
48
+ if (VALID_PADDING.includes(size)) {
49
+ classes.push(`a1-section--${bp}-padding-${size}`);
50
+ }
51
+ }
52
+ }
53
+
54
+ if (surface && VALID_SURFACES.includes(surface)) {
55
+ classes.push(`a1-section--surface-${surface}`);
56
+ }
57
+
58
+ // When contentWidth is set, gap moves to the inner wrapper — keep section flat.
59
+ if (gap && VALID_GAPS.includes(gap) && !resolvedContentWidth) {
60
+ classes.push(`a1-section--gap-${gap}`);
61
+ }
62
+
63
+ if (gradient && VALID_GRADIENTS.includes(gradient)) {
64
+ classes.push(`a1-section--gradient-${gradient}`);
65
+ }
66
+
67
+ if (gradient && VALID_GRADIENT_POSITIONS.includes(gradientPosition)) {
68
+ classes.push(`a1-section--gradient-${gradientPosition}`);
69
+ }
70
+
71
+ if (height && VALID_HEIGHTS.includes(height)) {
72
+ classes.push(`a1-section--height-${height}`);
73
+ }
74
+
75
+ if (typeof alignment === "string") {
76
+ if (VALID_ALIGNMENTS.includes(alignment)) {
77
+ classes.push(`a1-section--align-${alignment}`);
78
+ }
79
+ } else if (alignment && typeof alignment === "object") {
80
+ for (const [bp, align] of Object.entries(alignment)) {
81
+ if (VALID_ALIGNMENTS.includes(align)) {
82
+ classes.push(`a1-section--${bp}-align-${align}`);
83
+ }
84
+ }
85
+ }
86
+
87
+ if (inverse) {
88
+ classes.push("a1-inverse");
89
+ }
90
+
91
+ if (className) classes.push(className);
92
+
93
+ const innerClasses = [
94
+ "a1-section__inner",
95
+ resolvedContentWidth && `a1-section__inner--${resolvedContentWidth}`,
96
+ gap && VALID_GAPS.includes(gap) && `a1-section--gap-${gap}`,
97
+ ].filter(Boolean).join(" ");
98
+
99
+ return (
100
+ <Component className={classes.join(" ")} {...props}>
101
+ {resolvedContentWidth ? (
102
+ <div className={innerClasses}>
103
+ {children}
104
+ </div>
105
+ ) : children}
106
+ </Component>
107
+ );
108
+ }
@@ -0,0 +1,280 @@
1
+ /* ── Base ──────────────────────────────────────────────────────────────────── */
2
+
3
+ .a1-section {
4
+ box-sizing: border-box;
5
+ width: 100%;
6
+ --a1-section-surface: transparent;
7
+ --a1-section-gradient-color: transparent;
8
+ --a1-section-gradient-width: var(--component-section-gradient-center-width);
9
+ --a1-section-gradient-height: var(--component-section-gradient-center-height);
10
+ --a1-section-gradient-anchor: center;
11
+ --a1-section-gradient-strength: var(--component-section-gradient-strength);
12
+ --a1-section-justify-items: stretch;
13
+ }
14
+
15
+ .a1-section.a1-inverse {
16
+ --a1-section-surface: var(--semantic-color-surface-page);
17
+ --a1-section-gradient-strength: var(--component-section-gradient-strength-inverse);
18
+ }
19
+
20
+ /* ── Surface ───────────────────────────────────────────────────────────────── */
21
+
22
+ .a1-section--surface-page { --a1-section-surface: var(--semantic-color-surface-page); background: var(--a1-section-surface); }
23
+ .a1-section--surface-panel { --a1-section-surface: var(--semantic-color-surface-panel); background: var(--a1-section-surface); }
24
+ .a1-section--surface-raised { --a1-section-surface: var(--semantic-color-surface-raised); background: var(--a1-section-surface); }
25
+
26
+ /* ── Gradient wash ─────────────────────────────────────────────────────────── */
27
+
28
+ .a1-section--gradient-accent { --a1-section-gradient-color: var(--semantic-color-action-background); }
29
+ .a1-section--gradient-highlight { --a1-section-gradient-color: var(--base-color-highlited-200); }
30
+ .a1-section--gradient-info { --a1-section-gradient-color: var(--semantic-color-status-info-background); }
31
+ .a1-section--gradient-success { --a1-section-gradient-color: var(--semantic-color-status-success-background); }
32
+ .a1-section--gradient-warn { --a1-section-gradient-color: var(--semantic-color-status-warn-background); }
33
+
34
+ .a1-section--gradient-top,
35
+ .a1-section--gradient-top-right,
36
+ .a1-section--gradient-right,
37
+ .a1-section--gradient-bottom-right,
38
+ .a1-section--gradient-bottom,
39
+ .a1-section--gradient-bottom-left,
40
+ .a1-section--gradient-top-left,
41
+ .a1-section--gradient-left {
42
+ --a1-section-gradient-width: var(--component-section-gradient-edge-width);
43
+ --a1-section-gradient-height: var(--component-section-gradient-edge-height);
44
+ }
45
+
46
+ .a1-section--gradient-top { --a1-section-gradient-anchor: top center; }
47
+ .a1-section--gradient-top-right { --a1-section-gradient-anchor: top right; }
48
+ .a1-section--gradient-right { --a1-section-gradient-anchor: right center; }
49
+ .a1-section--gradient-bottom-right { --a1-section-gradient-anchor: bottom right; }
50
+ .a1-section--gradient-bottom { --a1-section-gradient-anchor: bottom center; }
51
+ .a1-section--gradient-bottom-left { --a1-section-gradient-anchor: bottom left; }
52
+ .a1-section--gradient-left { --a1-section-gradient-anchor: left center; }
53
+ .a1-section--gradient-top-left { --a1-section-gradient-anchor: top left; }
54
+ .a1-section--gradient-center { --a1-section-gradient-anchor: center; }
55
+
56
+ .a1-section[class*="a1-section--gradient-"] {
57
+ background:
58
+ radial-gradient(
59
+ ellipse var(--a1-section-gradient-width) var(--a1-section-gradient-height) at var(--a1-section-gradient-anchor),
60
+ color-mix(in srgb, var(--a1-section-gradient-color) calc(var(--a1-section-gradient-strength) * 1%), transparent) 0%,
61
+ transparent calc(var(--component-section-gradient-fade) * 1%)
62
+ ),
63
+ var(--a1-section-surface, var(--semantic-color-surface-page));
64
+ }
65
+
66
+ /* ── Content gap ──────────────────────────────────────────────────────────── */
67
+
68
+ .a1-section--gap-xs,
69
+ .a1-section--gap-sm,
70
+ .a1-section--gap-md,
71
+ .a1-section--gap-lg {
72
+ display: grid;
73
+ justify-items: var(--a1-section-justify-items);
74
+ }
75
+
76
+ .a1-section--gap-xs { gap: var(--semantic-spacing-gap-xs); }
77
+ .a1-section--gap-sm { gap: var(--semantic-spacing-gap-sm); }
78
+ .a1-section--gap-md { gap: var(--semantic-spacing-gap-md); }
79
+ .a1-section--gap-lg { gap: var(--semantic-spacing-gap-lg); }
80
+
81
+ /* ── Height ────────────────────────────────────────────────────────────────── */
82
+
83
+ .a1-section--height-screen {
84
+ min-height: 100svh;
85
+ }
86
+
87
+ /* Fills the viewport minus the sticky top header — use for hero/landing sections. */
88
+ .a1-section--height-hero {
89
+ min-block-size: calc(90svh - var(--component-top-header-height));
90
+ display: grid;
91
+ align-content: center;
92
+ }
93
+
94
+ /* ── Content width ─────────────────────────────────────────────────────────── */
95
+
96
+ .a1-section__inner {
97
+ display: grid;
98
+ justify-items: var(--a1-section-justify-items);
99
+ width: 100%;
100
+ margin-inline: auto;
101
+ box-sizing: border-box;
102
+ }
103
+
104
+ .a1-section__inner--xs { max-width: 28.5rem; }
105
+ .a1-section__inner--sm { max-width: 40rem; }
106
+ .a1-section__inner--md { max-width: 50rem; }
107
+ .a1-section__inner--lg { max-width: 60rem; }
108
+ .a1-section__inner--xl { max-width: 70rem; }
109
+ .a1-section__inner--2xl { max-width: 90rem; }
110
+
111
+ /* ── Alignment ─────────────────────────────────────────────────────────────── */
112
+ /*
113
+ * Aligns direct children as layout items.
114
+ * Use the object prop for responsive changes: alignment={{ xs: "center", lg: "left" }}
115
+ */
116
+
117
+ .a1-section[class*="-align-"] {
118
+ display: grid;
119
+ justify-items: var(--a1-section-justify-items);
120
+ }
121
+
122
+ .a1-section--align-left {
123
+ --a1-section-justify-items: start;
124
+ }
125
+
126
+ .a1-section--align-center {
127
+ --a1-section-justify-items: center;
128
+ }
129
+
130
+ .a1-section--align-right {
131
+ --a1-section-justify-items: end;
132
+ }
133
+
134
+ /* xs: base, no media query */
135
+ .a1-section--xs-align-left {
136
+ --a1-section-justify-items: start;
137
+ }
138
+
139
+ .a1-section--xs-align-center {
140
+ --a1-section-justify-items: center;
141
+ }
142
+
143
+ .a1-section--xs-align-right {
144
+ --a1-section-justify-items: end;
145
+ }
146
+
147
+ /* sm: ≥481px */
148
+ @media (--bp-sm-up) {
149
+ .a1-section--sm-align-left {
150
+ --a1-section-justify-items: start;
151
+ }
152
+
153
+ .a1-section--sm-align-center {
154
+ --a1-section-justify-items: center;
155
+ }
156
+
157
+ .a1-section--sm-align-right {
158
+ --a1-section-justify-items: end;
159
+ }
160
+ }
161
+
162
+ /* md: ≥641px */
163
+ @media (--bp-md-up) {
164
+ .a1-section--md-align-left {
165
+ --a1-section-justify-items: start;
166
+ }
167
+
168
+ .a1-section--md-align-center {
169
+ --a1-section-justify-items: center;
170
+ }
171
+
172
+ .a1-section--md-align-right {
173
+ --a1-section-justify-items: end;
174
+ }
175
+ }
176
+
177
+ /* lg: ≥1025px */
178
+ @media (--bp-lg-up) {
179
+ .a1-section--lg-align-left {
180
+ --a1-section-justify-items: start;
181
+ }
182
+
183
+ .a1-section--lg-align-center {
184
+ --a1-section-justify-items: center;
185
+ }
186
+
187
+ .a1-section--lg-align-right {
188
+ --a1-section-justify-items: end;
189
+ }
190
+ }
191
+
192
+ /* xl: ≥1441px */
193
+ @media (--bp-xl-up) {
194
+ .a1-section--xl-align-left {
195
+ --a1-section-justify-items: start;
196
+ }
197
+
198
+ .a1-section--xl-align-center {
199
+ --a1-section-justify-items: center;
200
+ }
201
+
202
+ .a1-section--xl-align-right {
203
+ --a1-section-justify-items: end;
204
+ }
205
+ }
206
+
207
+ /* ── Padding — static (with built-in responsive scaling) ───────────────────── */
208
+ /*
209
+ * Three tiers scale across three breakpoints:
210
+ * lg 96/64 → 96/40 at ≤1024 → 64/24 at ≤640
211
+ * md 64/40 → 40/24 at ≤1024 → 32/16 at ≤640
212
+ * sm 32/24 → 24/16 at ≤1024 → 16/12 at ≤640
213
+ * Block (top/bottom) / Inline (left/right)
214
+ */
215
+
216
+ .a1-section--padding-none {
217
+ padding: 0;
218
+ }
219
+
220
+ .a1-section--padding-sm {
221
+ padding-block: var(--base-spacing-32);
222
+ padding-inline: var(--base-spacing-24);
223
+ }
224
+
225
+ .a1-section--padding-md {
226
+ padding-block: var(--base-spacing-64);
227
+ padding-inline: var(--base-spacing-40);
228
+ }
229
+
230
+ .a1-section--padding-lg {
231
+ padding-block: var(--base-spacing-96);
232
+ padding-inline: var(--base-spacing-64);
233
+ }
234
+
235
+ @media (--bp-md-down) {
236
+ .a1-section--padding-sm { padding-block: var(--base-spacing-24); padding-inline: var(--base-spacing-16); }
237
+ .a1-section--padding-md { padding-block: var(--base-spacing-40); padding-inline: var(--base-spacing-24); }
238
+ .a1-section--padding-lg { padding-block: var(--base-spacing-64); padding-inline: var(--base-spacing-40); }
239
+ }
240
+
241
+ @media (--bp-sm-down) {
242
+ .a1-section--padding-sm { padding-block: var(--base-spacing-16); padding-inline: var(--base-spacing-12); }
243
+ .a1-section--padding-md { padding-block: var(--base-spacing-24); padding-inline: var(--base-spacing-16); }
244
+ .a1-section--padding-lg { padding-block: var(--base-spacing-40); padding-inline: var(--base-spacing-24); }
245
+ }
246
+
247
+ /* ── Padding — responsive modifiers (mobile-first overrides, no auto-scaling) ─
248
+ * Use when the padding object prop is passed: padding={{ xs: "sm", lg: "lg" }}
249
+ * Each modifier applies the raw padding at or above that breakpoint.
250
+ */
251
+
252
+ /* xs: base, no media query */
253
+ .a1-section--xs-padding-none { padding: 0; }
254
+ .a1-section--xs-padding-sm { padding-block: var(--base-spacing-32); padding-inline: var(--base-spacing-24); }
255
+ .a1-section--xs-padding-md { padding-block: var(--base-spacing-64); padding-inline: var(--base-spacing-40); }
256
+ .a1-section--xs-padding-lg { padding-block: var(--base-spacing-96); padding-inline: var(--base-spacing-64); }
257
+
258
+ /* sm: ≥481px */
259
+ @media (--bp-sm-up) {
260
+ .a1-section--sm-padding-none { padding: 0; }
261
+ .a1-section--sm-padding-sm { padding-block: var(--base-spacing-32); padding-inline: var(--base-spacing-24); }
262
+ .a1-section--sm-padding-md { padding-block: var(--base-spacing-64); padding-inline: var(--base-spacing-40); }
263
+ .a1-section--sm-padding-lg { padding-block: var(--base-spacing-96); padding-inline: var(--base-spacing-64); }
264
+ }
265
+
266
+ /* md: ≥769px */
267
+ @media (min-width: 769px) {
268
+ .a1-section--md-padding-none { padding: 0; }
269
+ .a1-section--md-padding-sm { padding-block: var(--base-spacing-24); padding-inline: var(--base-spacing-16); }
270
+ .a1-section--md-padding-md { padding-block: var(--base-spacing-40); padding-inline: var(--base-spacing-24); }
271
+ .a1-section--md-padding-lg { padding-block: var(--base-spacing-64); padding-inline: var(--base-spacing-40); }
272
+ }
273
+
274
+ /* lg: ≥1025px */
275
+ @media (--bp-lg-up) {
276
+ .a1-section--lg-padding-none { padding: 0; }
277
+ .a1-section--lg-padding-sm { padding-block: var(--base-spacing-32); padding-inline: var(--base-spacing-24); }
278
+ .a1-section--lg-padding-md { padding-block: var(--base-spacing-64); padding-inline: var(--base-spacing-40); }
279
+ .a1-section--lg-padding-lg { padding-block: var(--base-spacing-96); padding-inline: var(--base-spacing-64); }
280
+ }
@@ -10,6 +10,8 @@ export function SegmentedControl({
10
10
  value,
11
11
  onChange,
12
12
  fullWidth = false,
13
+ size,
14
+ ...props
13
15
  }) {
14
16
  const items = options.map(normalize);
15
17
 
@@ -41,10 +43,12 @@ export function SegmentedControl({
41
43
  role="radiogroup"
42
44
  className={[
43
45
  "a1-segmented",
46
+ size && `a1-segmented--${size}`,
44
47
  fullWidth && "a1-segmented--full-width",
45
48
  ]
46
49
  .filter(Boolean)
47
50
  .join(" ")}
51
+ {...props}
48
52
  onKeyDown={handleKeyDown}
49
53
  >
50
54
  {items.map((opt) => {