@gtivr4/a1-design-system-react 0.1.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 (45) hide show
  1. package/README.md +32 -0
  2. package/package.json +40 -0
  3. package/src/color-scheme.css +213 -0
  4. package/src/components/button/Button.jsx +45 -0
  5. package/src/components/button/button.css +135 -0
  6. package/src/components/button-container/ButtonContainer.jsx +27 -0
  7. package/src/components/button-container/button-container.css +38 -0
  8. package/src/components/card/Card.jsx +29 -0
  9. package/src/components/card/card.css +37 -0
  10. package/src/components/dialog/Dialog.jsx +44 -0
  11. package/src/components/dialog/dialog.css +58 -0
  12. package/src/components/grid/Grid.jsx +77 -0
  13. package/src/components/grid/grid.css +86 -0
  14. package/src/components/heading/Heading.jsx +69 -0
  15. package/src/components/heading/heading.css +76 -0
  16. package/src/components/icon/Icon.jsx +32 -0
  17. package/src/components/icon/icon.css +10 -0
  18. package/src/components/icon-button/IconButton.jsx +34 -0
  19. package/src/components/icon-button/icon-button.css +196 -0
  20. package/src/components/inverse/Inverse.jsx +18 -0
  21. package/src/components/labels/Labels.jsx +29 -0
  22. package/src/components/link/Link.jsx +41 -0
  23. package/src/components/link/link.css +50 -0
  24. package/src/components/menu/Menu.jsx +45 -0
  25. package/src/components/menu/menu.css +45 -0
  26. package/src/components/message/Message.jsx +103 -0
  27. package/src/components/message/message.css +226 -0
  28. package/src/components/notification/Notification.jsx +55 -0
  29. package/src/components/notification/notification.css +69 -0
  30. package/src/components/page-layout/PageLayout.jsx +40 -0
  31. package/src/components/page-layout/page-layout.css +61 -0
  32. package/src/components/pagination/Pagination.jsx +64 -0
  33. package/src/components/pagination/pagination.css +85 -0
  34. package/src/components/paragraph/Paragraph.jsx +26 -0
  35. package/src/components/paragraph/paragraph.css +16 -0
  36. package/src/components/segmented-control/SegmentedControl.jsx +77 -0
  37. package/src/components/segmented-control/segmented.css +76 -0
  38. package/src/components/side-nav/SideNav.jsx +208 -0
  39. package/src/components/side-nav/scrim.css +17 -0
  40. package/src/components/side-nav/side-nav.css +283 -0
  41. package/src/components/tabs/Tabs.jsx +102 -0
  42. package/src/components/tabs/tabs.css +135 -0
  43. package/src/index.js +20 -0
  44. package/src/themes.css +186 -0
  45. package/src/utilities/spacing.css +230 -0
