@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
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
.a1-dialog {
|
|
2
|
+
box-sizing: border-box;
|
|
3
|
+
border: var(--component-dialog-border-width) solid var(--semantic-color-border-strong);
|
|
4
|
+
border-radius: var(--component-dialog-border-radius);
|
|
5
|
+
padding: var(--component-dialog-padding);
|
|
6
|
+
background: var(--semantic-color-surface-page);
|
|
7
|
+
box-shadow: var(--component-dialog-shadow);
|
|
8
|
+
color: var(--semantic-color-text-default);
|
|
9
|
+
width: min(560px, calc(100vw - var(--base-spacing-64)));
|
|
10
|
+
max-height: calc(100dvh - var(--base-spacing-64));
|
|
11
|
+
overflow: hidden;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.a1-dialog[open] {
|
|
15
|
+
display: flex;
|
|
16
|
+
flex-direction: column;
|
|
17
|
+
gap: var(--base-spacing-16);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.a1-dialog::backdrop {
|
|
21
|
+
background: var(--component-scrim-color);
|
|
22
|
+
backdrop-filter: blur(var(--component-scrim-blur));
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.a1-dialog__header {
|
|
26
|
+
display: flex;
|
|
27
|
+
align-items: flex-start;
|
|
28
|
+
gap: var(--base-spacing-16);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.a1-dialog__title {
|
|
32
|
+
flex: 1;
|
|
33
|
+
margin: 0;
|
|
34
|
+
font-family: var(--component-heading-font-family-heading);
|
|
35
|
+
font-size: var(--semantic-font-size-heading-sm);
|
|
36
|
+
font-weight: var(--component-heading-font-weight-heading);
|
|
37
|
+
line-height: var(--component-heading-font-line-height-heading);
|
|
38
|
+
color: var(--semantic-color-text-default);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.a1-dialog__close {
|
|
42
|
+
flex-shrink: 0;
|
|
43
|
+
margin-top: var(--component-dialog-close-offset);
|
|
44
|
+
margin-right: var(--component-dialog-close-offset);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.a1-dialog__body {
|
|
48
|
+
flex: 1;
|
|
49
|
+
overflow-y: auto;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.a1-dialog__footer {
|
|
53
|
+
display: flex;
|
|
54
|
+
justify-content: flex-end;
|
|
55
|
+
gap: var(--base-spacing-12);
|
|
56
|
+
padding-top: var(--base-spacing-16);
|
|
57
|
+
border-top: var(--component-dialog-footer-border-width) solid var(--semantic-color-border-subtle);
|
|
58
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import "./grid.css";
|
|
2
|
+
|
|
3
|
+
const SPACING_KEYS = [1, 2, 4, 6, 8, 12, 16, 20, 24, 32, 40, 64, 96, 128];
|
|
4
|
+
|
|
5
|
+
function resolveGap(key) {
|
|
6
|
+
if (key == null) return undefined;
|
|
7
|
+
const n = Number(key);
|
|
8
|
+
return SPACING_KEYS.includes(n) ? `var(--base-spacing-${n})` : undefined;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function Grid({
|
|
12
|
+
columns,
|
|
13
|
+
gap,
|
|
14
|
+
rowGap,
|
|
15
|
+
columnGap,
|
|
16
|
+
className = "",
|
|
17
|
+
children,
|
|
18
|
+
...props
|
|
19
|
+
}) {
|
|
20
|
+
const classes = ["a1-grid"];
|
|
21
|
+
|
|
22
|
+
let inlineCols;
|
|
23
|
+
if (typeof columns === "number") {
|
|
24
|
+
inlineCols = columns;
|
|
25
|
+
} else if (columns && typeof columns === "object") {
|
|
26
|
+
for (const [bp, count] of Object.entries(columns)) {
|
|
27
|
+
classes.push(`a1-grid--${bp}-${count}`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (className) classes.push(className);
|
|
32
|
+
|
|
33
|
+
const gapVal = resolveGap(gap);
|
|
34
|
+
const rowGapVal = resolveGap(rowGap) ?? gapVal;
|
|
35
|
+
const colGapVal = resolveGap(columnGap) ?? gapVal;
|
|
36
|
+
|
|
37
|
+
const style = {
|
|
38
|
+
...(inlineCols != null ? { "--a1-grid-cols": inlineCols } : {}),
|
|
39
|
+
...(rowGapVal ? { rowGap: rowGapVal } : {}),
|
|
40
|
+
...(colGapVal ? { columnGap: colGapVal } : {}),
|
|
41
|
+
...props.style,
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
<div className={classes.join(" ")} style={style} {...props}>
|
|
46
|
+
{children}
|
|
47
|
+
</div>
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function GridItem({
|
|
52
|
+
span,
|
|
53
|
+
rowSpan,
|
|
54
|
+
className = "",
|
|
55
|
+
children,
|
|
56
|
+
...props
|
|
57
|
+
}) {
|
|
58
|
+
const classes = ["a1-grid-item"];
|
|
59
|
+
|
|
60
|
+
if (span === "full") {
|
|
61
|
+
classes.push("a1-grid-item--span-full");
|
|
62
|
+
} else if (typeof span === "number") {
|
|
63
|
+
classes.push(`a1-grid-item--span-${span}`);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (typeof rowSpan === "number") {
|
|
67
|
+
classes.push(`a1-grid-item--row-span-${rowSpan}`);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (className) classes.push(className);
|
|
71
|
+
|
|
72
|
+
return (
|
|
73
|
+
<div className={classes.join(" ")} {...props}>
|
|
74
|
+
{children}
|
|
75
|
+
</div>
|
|
76
|
+
);
|
|
77
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
.a1-grid {
|
|
2
|
+
display: grid;
|
|
3
|
+
grid-template-columns: repeat(var(--a1-grid-cols, 1), minmax(0, 1fr));
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
/* ── Static column-count modifiers ─────────────────────────────────────────── */
|
|
7
|
+
|
|
8
|
+
.a1-grid--cols-1 { --a1-grid-cols: 1; }
|
|
9
|
+
.a1-grid--cols-2 { --a1-grid-cols: 2; }
|
|
10
|
+
.a1-grid--cols-3 { --a1-grid-cols: 3; }
|
|
11
|
+
.a1-grid--cols-4 { --a1-grid-cols: 4; }
|
|
12
|
+
.a1-grid--cols-5 { --a1-grid-cols: 5; }
|
|
13
|
+
.a1-grid--cols-6 { --a1-grid-cols: 6; }
|
|
14
|
+
.a1-grid--cols-8 { --a1-grid-cols: 8; }
|
|
15
|
+
.a1-grid--cols-10 { --a1-grid-cols: 10; }
|
|
16
|
+
.a1-grid--cols-12 { --a1-grid-cols: 12; }
|
|
17
|
+
|
|
18
|
+
/* ── Responsive column-count modifiers (mobile-first) ───────────────────────
|
|
19
|
+
xs has no min-width — it is the base/mobile default.
|
|
20
|
+
Each subsequent tier overrides via a min-width query. ─────── */
|
|
21
|
+
|
|
22
|
+
.a1-grid--xs-1 { --a1-grid-cols: 1; }
|
|
23
|
+
.a1-grid--xs-2 { --a1-grid-cols: 2; }
|
|
24
|
+
.a1-grid--xs-3 { --a1-grid-cols: 3; }
|
|
25
|
+
.a1-grid--xs-4 { --a1-grid-cols: 4; }
|
|
26
|
+
.a1-grid--xs-6 { --a1-grid-cols: 6; }
|
|
27
|
+
.a1-grid--xs-12 { --a1-grid-cols: 12; }
|
|
28
|
+
|
|
29
|
+
@media (min-width: 481px) {
|
|
30
|
+
.a1-grid--sm-1 { --a1-grid-cols: 1; }
|
|
31
|
+
.a1-grid--sm-2 { --a1-grid-cols: 2; }
|
|
32
|
+
.a1-grid--sm-3 { --a1-grid-cols: 3; }
|
|
33
|
+
.a1-grid--sm-4 { --a1-grid-cols: 4; }
|
|
34
|
+
.a1-grid--sm-6 { --a1-grid-cols: 6; }
|
|
35
|
+
.a1-grid--sm-12 { --a1-grid-cols: 12; }
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
@media (min-width: 641px) {
|
|
39
|
+
.a1-grid--md-1 { --a1-grid-cols: 1; }
|
|
40
|
+
.a1-grid--md-2 { --a1-grid-cols: 2; }
|
|
41
|
+
.a1-grid--md-3 { --a1-grid-cols: 3; }
|
|
42
|
+
.a1-grid--md-4 { --a1-grid-cols: 4; }
|
|
43
|
+
.a1-grid--md-6 { --a1-grid-cols: 6; }
|
|
44
|
+
.a1-grid--md-12 { --a1-grid-cols: 12; }
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
@media (min-width: 1025px) {
|
|
48
|
+
.a1-grid--lg-1 { --a1-grid-cols: 1; }
|
|
49
|
+
.a1-grid--lg-2 { --a1-grid-cols: 2; }
|
|
50
|
+
.a1-grid--lg-3 { --a1-grid-cols: 3; }
|
|
51
|
+
.a1-grid--lg-4 { --a1-grid-cols: 4; }
|
|
52
|
+
.a1-grid--lg-6 { --a1-grid-cols: 6; }
|
|
53
|
+
.a1-grid--lg-12 { --a1-grid-cols: 12; }
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
@media (min-width: 1441px) {
|
|
57
|
+
.a1-grid--xl-1 { --a1-grid-cols: 1; }
|
|
58
|
+
.a1-grid--xl-2 { --a1-grid-cols: 2; }
|
|
59
|
+
.a1-grid--xl-3 { --a1-grid-cols: 3; }
|
|
60
|
+
.a1-grid--xl-4 { --a1-grid-cols: 4; }
|
|
61
|
+
.a1-grid--xl-6 { --a1-grid-cols: 6; }
|
|
62
|
+
.a1-grid--xl-12 { --a1-grid-cols: 12; }
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/* ── GridItem span classes ──────────────────────────────────────────────────── */
|
|
66
|
+
|
|
67
|
+
.a1-grid-item--span-1 { grid-column: span 1; }
|
|
68
|
+
.a1-grid-item--span-2 { grid-column: span 2; }
|
|
69
|
+
.a1-grid-item--span-3 { grid-column: span 3; }
|
|
70
|
+
.a1-grid-item--span-4 { grid-column: span 4; }
|
|
71
|
+
.a1-grid-item--span-5 { grid-column: span 5; }
|
|
72
|
+
.a1-grid-item--span-6 { grid-column: span 6; }
|
|
73
|
+
.a1-grid-item--span-7 { grid-column: span 7; }
|
|
74
|
+
.a1-grid-item--span-8 { grid-column: span 8; }
|
|
75
|
+
.a1-grid-item--span-9 { grid-column: span 9; }
|
|
76
|
+
.a1-grid-item--span-10 { grid-column: span 10; }
|
|
77
|
+
.a1-grid-item--span-11 { grid-column: span 11; }
|
|
78
|
+
.a1-grid-item--span-12 { grid-column: span 12; }
|
|
79
|
+
.a1-grid-item--span-full { grid-column: 1 / -1; }
|
|
80
|
+
|
|
81
|
+
.a1-grid-item--row-span-1 { grid-row: span 1; }
|
|
82
|
+
.a1-grid-item--row-span-2 { grid-row: span 2; }
|
|
83
|
+
.a1-grid-item--row-span-3 { grid-row: span 3; }
|
|
84
|
+
.a1-grid-item--row-span-4 { grid-row: span 4; }
|
|
85
|
+
.a1-grid-item--row-span-5 { grid-row: span 5; }
|
|
86
|
+
.a1-grid-item--row-span-6 { grid-row: span 6; }
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import "./heading.css";
|
|
2
|
+
|
|
3
|
+
const headingSizes = ["xl", "lg", "md", "sm", "xs"];
|
|
4
|
+
const displaySizes = ["sm", "md", "lg", "xl", "xxl", "jumbo", "xJumbo"];
|
|
5
|
+
const colors = ["default", "muted", "accent"];
|
|
6
|
+
const levels = ["h1", "h2", "h3", "h4", "h5", "h6"];
|
|
7
|
+
const breakpoints = ["xs", "sm", "md", "lg", "xl"];
|
|
8
|
+
|
|
9
|
+
const levelDefaults = { h1: "xl", h2: "lg", h3: "md", h4: "sm", h5: "xs", h6: "xs" };
|
|
10
|
+
|
|
11
|
+
function isResponsiveSize(size) {
|
|
12
|
+
return size && typeof size === "object" && !Array.isArray(size);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function resolveSize(size, validSizes, defaultSize) {
|
|
16
|
+
if (!isResponsiveSize(size)) {
|
|
17
|
+
return validSizes.includes(size) ? size : defaultSize;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return validSizes.includes(size.xs) ? size.xs : defaultSize;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function getResponsiveSizeStyle(size, type, validSizes) {
|
|
24
|
+
if (!isResponsiveSize(size)) return {};
|
|
25
|
+
|
|
26
|
+
return breakpoints.slice(1).reduce((style, breakpoint) => {
|
|
27
|
+
const breakpointSize = size[breakpoint];
|
|
28
|
+
|
|
29
|
+
if (validSizes.includes(breakpointSize)) {
|
|
30
|
+
style[`--a1-heading-size-${breakpoint}`] =
|
|
31
|
+
`var(--semantic-font-size-${type}-${breakpointSize === "xJumbo" ? "x-jumbo" : breakpointSize})`;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return style;
|
|
35
|
+
}, {});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function Heading({
|
|
39
|
+
as: Component = "h2",
|
|
40
|
+
type = "heading",
|
|
41
|
+
size,
|
|
42
|
+
color = "default",
|
|
43
|
+
className = "",
|
|
44
|
+
style,
|
|
45
|
+
...props
|
|
46
|
+
}) {
|
|
47
|
+
const resolvedAs = levels.includes(Component) ? Component : "h2";
|
|
48
|
+
const isDisplay = type === "display";
|
|
49
|
+
const validSizes = isDisplay ? displaySizes : headingSizes;
|
|
50
|
+
const defaultSize = isDisplay ? "md" : (levelDefaults[resolvedAs] ?? "md");
|
|
51
|
+
const resolvedSize = resolveSize(size, validSizes, defaultSize);
|
|
52
|
+
const resolvedColor = colors.includes(color) ? color : "default";
|
|
53
|
+
const responsiveSizeStyle = getResponsiveSizeStyle(size, type, validSizes);
|
|
54
|
+
const resolvedStyle = Object.keys(responsiveSizeStyle).length
|
|
55
|
+
? { ...responsiveSizeStyle, ...style }
|
|
56
|
+
: style;
|
|
57
|
+
|
|
58
|
+
const classes = [
|
|
59
|
+
"a1-heading",
|
|
60
|
+
`a1-heading--${type}`,
|
|
61
|
+
`a1-heading--${type}-${resolvedSize}`,
|
|
62
|
+
resolvedColor !== "default" && `a1-heading--${resolvedColor}`,
|
|
63
|
+
className
|
|
64
|
+
]
|
|
65
|
+
.filter(Boolean)
|
|
66
|
+
.join(" ");
|
|
67
|
+
|
|
68
|
+
return <Component className={classes} style={resolvedStyle} {...props} />;
|
|
69
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
.a1-heading {
|
|
2
|
+
margin: 0;
|
|
3
|
+
font-family: var(--a1-heading-family);
|
|
4
|
+
font-size: var(--a1-heading-responsive-size, var(--a1-heading-size));
|
|
5
|
+
font-weight: var(--a1-heading-weight);
|
|
6
|
+
line-height: var(--a1-heading-line-height);
|
|
7
|
+
color: var(--a1-heading-color, var(--semantic-color-text-default));
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
@media (min-width: 481px) {
|
|
11
|
+
.a1-heading {
|
|
12
|
+
--a1-heading-responsive-size: var(--a1-heading-size-sm, var(--a1-heading-size));
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
@media (min-width: 641px) {
|
|
17
|
+
.a1-heading {
|
|
18
|
+
--a1-heading-responsive-size: var(
|
|
19
|
+
--a1-heading-size-md,
|
|
20
|
+
var(--a1-heading-size-sm, var(--a1-heading-size))
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
@media (min-width: 1025px) {
|
|
26
|
+
.a1-heading {
|
|
27
|
+
--a1-heading-responsive-size: var(
|
|
28
|
+
--a1-heading-size-lg,
|
|
29
|
+
var(--a1-heading-size-md, var(--a1-heading-size-sm, var(--a1-heading-size)))
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
@media (min-width: 1441px) {
|
|
35
|
+
.a1-heading {
|
|
36
|
+
--a1-heading-responsive-size: var(
|
|
37
|
+
--a1-heading-size-xl,
|
|
38
|
+
var(
|
|
39
|
+
--a1-heading-size-lg,
|
|
40
|
+
var(--a1-heading-size-md, var(--a1-heading-size-sm, var(--a1-heading-size)))
|
|
41
|
+
)
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.a1-heading--heading {
|
|
47
|
+
--a1-heading-family: var(--component-heading-font-family-heading);
|
|
48
|
+
--a1-heading-weight: var(--component-heading-font-weight-heading);
|
|
49
|
+
--a1-heading-line-height: var(--component-heading-font-line-height-heading);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.a1-heading--display {
|
|
53
|
+
--a1-heading-family: var(--component-heading-font-family-display);
|
|
54
|
+
--a1-heading-weight: var(--component-heading-font-weight-display);
|
|
55
|
+
--a1-heading-line-height: var(--component-heading-font-line-height-display);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/* Heading sizes */
|
|
59
|
+
.a1-heading--heading-xl { --a1-heading-size: var(--semantic-font-size-heading-xl); }
|
|
60
|
+
.a1-heading--heading-lg { --a1-heading-size: var(--semantic-font-size-heading-lg); }
|
|
61
|
+
.a1-heading--heading-md { --a1-heading-size: var(--semantic-font-size-heading-md); }
|
|
62
|
+
.a1-heading--heading-sm { --a1-heading-size: var(--semantic-font-size-heading-sm); }
|
|
63
|
+
.a1-heading--heading-xs { --a1-heading-size: var(--semantic-font-size-heading-xs); }
|
|
64
|
+
|
|
65
|
+
/* Display sizes */
|
|
66
|
+
.a1-heading--display-sm { --a1-heading-size: var(--semantic-font-size-display-sm); }
|
|
67
|
+
.a1-heading--display-md { --a1-heading-size: var(--semantic-font-size-display-md); }
|
|
68
|
+
.a1-heading--display-lg { --a1-heading-size: var(--semantic-font-size-display-lg); }
|
|
69
|
+
.a1-heading--display-xl { --a1-heading-size: var(--semantic-font-size-display-xl); }
|
|
70
|
+
.a1-heading--display-xxl { --a1-heading-size: var(--semantic-font-size-display-xxl); }
|
|
71
|
+
.a1-heading--display-jumbo { --a1-heading-size: var(--semantic-font-size-display-jumbo); }
|
|
72
|
+
.a1-heading--display-xJumbo { --a1-heading-size: var(--semantic-font-size-display-x-jumbo); }
|
|
73
|
+
|
|
74
|
+
/* Color modifiers */
|
|
75
|
+
.a1-heading--muted { --a1-heading-color: var(--semantic-color-text-muted); }
|
|
76
|
+
.a1-heading--accent { --a1-heading-color: var(--semantic-color-text-accent); }
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import "./icon.css";
|
|
2
|
+
|
|
3
|
+
export function Icon({
|
|
4
|
+
name,
|
|
5
|
+
weight,
|
|
6
|
+
grade,
|
|
7
|
+
opticalSize,
|
|
8
|
+
fill,
|
|
9
|
+
className = "",
|
|
10
|
+
style,
|
|
11
|
+
...props
|
|
12
|
+
}) {
|
|
13
|
+
const vars = {
|
|
14
|
+
...(weight != null && { "--a1-icon-weight": weight }),
|
|
15
|
+
...(grade != null && { "--a1-icon-grade": grade }),
|
|
16
|
+
...(opticalSize != null && { "--a1-icon-opsz": opticalSize }),
|
|
17
|
+
...(fill != null && { "--a1-icon-fill": fill ? 1 : 0 }),
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<span
|
|
22
|
+
className={["a1-icon", "material-symbols-outlined", className]
|
|
23
|
+
.filter(Boolean)
|
|
24
|
+
.join(" ")}
|
|
25
|
+
style={{ ...vars, ...style }}
|
|
26
|
+
aria-hidden="true"
|
|
27
|
+
{...props}
|
|
28
|
+
>
|
|
29
|
+
{name}
|
|
30
|
+
</span>
|
|
31
|
+
);
|
|
32
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
.a1-icon {
|
|
2
|
+
font-size: inherit;
|
|
3
|
+
line-height: 1;
|
|
4
|
+
user-select: none;
|
|
5
|
+
font-variation-settings:
|
|
6
|
+
"FILL" var(--a1-icon-fill, 0),
|
|
7
|
+
"wght" var(--a1-icon-weight, var(--base-font-weight-regular)),
|
|
8
|
+
"GRAD" var(--a1-icon-grade, 0),
|
|
9
|
+
"opsz" var(--a1-icon-opsz, var(--base-icon-optical-size));
|
|
10
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import "./icon-button.css";
|
|
2
|
+
import { Icon } from "../icon/Icon.jsx";
|
|
3
|
+
|
|
4
|
+
const variants = ["tertiary", "secondary", "destructive", "success"];
|
|
5
|
+
|
|
6
|
+
export function IconButton({
|
|
7
|
+
icon,
|
|
8
|
+
label,
|
|
9
|
+
variant = "tertiary",
|
|
10
|
+
disabled = false,
|
|
11
|
+
onClick,
|
|
12
|
+
className = "",
|
|
13
|
+
...props
|
|
14
|
+
}) {
|
|
15
|
+
const resolvedVariant = variants.includes(variant) ? variant : "tertiary";
|
|
16
|
+
const classes = [
|
|
17
|
+
"a1-icon-button",
|
|
18
|
+
`a1-icon-button--${resolvedVariant}`,
|
|
19
|
+
className,
|
|
20
|
+
].filter(Boolean).join(" ");
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<button
|
|
24
|
+
type="button"
|
|
25
|
+
className={classes}
|
|
26
|
+
aria-label={label}
|
|
27
|
+
disabled={disabled}
|
|
28
|
+
onClick={onClick}
|
|
29
|
+
{...props}
|
|
30
|
+
>
|
|
31
|
+
<Icon name={icon} />
|
|
32
|
+
</button>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/* ═══════════════════════════════════════════════════════════════════════════
|
|
2
|
+
IconButton
|
|
3
|
+
═══════════════════════════════════════════════════════════════════════════ */
|
|
4
|
+
|
|
5
|
+
.a1-icon-button {
|
|
6
|
+
display: inline-flex;
|
|
7
|
+
align-items: center;
|
|
8
|
+
justify-content: center;
|
|
9
|
+
flex-shrink: 0;
|
|
10
|
+
height: var(--component-icon-button-size);
|
|
11
|
+
aspect-ratio: 1;
|
|
12
|
+
padding: 0;
|
|
13
|
+
border-radius: var(--component-icon-button-border-radius);
|
|
14
|
+
cursor: pointer;
|
|
15
|
+
background: var(--a1-icon-button-background);
|
|
16
|
+
border-width: var(--a1-icon-button-border-width, var(--component-button-tertiary-border-width));
|
|
17
|
+
border-style: solid;
|
|
18
|
+
border-color: var(--a1-icon-button-border);
|
|
19
|
+
color: var(--a1-icon-button-foreground);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.a1-icon-button:hover {
|
|
23
|
+
background: var(--a1-icon-button-background-hover);
|
|
24
|
+
border-color: var(--a1-icon-button-border-hover);
|
|
25
|
+
color: var(--a1-icon-button-foreground-hover);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.a1-icon-button:active {
|
|
29
|
+
background: var(--a1-icon-button-background-pressed);
|
|
30
|
+
border-color: var(--a1-icon-button-border-pressed);
|
|
31
|
+
color: var(--a1-icon-button-foreground-pressed);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.a1-icon-button .a1-icon {
|
|
35
|
+
font-size: var(--component-icon-button-icon-size);
|
|
36
|
+
--a1-icon-opsz: var(--component-icon-button-icon-optical-size);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.a1-icon-button:focus-visible {
|
|
40
|
+
outline: var(--component-button-focus-ring-width) solid var(--component-button-focus-ring);
|
|
41
|
+
outline-offset: var(--component-icon-button-focus-ring-offset);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.a1-icon-button:disabled {
|
|
45
|
+
opacity: var(--component-button-disabled-opacity);
|
|
46
|
+
cursor: not-allowed;
|
|
47
|
+
pointer-events: none;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/* ── Variant: tertiary ───────────────────────────────────────────────────── */
|
|
51
|
+
|
|
52
|
+
.a1-icon-button--tertiary {
|
|
53
|
+
--a1-icon-button-background: var(--component-button-tertiary-background);
|
|
54
|
+
--a1-icon-button-background-hover: var(--component-button-tertiary-background-hover);
|
|
55
|
+
--a1-icon-button-background-pressed: var(--component-button-tertiary-background-pressed);
|
|
56
|
+
--a1-icon-button-foreground: var(--component-button-tertiary-foreground);
|
|
57
|
+
--a1-icon-button-foreground-hover: var(--component-button-tertiary-foreground-hover);
|
|
58
|
+
--a1-icon-button-foreground-pressed: var(--component-button-tertiary-foreground-pressed);
|
|
59
|
+
--a1-icon-button-border: var(--component-button-tertiary-border);
|
|
60
|
+
--a1-icon-button-border-hover: var(--component-button-tertiary-border-hover);
|
|
61
|
+
--a1-icon-button-border-pressed: var(--component-button-tertiary-border-pressed);
|
|
62
|
+
--a1-icon-button-border-width: var(--component-button-tertiary-border-width);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/* ── Variant: secondary ──────────────────────────────────────────────────── */
|
|
66
|
+
|
|
67
|
+
.a1-icon-button--secondary {
|
|
68
|
+
--a1-icon-button-background: var(--component-button-secondary-background);
|
|
69
|
+
--a1-icon-button-background-hover: var(--component-button-secondary-background-hover);
|
|
70
|
+
--a1-icon-button-background-pressed: var(--component-button-secondary-background-pressed);
|
|
71
|
+
--a1-icon-button-foreground: var(--component-button-secondary-foreground);
|
|
72
|
+
--a1-icon-button-foreground-hover: var(--component-button-secondary-foreground-hover);
|
|
73
|
+
--a1-icon-button-foreground-pressed: var(--component-button-secondary-foreground-pressed);
|
|
74
|
+
--a1-icon-button-border: var(--component-button-secondary-border);
|
|
75
|
+
--a1-icon-button-border-hover: var(--component-button-secondary-border-hover);
|
|
76
|
+
--a1-icon-button-border-pressed: var(--component-button-secondary-border-pressed);
|
|
77
|
+
--a1-icon-button-border-width: var(--component-button-secondary-border-width);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/* ── Variant: destructive ───────────────────────────────────────────────── */
|
|
81
|
+
|
|
82
|
+
.a1-icon-button--destructive {
|
|
83
|
+
background: var(--semantic-color-status-error-surface);
|
|
84
|
+
border-color: var(--semantic-color-status-error-border);
|
|
85
|
+
color: var(--semantic-color-status-error-background);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.a1-icon-button--destructive:hover {
|
|
89
|
+
background: color-mix(in srgb, var(--semantic-color-status-error-surface), var(--semantic-color-status-error-background) 8%);
|
|
90
|
+
border-color: var(--semantic-color-status-error-background);
|
|
91
|
+
color: var(--semantic-color-status-error-background);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.a1-icon-button--destructive:active {
|
|
95
|
+
background: color-mix(in srgb, var(--semantic-color-status-error-surface), var(--semantic-color-status-error-background) 16%);
|
|
96
|
+
border-color: var(--semantic-color-status-error-background);
|
|
97
|
+
color: var(--semantic-color-status-error-background);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/* ── Variant: success ───────────────────────────────────────────────────── */
|
|
101
|
+
|
|
102
|
+
.a1-icon-button--success {
|
|
103
|
+
background: var(--semantic-color-status-success-surface);
|
|
104
|
+
border-color: var(--semantic-color-status-success-border);
|
|
105
|
+
color: var(--semantic-color-status-success-background);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.a1-icon-button--success:hover {
|
|
109
|
+
background: color-mix(in srgb, var(--semantic-color-status-success-surface), var(--semantic-color-status-success-background) 8%);
|
|
110
|
+
border-color: var(--semantic-color-status-success-background);
|
|
111
|
+
color: var(--semantic-color-status-success-background);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.a1-icon-button--success:active {
|
|
115
|
+
background: color-mix(in srgb, var(--semantic-color-status-success-surface), var(--semantic-color-status-success-background) 16%);
|
|
116
|
+
border-color: var(--semantic-color-status-success-background);
|
|
117
|
+
color: var(--semantic-color-status-success-background);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.a1-theme-dark .a1-icon-button--destructive,
|
|
121
|
+
.a1-inverse .a1-icon-button--destructive {
|
|
122
|
+
background: var(--semantic-color-status-error-background);
|
|
123
|
+
border-color: var(--semantic-color-status-error-background);
|
|
124
|
+
color: var(--semantic-color-status-error-foreground);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.a1-theme-dark .a1-icon-button--destructive:hover,
|
|
128
|
+
.a1-inverse .a1-icon-button--destructive:hover {
|
|
129
|
+
background: color-mix(in srgb, var(--semantic-color-status-error-background), black 16%);
|
|
130
|
+
border-color: var(--semantic-color-status-error-background);
|
|
131
|
+
color: var(--semantic-color-status-error-foreground);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.a1-theme-dark .a1-icon-button--destructive:active,
|
|
135
|
+
.a1-inverse .a1-icon-button--destructive:active {
|
|
136
|
+
background: color-mix(in srgb, var(--semantic-color-status-error-background), black 32%);
|
|
137
|
+
border-color: var(--semantic-color-status-error-background);
|
|
138
|
+
color: var(--semantic-color-status-error-foreground);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.a1-theme-dark .a1-icon-button--success,
|
|
142
|
+
.a1-inverse .a1-icon-button--success {
|
|
143
|
+
background: var(--semantic-color-status-success-background);
|
|
144
|
+
border-color: var(--semantic-color-status-success-background);
|
|
145
|
+
color: var(--semantic-color-status-success-foreground);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
.a1-theme-dark .a1-icon-button--success:hover,
|
|
149
|
+
.a1-inverse .a1-icon-button--success:hover {
|
|
150
|
+
background: color-mix(in srgb, var(--semantic-color-status-success-background), black 16%);
|
|
151
|
+
border-color: var(--semantic-color-status-success-background);
|
|
152
|
+
color: var(--semantic-color-status-success-foreground);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
.a1-theme-dark .a1-icon-button--success:active,
|
|
156
|
+
.a1-inverse .a1-icon-button--success:active {
|
|
157
|
+
background: color-mix(in srgb, var(--semantic-color-status-success-background), black 32%);
|
|
158
|
+
border-color: var(--semantic-color-status-success-background);
|
|
159
|
+
color: var(--semantic-color-status-success-foreground);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.a1-theme-dark .a1-inverse .a1-icon-button--destructive {
|
|
163
|
+
background: var(--semantic-color-status-error-surface);
|
|
164
|
+
border-color: var(--semantic-color-status-error-border);
|
|
165
|
+
color: var(--semantic-color-status-error-background);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
.a1-theme-dark .a1-inverse .a1-icon-button--destructive:hover {
|
|
169
|
+
background: color-mix(in srgb, var(--semantic-color-status-error-surface), var(--semantic-color-status-error-background) 8%);
|
|
170
|
+
border-color: var(--semantic-color-status-error-background);
|
|
171
|
+
color: var(--semantic-color-status-error-background);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
.a1-theme-dark .a1-inverse .a1-icon-button--destructive:active {
|
|
175
|
+
background: color-mix(in srgb, var(--semantic-color-status-error-surface), var(--semantic-color-status-error-background) 16%);
|
|
176
|
+
border-color: var(--semantic-color-status-error-background);
|
|
177
|
+
color: var(--semantic-color-status-error-background);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
.a1-theme-dark .a1-inverse .a1-icon-button--success {
|
|
181
|
+
background: var(--semantic-color-status-success-surface);
|
|
182
|
+
border-color: var(--semantic-color-status-success-border);
|
|
183
|
+
color: var(--semantic-color-status-success-background);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
.a1-theme-dark .a1-inverse .a1-icon-button--success:hover {
|
|
187
|
+
background: color-mix(in srgb, var(--semantic-color-status-success-surface), var(--semantic-color-status-success-background) 8%);
|
|
188
|
+
border-color: var(--semantic-color-status-success-background);
|
|
189
|
+
color: var(--semantic-color-status-success-background);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
.a1-theme-dark .a1-inverse .a1-icon-button--success:active {
|
|
193
|
+
background: color-mix(in srgb, var(--semantic-color-status-success-surface), var(--semantic-color-status-success-background) 16%);
|
|
194
|
+
border-color: var(--semantic-color-status-success-background);
|
|
195
|
+
color: var(--semantic-color-status-success-background);
|
|
196
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import "../../themes.css";
|
|
2
|
+
import "../../color-scheme.css";
|
|
3
|
+
|
|
4
|
+
export function Inverse({
|
|
5
|
+
as: Component = "div",
|
|
6
|
+
className = "",
|
|
7
|
+
children,
|
|
8
|
+
...props
|
|
9
|
+
}) {
|
|
10
|
+
return (
|
|
11
|
+
<Component
|
|
12
|
+
className={["a1-inverse", className].filter(Boolean).join(" ")}
|
|
13
|
+
{...props}
|
|
14
|
+
>
|
|
15
|
+
{children}
|
|
16
|
+
</Component>
|
|
17
|
+
);
|
|
18
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { createContext, useContext } from "react";
|
|
2
|
+
|
|
3
|
+
const LabelsContext = createContext({ locale: null, brand: null, labels: null });
|
|
4
|
+
|
|
5
|
+
export function LabelsProvider({ locale = null, brand = null, labels, children }) {
|
|
6
|
+
return (
|
|
7
|
+
<LabelsContext.Provider value={{ locale, brand, labels }}>
|
|
8
|
+
{children}
|
|
9
|
+
</LabelsContext.Provider>
|
|
10
|
+
);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function useLabel(key) {
|
|
14
|
+
const { locale, brand, labels } = useContext(LabelsContext);
|
|
15
|
+
if (!labels) return key;
|
|
16
|
+
|
|
17
|
+
const parts = key.split(".");
|
|
18
|
+
let node = labels?.label;
|
|
19
|
+
for (const part of parts) {
|
|
20
|
+
if (node == null || typeof node !== "object") return key;
|
|
21
|
+
node = node[part];
|
|
22
|
+
}
|
|
23
|
+
if (node == null) return key;
|
|
24
|
+
|
|
25
|
+
// Resolution order: locale > brand > default
|
|
26
|
+
if (locale && node.locale?.[locale] != null) return node.locale[locale];
|
|
27
|
+
if (brand && node.brand?.[brand] != null) return node.brand[brand];
|
|
28
|
+
return node.$value ?? key;
|
|
29
|
+
}
|