@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.
- package/README.md +32 -0
- package/package.json +40 -0
- package/src/color-scheme.css +213 -0
- package/src/components/button/Button.jsx +45 -0
- package/src/components/button/button.css +135 -0
- package/src/components/button-container/ButtonContainer.jsx +27 -0
- package/src/components/button-container/button-container.css +38 -0
- package/src/components/card/Card.jsx +29 -0
- package/src/components/card/card.css +37 -0
- package/src/components/dialog/Dialog.jsx +44 -0
- package/src/components/dialog/dialog.css +58 -0
- package/src/components/grid/Grid.jsx +77 -0
- package/src/components/grid/grid.css +86 -0
- package/src/components/heading/Heading.jsx +69 -0
- package/src/components/heading/heading.css +76 -0
- package/src/components/icon/Icon.jsx +32 -0
- package/src/components/icon/icon.css +10 -0
- package/src/components/icon-button/IconButton.jsx +34 -0
- package/src/components/icon-button/icon-button.css +196 -0
- package/src/components/inverse/Inverse.jsx +18 -0
- package/src/components/labels/Labels.jsx +29 -0
- package/src/components/link/Link.jsx +41 -0
- package/src/components/link/link.css +50 -0
- package/src/components/menu/Menu.jsx +45 -0
- package/src/components/menu/menu.css +45 -0
- package/src/components/message/Message.jsx +103 -0
- package/src/components/message/message.css +226 -0
- package/src/components/notification/Notification.jsx +55 -0
- package/src/components/notification/notification.css +69 -0
- package/src/components/page-layout/PageLayout.jsx +40 -0
- package/src/components/page-layout/page-layout.css +61 -0
- package/src/components/pagination/Pagination.jsx +64 -0
- package/src/components/pagination/pagination.css +85 -0
- package/src/components/paragraph/Paragraph.jsx +26 -0
- package/src/components/paragraph/paragraph.css +16 -0
- package/src/components/segmented-control/SegmentedControl.jsx +77 -0
- package/src/components/segmented-control/segmented.css +76 -0
- package/src/components/side-nav/SideNav.jsx +208 -0
- package/src/components/side-nav/scrim.css +17 -0
- package/src/components/side-nav/side-nav.css +283 -0
- package/src/components/tabs/Tabs.jsx +102 -0
- package/src/components/tabs/tabs.css +135 -0
- package/src/index.js +20 -0
- package/src/themes.css +186 -0
- 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
|
+
}
|