package/README.md ADDED
@@ -0,0 +1,32 @@
1
+ # @a1-design-system/react
2
+
3
+ React components for the A1 token-driven design system.
4
+
5
+ ## Install
6
+
7
+ ```sh
8
+ npm install @a1-design-system/react
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ Import the global theme CSS once in your app, then import components from the
14
+ package.
15
+
16
+ ```jsx
17
+ import "@a1-design-system/react/themes.css";
18
+ import "@a1-design-system/react/color-scheme.css";
19
+ import { Button, Card, Heading, Paragraph } from "@a1-design-system/react";
20
+
21
+ export function Example() {
22
+ return (
23
+ <Card>
24
+ <Heading as="h2">A1 Design</Heading>
25
+ <Paragraph>A token-driven, component-first design system.</Paragraph>
26
+ <Button>Get started</Button>
27
+ </Card>
28
+ );
29
+ }
30
+ ```
31
+
32
+ Component styles are imported by each component module.
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@gtivr4/a1-design-system-react",
3
+ "version": "0.1.0",
4
+ "description": "React components for the A1 token-driven design system.",
5
+ "type": "module",
6
+ "main": "./src/index.js",
7
+ "keywords": [
8
+ "design-system",
9
+ "react",
10
+ "tokens",
11
+ "components"
12
+ ],
13
+ "sideEffects": [
14
+ "**/*.css"
15
+ ],
16
+ "files": [
17
+ "README.md",
18
+ "src/**/*.css",
19
+ "src/**/*.jsx",
20
+ "src/index.js",
21
+ "!src/**/*.stories.jsx",
22
+ "!src/tokens/**",
23
+ "!src/rules/**",
24
+ "!src/Breakpoints.stories.jsx",
25
+ "!src/Colors.stories.jsx"
26
+ ],
27
+ "exports": {
28
+ ".": "./src/index.js",
29
+ "./themes.css": "./src/themes.css",
30
+ "./color-scheme.css": "./src/color-scheme.css",
31
+ "./utilities/spacing.css": "./src/utilities/spacing.css",
32
+ "./components/*": "./src/components/*"
33
+ },
34
+ "publishConfig": {
35
+ "access": "public"
36
+ },
37
+ "peerDependencies": {
38
+ "react": ">=18"
39
+ }
40
+ }
@@ -0,0 +1,213 @@
1
+ /* Base design system color scheme switching — not a theme.
2
+ Edit this file directly; do not generate from system/themes/. */
3
+
4
+ /* ─── Dark ───────────────────────────────────────────────────────────────────
5
+ Apply .a1-theme-dark to <html> for global dark mode.
6
+ .a1-inverse on any container also activates dark colors. */
7
+
8
+ .a1-theme-dark, .a1-inverse {
9
+ color-scheme: dark;
10
+ --semantic-color-surface-page: var(--base-color-neutral-900);
11
+ --semantic-color-surface-panel: var(--base-color-neutral-800);
12
+ --semantic-color-surface-raised: var(--base-color-neutral-700);
13
+ --semantic-color-surface-inverse: var(--base-color-neutral-0);
14
+ --semantic-color-text-default: var(--base-color-neutral-50);
15
+ --semantic-color-text-muted: var(--base-color-neutral-400);
16
+ --semantic-color-text-inverse: var(--base-color-neutral-900);
17
+ --semantic-color-border-subtle: var(--base-color-neutral-700);
18
+ --semantic-color-border-default: var(--base-color-neutral-600);
19
+ --semantic-color-border-strong: var(--base-color-neutral-400);
20
+ --semantic-color-action-background: var(--base-color-accent-400);
21
+ --semantic-color-action-background-hover: var(--base-color-accent-300);
22
+ --semantic-color-action-background-pressed: var(--base-color-accent-500);
23
+ --semantic-color-action-foreground: var(--base-color-accent-1000);
24
+ --semantic-color-action-foreground-pressed: var(--base-color-accent-1000);
25
+ --semantic-color-action-surface: var(--base-color-accent-900);
26
+ --semantic-color-action-border: var(--base-color-accent-500);
27
+ --semantic-color-status-info-background: var(--base-color-info-400);
28
+ --semantic-color-status-info-surface: var(--base-color-info-900);
29
+ --semantic-color-status-info-border: var(--base-color-info-500);
30
+ --semantic-color-status-info-foreground: var(--base-color-info-1000);
31
+ --semantic-color-status-error-background: var(--base-color-error-400);
32
+ --semantic-color-status-error-surface: var(--base-color-error-900);
33
+ --semantic-color-status-error-border: var(--base-color-error-500);
34
+ --semantic-color-status-error-foreground: var(--base-color-neutral-900);
35
+ --semantic-color-status-warn-background: var(--base-color-warn-400);
36
+ --semantic-color-status-warn-surface: var(--base-color-warn-900);
37
+ --semantic-color-status-warn-border: var(--base-color-warn-500);
38
+ --semantic-color-status-warn-foreground: var(--base-color-neutral-900);
39
+ --semantic-color-status-success-background: var(--base-color-success-400);
40
+ --semantic-color-status-success-surface: var(--base-color-success-900);
41
+ --semantic-color-status-success-border: var(--base-color-success-500);
42
+ --semantic-color-status-success-foreground: var(--base-color-neutral-900);
43
+ --component-scrim-color: rgba(181, 160, 255, 0.6);
44
+ --component-button-primary-background: var(--base-color-accent-200);
45
+ --component-button-primary-background-hover: var(--base-color-accent-100);
46
+ --component-button-primary-background-pressed: var(--base-color-accent-50);
47
+ --component-button-primary-foreground: var(--base-color-accent-900);
48
+ --component-button-primary-foreground-hover: var(--base-color-accent-800);
49
+ --component-button-primary-foreground-pressed: var(--base-color-accent-700);
50
+ --component-button-primary-border: var(--base-color-accent-200);
51
+ --component-button-secondary-background: var(--base-color-accent-900);
52
+ --component-button-secondary-background-hover: var(--base-color-accent-800);
53
+ --component-button-secondary-background-pressed: var(--base-color-accent-700);
54
+ --component-button-secondary-foreground: var(--base-color-accent-200);
55
+ --component-button-secondary-foreground-hover: var(--base-color-accent-100);
56
+ --component-button-secondary-foreground-pressed: var(--base-color-accent-50);
57
+ --component-button-secondary-border: var(--base-color-accent-200);
58
+ --component-button-secondary-border-hover: var(--base-color-accent-100);
59
+ --component-button-secondary-border-pressed: var(--base-color-accent-50);
60
+ --component-button-tertiary-background: var(--base-color-accent-900);
61
+ --component-button-tertiary-background-hover: var(--base-color-accent-800);
62
+ --component-button-tertiary-background-pressed: var(--base-color-accent-700);
63
+ --component-button-tertiary-foreground: var(--base-color-accent-200);
64
+ --component-button-tertiary-foreground-hover: var(--base-color-accent-100);
65
+ --component-button-tertiary-foreground-pressed: var(--base-color-accent-50);
66
+ --component-button-tertiary-border: var(--base-color-accent-900);
67
+ --component-button-tertiary-border-hover: var(--base-color-accent-800);
68
+ --component-button-tertiary-border-pressed: var(--base-color-accent-700);
69
+ }
70
+
71
+ /* Light restore inside a dark context (.a1-inverse or .a1-theme-light nested under .a1-theme-dark) */
72
+ .a1-theme-dark .a1-inverse,
73
+ .a1-theme-dark .a1-theme-light {
74
+ color-scheme: light;
75
+ --semantic-color-surface-page: var(--base-color-neutral-0);
76
+ --semantic-color-surface-panel: var(--base-color-neutral-50);
77
+ --semantic-color-surface-raised: var(--base-color-neutral-100);
78
+ --semantic-color-surface-inverse: var(--base-color-neutral-900);
79
+ --semantic-color-text-default: var(--base-color-neutral-900);
80
+ --semantic-color-text-muted: var(--base-color-neutral-600);
81
+ --semantic-color-text-inverse: var(--base-color-neutral-0);
82
+ --semantic-color-border-subtle: var(--base-color-neutral-200);
83
+ --semantic-color-border-default: var(--base-color-neutral-300);
84
+ --semantic-color-border-strong: var(--base-color-neutral-500);
85
+ --semantic-color-action-background: var(--base-color-accent-500);
86
+ --semantic-color-action-background-hover: var(--base-color-accent-600);
87
+ --semantic-color-action-background-pressed: var(--base-color-accent-800);
88
+ --semantic-color-action-foreground: var(--base-color-accent-100);
89
+ --semantic-color-action-foreground-pressed: var(--base-color-accent-300);
90
+ --semantic-color-action-surface: var(--base-color-accent-50);
91
+ --semantic-color-action-border: var(--base-color-accent-300);
92
+ --semantic-color-status-info-background: var(--base-color-info-500);
93
+ --semantic-color-status-info-surface: var(--base-color-info-50);
94
+ --semantic-color-status-info-border: var(--base-color-info-300);
95
+ --semantic-color-status-info-foreground: var(--base-color-info-0);
96
+ --semantic-color-status-error-background: var(--base-color-error-500);
97
+ --semantic-color-status-error-surface: var(--base-color-error-50);
98
+ --semantic-color-status-error-border: var(--base-color-error-300);
99
+ --semantic-color-status-error-foreground: var(--base-color-error-0);
100
+ --semantic-color-status-warn-background: var(--base-color-warn-500);
101
+ --semantic-color-status-warn-surface: var(--base-color-warn-50);
102
+ --semantic-color-status-warn-border: var(--base-color-warn-300);
103
+ --semantic-color-status-warn-foreground: var(--base-color-warn-0);
104
+ --semantic-color-status-success-background: var(--base-color-success-500);
105
+ --semantic-color-status-success-surface: var(--base-color-success-50);
106
+ --semantic-color-status-success-border: var(--base-color-success-300);
107
+ --semantic-color-status-success-foreground: var(--base-color-success-0);
108
+ --component-scrim-color: rgba(15, 0, 42, 0.6);
109
+ --component-button-primary-background: var(--base-color-accent-500);
110
+ --component-button-primary-background-hover: var(--base-color-accent-600);
111
+ --component-button-primary-background-pressed: var(--base-color-accent-800);
112
+ --component-button-primary-foreground: var(--base-color-accent-0);
113
+ --component-button-primary-foreground-hover: var(--base-color-accent-50);
114
+ --component-button-primary-foreground-pressed: var(--base-color-accent-100);
115
+ --component-button-primary-border: var(--base-color-accent-500);
116
+ --component-button-secondary-background: var(--base-color-accent-0);
117
+ --component-button-secondary-background-hover: var(--base-color-accent-50);
118
+ --component-button-secondary-background-pressed: var(--base-color-accent-100);
119
+ --component-button-secondary-foreground: var(--base-color-accent-600);
120
+ --component-button-secondary-foreground-hover: var(--base-color-accent-700);
121
+ --component-button-secondary-foreground-pressed: var(--base-color-accent-800);
122
+ --component-button-secondary-border: var(--base-color-accent-500);
123
+ --component-button-secondary-border-hover: var(--base-color-accent-700);
124
+ --component-button-secondary-border-pressed: var(--base-color-accent-800);
125
+ --component-button-tertiary-background: var(--base-color-accent-0);
126
+ --component-button-tertiary-background-hover: var(--base-color-accent-50);
127
+ --component-button-tertiary-background-pressed: var(--base-color-accent-100);
128
+ --component-button-tertiary-foreground: var(--base-color-accent-600);
129
+ --component-button-tertiary-foreground-hover: var(--base-color-accent-700);
130
+ --component-button-tertiary-foreground-pressed: var(--base-color-accent-800);
131
+ --component-button-tertiary-border: var(--base-color-accent-0);
132
+ --component-button-tertiary-border-hover: var(--base-color-accent-50);
133
+ --component-button-tertiary-border-pressed: var(--base-color-accent-100);
134
+ }
135
+
136
+ .a1-theme-dark .a1-notification--default,
137
+ .a1-inverse .a1-notification--default {
138
+ --a1-notification-background: var(--base-color-neutral-500);
139
+ --a1-notification-foreground: var(--base-color-neutral-0);
140
+ }
141
+
142
+ .a1-theme-dark .a1-inverse .a1-notification--default,
143
+ .a1-theme-dark .a1-theme-light .a1-notification--default {
144
+ --a1-notification-background: var(--base-color-neutral-600);
145
+ --a1-notification-foreground: var(--base-color-neutral-0);
146
+ }
147
+
148
+ /* ─── Light ──────────────────────────────────────────────────────────────────
149
+ Use .a1-theme-light to explicitly force light mode, e.g. inside a dark container. */
150
+
151
+ .a1-theme-light {
152
+ color-scheme: light;
153
+ --semantic-color-surface-page: var(--base-color-neutral-0);
154
+ --semantic-color-surface-panel: var(--base-color-neutral-50);
155
+ --semantic-color-surface-raised: var(--base-color-neutral-100);
156
+ --semantic-color-surface-inverse: var(--base-color-neutral-900);
157
+ --semantic-color-text-default: var(--base-color-neutral-900);
158
+ --semantic-color-text-muted: var(--base-color-neutral-600);
159
+ --semantic-color-text-inverse: var(--base-color-neutral-0);
160
+ --semantic-color-text-accent: var(--base-color-accent-500);
161
+ --semantic-color-border-subtle: var(--base-color-neutral-200);
162
+ --semantic-color-border-default: var(--base-color-neutral-300);
163
+ --semantic-color-border-strong: var(--base-color-neutral-500);
164
+ --semantic-color-action-background: var(--base-color-accent-500);
165
+ --semantic-color-action-background-hover: var(--base-color-accent-600);
166
+ --semantic-color-action-background-pressed: var(--base-color-accent-800);
167
+ --semantic-color-action-foreground: var(--base-color-accent-100);
168
+ --semantic-color-action-foreground-pressed: var(--base-color-accent-300);
169
+ --semantic-color-action-surface: var(--base-color-accent-50);
170
+ --semantic-color-action-border: var(--base-color-accent-300);
171
+ --semantic-color-status-info-background: var(--base-color-info-500);
172
+ --semantic-color-status-info-surface: var(--base-color-info-50);
173
+ --semantic-color-status-info-border: var(--base-color-info-300);
174
+ --semantic-color-status-info-foreground: var(--base-color-info-0);
175
+ --semantic-color-status-error-background: var(--base-color-error-500);
176
+ --semantic-color-status-error-surface: var(--base-color-error-50);
177
+ --semantic-color-status-error-border: var(--base-color-error-300);
178
+ --semantic-color-status-error-foreground: var(--base-color-error-0);
179
+ --semantic-color-status-warn-background: var(--base-color-warn-500);
180
+ --semantic-color-status-warn-surface: var(--base-color-warn-50);
181
+ --semantic-color-status-warn-border: var(--base-color-warn-300);
182
+ --semantic-color-status-warn-foreground: var(--base-color-warn-0);
183
+ --semantic-color-status-success-background: var(--base-color-success-500);
184
+ --semantic-color-status-success-surface: var(--base-color-success-50);
185
+ --semantic-color-status-success-border: var(--base-color-success-300);
186
+ --semantic-color-status-success-foreground: var(--base-color-success-0);
187
+ --component-scrim-color: rgba(15, 0, 42, 0.6);
188
+ --component-button-primary-background: var(--base-color-accent-500);
189
+ --component-button-primary-background-hover: var(--base-color-accent-600);
190
+ --component-button-primary-background-pressed: var(--base-color-accent-800);
191
+ --component-button-primary-foreground: var(--base-color-accent-0);
192
+ --component-button-primary-foreground-hover: var(--base-color-accent-50);
193
+ --component-button-primary-foreground-pressed: var(--base-color-accent-100);
194
+ --component-button-primary-border: var(--base-color-accent-500);
195
+ --component-button-secondary-background: var(--base-color-accent-0);
196
+ --component-button-secondary-background-hover: var(--base-color-accent-50);
197
+ --component-button-secondary-background-pressed: var(--base-color-accent-100);
198
+ --component-button-secondary-foreground: var(--base-color-accent-600);
199
+ --component-button-secondary-foreground-hover: var(--base-color-accent-700);
200
+ --component-button-secondary-foreground-pressed: var(--base-color-accent-800);
201
+ --component-button-secondary-border: var(--base-color-accent-500);
202
+ --component-button-secondary-border-hover: var(--base-color-accent-700);
203
+ --component-button-secondary-border-pressed: var(--base-color-accent-800);
204
+ --component-button-tertiary-background: var(--base-color-accent-0);
205
+ --component-button-tertiary-background-hover: var(--base-color-accent-50);
206
+ --component-button-tertiary-background-pressed: var(--base-color-accent-100);
207
+ --component-button-tertiary-foreground: var(--base-color-accent-600);
208
+ --component-button-tertiary-foreground-hover: var(--base-color-accent-700);
209
+ --component-button-tertiary-foreground-pressed: var(--base-color-accent-800);
210
+ --component-button-tertiary-border: var(--base-color-accent-0);
211
+ --component-button-tertiary-border-hover: var(--base-color-accent-50);
212
+ --component-button-tertiary-border-pressed: var(--base-color-accent-100);
213
+ }
@@ -0,0 +1,45 @@
1
+ import "./button.css";
2
+ import { Icon } from "../icon/Icon.jsx";
3
+
4
+ const variants = ["primary", "secondary", "tertiary", "destructive", "success"];
5
+ const sizes = ["sm", "md", "lg"];
6
+ const iconPositions = ["start", "end"];
7
+
8
+ export function Button({
9
+ as: Component = "button",
10
+ variant = "primary",
11
+ size = "md",
12
+ icon,
13
+ iconPosition = "start",
14
+ className = "",
15
+ type,
16
+ children,
17
+ ...props
18
+ }) {
19
+ const resolvedVariant = variants.includes(variant) ? variant : "primary";
20
+ const resolvedSize = sizes.includes(size) ? size : "md";
21
+ const resolvedPosition = iconPositions.includes(iconPosition) ? iconPosition : "start";
22
+ const classes = [
23
+ "a1-button",
24
+ `a1-button--${resolvedVariant}`,
25
+ resolvedSize !== "md" && `a1-button--${resolvedSize}`,
26
+ icon && "a1-button--has-icon",
27
+ className
28
+ ]
29
+ .filter(Boolean)
30
+ .join(" ");
31
+
32
+ const iconEl = icon ? <Icon name={icon} className="a1-button__icon" /> : null;
33
+
34
+ return (
35
+ <Component
36
+ className={classes}
37
+ type={Component === "button" ? type ?? "button" : type}
38
+ {...props}
39
+ >
40
+ {resolvedPosition === "start" && iconEl}
41
+ {children}
42
+ {resolvedPosition === "end" && iconEl}
43
+ </Component>
44
+ );
45
+ }
@@ -0,0 +1,135 @@
1
+ .a1-button {
2
+ box-sizing: border-box;
3
+ height: var(--a1-button-height, var(--component-button-min-height));
4
+ min-height: var(--a1-button-height, var(--component-button-min-height));
5
+ max-height: var(--a1-button-height, var(--component-button-min-height));
6
+ display: inline-flex;
7
+ align-items: center;
8
+ justify-content: center;
9
+ gap: var(--component-button-gap);
10
+ border-width: var(--a1-button-border-width, var(--component-button-border-width));
11
+ border-style: solid;
12
+ border-radius: var(--a1-button-border-radius, var(--component-button-border-radius));
13
+ padding-block: var(--component-button-padding-block);
14
+ padding-inline: var(--a1-button-padding-inline, var(--component-button-padding-inline));
15
+ font-family: var(--component-button-font-family);
16
+ font-size: var(--a1-button-font-size, var(--component-button-font-size));
17
+ font-weight: var(--a1-button-font-weight, var(--component-button-font-weight));
18
+ line-height: var(--component-button-font-line-height);
19
+ text-decoration: none;
20
+ white-space: nowrap;
21
+ overflow: clip;
22
+ cursor: pointer;
23
+ background: var(--a1-button-background);
24
+ border-color: var(--a1-button-border);
25
+ color: var(--a1-button-foreground);
26
+ }
27
+
28
+ .a1-button:hover {
29
+ background: var(--a1-button-background-hover);
30
+ border-color: var(--a1-button-border-hover, var(--a1-button-border));
31
+ color: var(--a1-button-foreground-hover, var(--a1-button-foreground));
32
+ }
33
+
34
+ .a1-button:active {
35
+ background: var(--a1-button-background-pressed);
36
+ border-color: var(--a1-button-border-pressed, var(--a1-button-border));
37
+ color: var(--a1-button-foreground-pressed, var(--a1-button-foreground));
38
+ }
39
+
40
+ .a1-button:focus-visible {
41
+ outline: var(--component-button-focus-ring-width) solid var(--component-button-focus-ring);
42
+ outline-offset: var(--component-button-focus-ring-offset);
43
+ }
44
+
45
+ .a1-button:disabled,
46
+ .a1-button[aria-disabled="true"] {
47
+ cursor: not-allowed;
48
+ opacity: var(--component-button-disabled-opacity);
49
+ }
50
+
51
+ .a1-button--primary {
52
+ --a1-button-background: var(--component-button-primary-background);
53
+ --a1-button-background-hover: var(--component-button-primary-background-hover);
54
+ --a1-button-background-pressed: var(--component-button-primary-background-pressed);
55
+ --a1-button-foreground: var(--component-button-primary-foreground);
56
+ --a1-button-foreground-hover: var(--component-button-primary-foreground-hover);
57
+ --a1-button-foreground-pressed: var(--component-button-primary-foreground-pressed);
58
+ --a1-button-border: var(--component-button-primary-border);
59
+ --a1-button-border-hover: var(--component-button-primary-border);
60
+ --a1-button-border-pressed: var(--component-button-primary-border);
61
+ --a1-button-border-width: var(--component-button-primary-border-width);
62
+ }
63
+
64
+ .a1-button--secondary {
65
+ --a1-button-background: var(--component-button-secondary-background);
66
+ --a1-button-background-hover: var(--component-button-secondary-background-hover);
67
+ --a1-button-background-pressed: var(--component-button-secondary-background-pressed);
68
+ --a1-button-foreground: var(--component-button-secondary-foreground);
69
+ --a1-button-foreground-hover: var(--component-button-secondary-foreground-hover);
70
+ --a1-button-foreground-pressed: var(--component-button-secondary-foreground-pressed);
71
+ --a1-button-border: var(--component-button-secondary-border);
72
+ --a1-button-border-hover: var(--component-button-secondary-border-hover);
73
+ --a1-button-border-pressed: var(--component-button-secondary-border-pressed);
74
+ --a1-button-border-width: var(--component-button-secondary-border-width);
75
+ }
76
+
77
+ .a1-button--tertiary {
78
+ --a1-button-background: var(--component-button-tertiary-background);
79
+ --a1-button-background-hover: var(--component-button-tertiary-background-hover);
80
+ --a1-button-background-pressed: var(--component-button-tertiary-background-pressed);
81
+ --a1-button-foreground: var(--component-button-tertiary-foreground);
82
+ --a1-button-foreground-hover: var(--component-button-tertiary-foreground-hover);
83
+ --a1-button-foreground-pressed: var(--component-button-tertiary-foreground-pressed);
84
+ --a1-button-border: var(--component-button-tertiary-border);
85
+ --a1-button-border-hover: var(--component-button-tertiary-border-hover);
86
+ --a1-button-border-pressed: var(--component-button-tertiary-border-pressed);
87
+ --a1-button-border-width: var(--component-button-tertiary-border-width);
88
+ }
89
+
90
+ .a1-button--destructive {
91
+ --a1-button-background: var(--semantic-color-status-error-background);
92
+ --a1-button-background-hover: color-mix(in srgb, var(--semantic-color-status-error-background), black 16%);
93
+ --a1-button-background-pressed: color-mix(in srgb, var(--semantic-color-status-error-background), black 32%);
94
+ --a1-button-foreground: var(--semantic-color-status-error-foreground);
95
+ --a1-button-foreground-hover: var(--semantic-color-status-error-foreground);
96
+ --a1-button-foreground-pressed: var(--semantic-color-status-error-foreground);
97
+ --a1-button-border: var(--semantic-color-status-error-background);
98
+ --a1-button-border-hover: var(--semantic-color-status-error-background);
99
+ --a1-button-border-pressed: var(--semantic-color-status-error-background);
100
+ --a1-button-border-width: var(--component-button-primary-border-width);
101
+ }
102
+
103
+ .a1-button--success {
104
+ --a1-button-background: var(--semantic-color-status-success-background);
105
+ --a1-button-background-hover: color-mix(in srgb, var(--semantic-color-status-success-background), black 16%);
106
+ --a1-button-background-pressed: color-mix(in srgb, var(--semantic-color-status-success-background), black 32%);
107
+ --a1-button-foreground: var(--semantic-color-status-success-foreground);
108
+ --a1-button-foreground-hover: var(--semantic-color-status-success-foreground);
109
+ --a1-button-foreground-pressed: var(--semantic-color-status-success-foreground);
110
+ --a1-button-border: var(--semantic-color-status-success-background);
111
+ --a1-button-border-hover: var(--semantic-color-status-success-background);
112
+ --a1-button-border-pressed: var(--semantic-color-status-success-background);
113
+ --a1-button-border-width: var(--component-button-primary-border-width);
114
+ }
115
+
116
+ .a1-button--sm {
117
+ --a1-button-height: 28px;
118
+ --a1-button-font-size: var(--semantic-font-size-body-sm);
119
+ --a1-button-font-weight: var(--base-font-weight-medium);
120
+ --a1-button-border-radius: 4px;
121
+ --a1-button-padding-inline: var(--base-spacing-8);
122
+ }
123
+
124
+ .a1-button--lg {
125
+ --a1-button-height: 56px;
126
+ --a1-button-font-size: var(--semantic-font-size-body-lg);
127
+ --a1-button-font-weight: var(--base-font-weight-extra-bold);
128
+ --a1-button-border-radius: var(--base-radius-lg);
129
+ --a1-button-padding-inline: var(--base-spacing-16);
130
+ }
131
+
132
+ .a1-button__icon {
133
+ font-size: var(--component-button-icon-size);
134
+ --a1-icon-opsz: var(--component-button-icon-optical-size);
135
+ }
@@ -0,0 +1,27 @@
1
+ import "./button-container.css";
2
+
3
+ const alignments = ["start", "center", "end"];
4
+
5
+ export function ButtonContainer({
6
+ align = "start",
7
+ className = "",
8
+ children,
9
+ ...props
10
+ }) {
11
+ const resolvedAlign = alignments.includes(align) ? align : "start";
12
+ const classes = [
13
+ "a1-button-container",
14
+ `a1-button-container--${resolvedAlign}`,
15
+ className
16
+ ]
17
+ .filter(Boolean)
18
+ .join(" ");
19
+
20
+ return (
21
+ <div className={classes} {...props}>
22
+ <div className="a1-button-container__inner">
23
+ {children}
24
+ </div>
25
+ </div>
26
+ );
27
+ }
@@ -0,0 +1,38 @@
1
+ .a1-button-container {
2
+ container: a1-button-container / inline-size;
3
+ }
4
+
5
+ .a1-button-container__inner {
6
+ display: flex;
7
+ flex-direction: column;
8
+ align-items: stretch;
9
+ gap: var(--base-spacing-8);
10
+ }
11
+
12
+ .a1-button-container__inner > .a1-button {
13
+ width: 100%;
14
+ }
15
+
16
+ @container a1-button-container (min-width: 480px) {
17
+ .a1-button-container__inner {
18
+ flex-direction: row;
19
+ flex-wrap: wrap;
20
+ align-items: center;
21
+ }
22
+
23
+ .a1-button-container__inner > .a1-button {
24
+ width: auto;
25
+ }
26
+
27
+ .a1-button-container--start .a1-button-container__inner {
28
+ justify-content: flex-start;
29
+ }
30
+
31
+ .a1-button-container--center .a1-button-container__inner {
32
+ justify-content: center;
33
+ }
34
+
35
+ .a1-button-container--end .a1-button-container__inner {
36
+ justify-content: flex-end;
37
+ }
38
+ }
@@ -0,0 +1,29 @@
1
+ import "./card.css";
2
+ import { Icon } from "../icon/Icon.jsx";
3
+
4
+ const shadows = ["none", "xs", "sm", "md", "lg", "xl"];
5
+
6
+ export function Card({
7
+ as: Component = "div",
8
+ shadow = "sm",
9
+ icon,
10
+ className = "",
11
+ children,
12
+ ...props
13
+ }) {
14
+ const resolvedShadow = shadows.includes(shadow) ? shadow : "sm";
15
+ const classes = ["a1-card", `a1-card--shadow-${resolvedShadow}`, className]
16
+ .filter(Boolean)
17
+ .join(" ");
18
+
19
+ return (
20
+ <Component className={classes} {...props}>
21
+ {icon && (
22
+ <span className="a1-card__icon" aria-hidden="true">
23
+ <Icon name={icon} />
24
+ </span>
25
+ )}
26
+ {children}
27
+ </Component>
28
+ );
29
+ }
@@ -0,0 +1,37 @@
1
+ .a1-card {
2
+ box-sizing: border-box;
3
+ background: var(--semantic-color-surface-page);
4
+ border: var(--component-card-border-width) solid var(--semantic-color-border-strong);
5
+ border-radius: var(--component-card-border-radius);
6
+ padding: var(--component-card-padding);
7
+ box-shadow: var(--a1-card-shadow);
8
+ color: var(--semantic-color-text-default);
9
+ }
10
+
11
+ .a1-card__icon {
12
+ display: flex;
13
+ align-items: center;
14
+ justify-content: center;
15
+ width: var(--base-spacing-40);
16
+ height: var(--base-spacing-40);
17
+ border-radius: var(--base-radius-control);
18
+ background: var(--semantic-color-action-surface);
19
+ color: var(--semantic-color-action-background);
20
+ margin-bottom: var(--base-spacing-12);
21
+ flex-shrink: 0;
22
+ }
23
+
24
+ .a1-card__icon {
25
+ --a1-icon-opsz: var(--component-card-icon-optical-size);
26
+ }
27
+
28
+ .a1-card__icon .a1-icon {
29
+ font-size: var(--component-card-icon-size);
30
+ }
31
+
32
+ .a1-card--shadow-none { --a1-card-shadow: none; }
33
+ .a1-card--shadow-xs { --a1-card-shadow: var(--semantic-shadow-xs); }
34
+ .a1-card--shadow-sm { --a1-card-shadow: var(--semantic-shadow-sm); }
35
+ .a1-card--shadow-md { --a1-card-shadow: var(--semantic-shadow-md); }
36
+ .a1-card--shadow-lg { --a1-card-shadow: var(--semantic-shadow-lg); }
37
+ .a1-card--shadow-xl { --a1-card-shadow: var(--semantic-shadow-xl); }
@@ -0,0 +1,44 @@
1
+ import { useEffect, useRef } from "react";
2
+ import "./dialog.css";
3
+ import { IconButton } from "../icon-button/IconButton.jsx";
4
+
5
+ export function Dialog({ open = false, onClose, title, footer, children, ...props }) {
6
+ const ref = useRef(null);
7
+
8
+ useEffect(() => {
9
+ const el = ref.current;
10
+ if (!el) return;
11
+ if (open) {
12
+ if (!el.open) el.showModal();
13
+ } else if (el.open) {
14
+ el.close();
15
+ }
16
+ }, [open]);
17
+
18
+ useEffect(() => {
19
+ const el = ref.current;
20
+ if (!el) return;
21
+ const handleCancel = (e) => {
22
+ e.preventDefault();
23
+ onClose?.();
24
+ };
25
+ el.addEventListener("cancel", handleCancel);
26
+ return () => el.removeEventListener("cancel", handleCancel);
27
+ }, [onClose]);
28
+
29
+ return (
30
+ <dialog ref={ref} className="a1-dialog" {...props}>
31
+ <div className="a1-dialog__header">
32
+ {title && <p className="a1-dialog__title">{title}</p>}
33
+ <IconButton
34
+ icon="close"
35
+ label="Close dialog"
36
+ onClick={onClose}
37
+ className="a1-dialog__close"
38
+ />
39
+ </div>
40
+ <div className="a1-dialog__body">{children}</div>
41
+ {footer && <div className="a1-dialog__footer">{footer}</div>}
42
+ </dialog>
43
+ );
44
+ }