@godxjp/ui 16.3.0 → 16.5.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/dist/app/app-provider.js +1 -0
- package/dist/components/data-display/card.d.ts +5 -1
- package/dist/components/data-display/card.js +4 -2
- package/dist/components/feedback/sheet.js +3 -1
- package/dist/components/navigation/steps.js +2 -2
- package/dist/lib/control-styles.d.ts +7 -5
- package/dist/lib/control-styles.js +4 -4
- package/dist/props/registry.d.ts +1 -1
- package/dist/props/registry.js +1 -1
- package/dist/styles/alert-layout.css +7 -5
- package/dist/styles/card-layout.css +33 -1
- package/dist/styles/control.css +24 -14
- package/dist/styles/data-display-layout.css +15 -12
- package/dist/styles/data-entry-layout.css +2 -2
- package/dist/styles/dialog-layout.css +6 -2
- package/dist/styles/index.css +52 -7
- package/dist/styles/layout.css +3 -0
- package/dist/styles/navigation-layout.css +10 -10
- package/dist/styles/shell-layout.css +17 -6
- package/dist/styles/table-layout.css +5 -5
- package/dist/tokens/foundation.css +70 -8
- package/package.json +10 -8
- package/dist/tokens/components/badge.css +0 -10
- package/dist/tokens/components/card.css +0 -51
- package/dist/tokens/components/control.css +0 -82
- package/dist/tokens/components/data-display.css +0 -8
- package/dist/tokens/components/data-entry.css +0 -6
- package/dist/tokens/components/descriptions.css +0 -9
- package/dist/tokens/components/feedback.css +0 -25
- package/dist/tokens/components/form.css +0 -11
- package/dist/tokens/components/list-row.css +0 -9
- package/dist/tokens/components/navigation.css +0 -15
- package/dist/tokens/components/shell.css +0 -17
- package/dist/tokens/components/table.css +0 -13
- package/dist/tokens/semantic/layout.css +0 -49
package/dist/app/app-provider.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { type VariantProps } from "class-variance-authority";
|
|
3
|
+
import type { LucideIcon } from "lucide-react";
|
|
3
4
|
type CardSize = "md" | "compact";
|
|
4
5
|
/** Semantic leading-edge accent stripe (border-inline-start; width via the
|
|
5
6
|
* --card-accent-rail-width token, default 6px). */
|
|
@@ -86,6 +87,9 @@ export type StatCardProps = React.HTMLAttributes<HTMLDivElement> & VariantProps<
|
|
|
86
87
|
label: React.ReactNode;
|
|
87
88
|
value: React.ReactNode;
|
|
88
89
|
hint?: React.ReactNode;
|
|
90
|
+
/** Optional leading icon, rendered as a tinted medallion above the metric. Decorative
|
|
91
|
+
* (aria-hidden) — the label carries the meaning. Tint via --stat-card-icon-* tokens. */
|
|
92
|
+
icon?: LucideIcon;
|
|
89
93
|
/** Optional compact trend text beside the value. Avoid badge-like deltas. */
|
|
90
94
|
delta?: React.ReactNode;
|
|
91
95
|
/** KPI layout: stacked = design default, inline = label left / value right. */
|
|
@@ -98,7 +102,7 @@ export type StatCardProps = React.HTMLAttributes<HTMLDivElement> & VariantProps<
|
|
|
98
102
|
accent?: CardAccent;
|
|
99
103
|
};
|
|
100
104
|
/** KPI / stat tile — token-driven layout aligned to dashboard KPI cards. */
|
|
101
|
-
export declare function StatCard({ label, value, hint, delta, layout, align, inverse, accent, className, size, ...props }: StatCardProps): import("react/jsx-runtime").JSX.Element;
|
|
105
|
+
export declare function StatCard({ label, value, hint, icon: Icon, delta, layout, align, inverse, accent, className, size, ...props }: StatCardProps): import("react/jsx-runtime").JSX.Element;
|
|
102
106
|
/** Header actions slot — pair with `CardHeader className="flex flex-row …"`. */
|
|
103
107
|
export declare const CardAction: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>;
|
|
104
108
|
export {};
|
|
@@ -96,6 +96,7 @@ function StatCard({
|
|
|
96
96
|
label,
|
|
97
97
|
value,
|
|
98
98
|
hint,
|
|
99
|
+
icon: Icon,
|
|
99
100
|
delta,
|
|
100
101
|
layout = "stacked",
|
|
101
102
|
align = "start",
|
|
@@ -117,6 +118,7 @@ function StatCard({
|
|
|
117
118
|
"data-stat-align": align,
|
|
118
119
|
...props,
|
|
119
120
|
children: [
|
|
121
|
+
Icon ? /* @__PURE__ */ jsx("span", { "data-slot": "stat-card-icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx(Icon, {}) }) : null,
|
|
120
122
|
/* @__PURE__ */ jsxs("div", { "data-slot": "stat-card-body", children: [
|
|
121
123
|
/* @__PURE__ */ jsx("div", { "data-slot": "stat-card-label", children: label }),
|
|
122
124
|
hint && layout === "inline" ? /* @__PURE__ */ jsx("div", { "data-slot": "stat-card-hint", children: hint }) : null
|
|
@@ -130,8 +132,8 @@ function StatCard({
|
|
|
130
132
|
"data-slot": "stat-card-delta",
|
|
131
133
|
"data-delta-tone": deltaTone,
|
|
132
134
|
className: cn(
|
|
133
|
-
deltaTone === "positive" && "text-success",
|
|
134
|
-
deltaTone === "negative" && "text-
|
|
135
|
+
deltaTone === "positive" && "text-success-strong",
|
|
136
|
+
deltaTone === "negative" && "text-error-strong"
|
|
135
137
|
),
|
|
136
138
|
children: delta
|
|
137
139
|
}
|
|
@@ -24,7 +24,9 @@ const SheetOverlay = React.forwardRef(({ className, ...props }, ref) => /* @__PU
|
|
|
24
24
|
ref,
|
|
25
25
|
"data-slot": "sheet-overlay",
|
|
26
26
|
className: cn(
|
|
27
|
-
|
|
27
|
+
// Scrim colour comes from the shared --overlay-background token (see dialog-layout.css),
|
|
28
|
+
// so a service tints every overlay's backdrop from one knob instead of a baked bg-black/50.
|
|
29
|
+
"data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0 fixed inset-0 z-50",
|
|
28
30
|
className
|
|
29
31
|
),
|
|
30
32
|
...props
|
|
@@ -17,7 +17,7 @@ function StepIcon({
|
|
|
17
17
|
if (icon)
|
|
18
18
|
return /* @__PURE__ */ jsx("span", { className: cn("flex items-center justify-center", controlIconClass), children: icon });
|
|
19
19
|
if (type === "dot") {
|
|
20
|
-
return /* @__PURE__ */ jsx(
|
|
20
|
+
return /* @__PURE__ */ jsx("span", { className: cn("flex items-center justify-center", controlIconClass), children: /* @__PURE__ */ jsx(
|
|
21
21
|
"span",
|
|
22
22
|
{
|
|
23
23
|
className: cn(
|
|
@@ -28,7 +28,7 @@ function StepIcon({
|
|
|
28
28
|
status === "wait" && "bg-muted-foreground/30"
|
|
29
29
|
)
|
|
30
30
|
}
|
|
31
|
-
);
|
|
31
|
+
) });
|
|
32
32
|
}
|
|
33
33
|
return /* @__PURE__ */ jsxs(
|
|
34
34
|
"span",
|
|
@@ -17,10 +17,12 @@ export declare const controlIconLeadingClass = "size-[length:var(--control-icon-
|
|
|
17
17
|
export declare const tableRowHeightClass = "h-[length:var(--table-row-height)]";
|
|
18
18
|
export declare const tableHeadHeightClass = "h-[length:var(--table-row-height)]";
|
|
19
19
|
export declare const tableCellPaddingClass = "py-[length:var(--table-cell-padding-y)]";
|
|
20
|
-
/** Semantic status / badge tones — always use tokens, never raw Tailwind palette.
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
export declare const
|
|
24
|
-
export declare const
|
|
20
|
+
/** Semantic status / badge tones — always use tokens, never raw Tailwind palette. The TEXT uses the
|
|
21
|
+
* AA-strong status colours (text-*-strong, darker than the fill) so a small status label clears
|
|
22
|
+
* WCAG AA on the soft tint; the border/fill keep the brighter wa-iro role. */
|
|
23
|
+
export declare const toneSuccessClass = "border-success/30 bg-success/10 text-success-strong";
|
|
24
|
+
export declare const toneWarningClass = "border-warning/30 bg-warning/10 text-warning-strong";
|
|
25
|
+
export declare const toneInfoClass = "border-info/30 bg-info/10 text-info-strong";
|
|
26
|
+
export declare const toneDestructiveClass = "border-destructive/30 bg-destructive/10 text-error-strong";
|
|
25
27
|
export declare const toneMutedClass = "border-border bg-muted text-muted-foreground";
|
|
26
28
|
export declare const toneNeutralClass = "border-border bg-muted text-muted-foreground";
|
|
@@ -8,10 +8,10 @@ const controlIconLeadingClass = "size-[length:var(--control-icon-size)] shrink-0
|
|
|
8
8
|
const tableRowHeightClass = "h-[length:var(--table-row-height)]";
|
|
9
9
|
const tableHeadHeightClass = "h-[length:var(--table-row-height)]";
|
|
10
10
|
const tableCellPaddingClass = "py-[length:var(--table-cell-padding-y)]";
|
|
11
|
-
const toneSuccessClass = "border-success/30 bg-success/10 text-success";
|
|
12
|
-
const toneWarningClass = "border-warning/30 bg-warning/10 text-warning-
|
|
13
|
-
const toneInfoClass = "border-info/30 bg-info/10 text-info";
|
|
14
|
-
const toneDestructiveClass = "border-destructive/30 bg-destructive/10 text-
|
|
11
|
+
const toneSuccessClass = "border-success/30 bg-success/10 text-success-strong";
|
|
12
|
+
const toneWarningClass = "border-warning/30 bg-warning/10 text-warning-strong";
|
|
13
|
+
const toneInfoClass = "border-info/30 bg-info/10 text-info-strong";
|
|
14
|
+
const toneDestructiveClass = "border-destructive/30 bg-destructive/10 text-error-strong";
|
|
15
15
|
const toneMutedClass = "border-border bg-muted text-muted-foreground";
|
|
16
16
|
const toneNeutralClass = "border-border bg-muted text-muted-foreground";
|
|
17
17
|
export {
|
package/dist/props/registry.d.ts
CHANGED
|
@@ -1086,7 +1086,7 @@ export declare const COMPONENT_PROP_REGISTRY: {
|
|
|
1086
1086
|
readonly StatCardProp: {
|
|
1087
1087
|
readonly group: "data-display";
|
|
1088
1088
|
readonly file: "components/data-display/card.tsx";
|
|
1089
|
-
readonly vocabulary: readonly ["TitleProp", "ToneProp", "ClassNameProp"];
|
|
1089
|
+
readonly vocabulary: readonly ["TitleProp", "ToneProp", "IconProp", "ClassNameProp"];
|
|
1090
1090
|
};
|
|
1091
1091
|
readonly ResponsiveGridProp: {
|
|
1092
1092
|
readonly group: "layout";
|
package/dist/props/registry.js
CHANGED
|
@@ -1080,7 +1080,7 @@ const COMPONENT_PROP_REGISTRY = {
|
|
|
1080
1080
|
StatCardProp: {
|
|
1081
1081
|
group: "data-display",
|
|
1082
1082
|
file: "components/data-display/card.tsx",
|
|
1083
|
-
vocabulary: ["TitleProp", "ToneProp", "ClassNameProp"]
|
|
1083
|
+
vocabulary: ["TitleProp", "ToneProp", "IconProp", "ClassNameProp"]
|
|
1084
1084
|
},
|
|
1085
1085
|
ResponsiveGridProp: {
|
|
1086
1086
|
group: "layout",
|
|
@@ -120,20 +120,22 @@
|
|
|
120
120
|
line-height: 1;
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
+
/* Title text reads the AA-strong status colour (darker than the fill) so the coloured heading
|
|
124
|
+
* clears WCAG AA on the soft alert tint; the icon keeps the brighter role colour. */
|
|
123
125
|
[data-slot="alert-title"][data-tone="destructive"] {
|
|
124
|
-
color: hsl(var(--
|
|
126
|
+
color: hsl(var(--text-error));
|
|
125
127
|
}
|
|
126
128
|
|
|
127
129
|
[data-slot="alert-title"][data-tone="warning"] {
|
|
128
|
-
color: hsl(var(--warning));
|
|
130
|
+
color: hsl(var(--text-warning));
|
|
129
131
|
}
|
|
130
132
|
|
|
131
133
|
[data-slot="alert-title"][data-tone="success"] {
|
|
132
|
-
color: hsl(var(--success));
|
|
134
|
+
color: hsl(var(--text-success));
|
|
133
135
|
}
|
|
134
136
|
|
|
135
137
|
[data-slot="alert-title"][data-tone="info"] {
|
|
136
|
-
color: hsl(var(--info));
|
|
138
|
+
color: hsl(var(--text-info));
|
|
137
139
|
}
|
|
138
140
|
|
|
139
141
|
[data-slot="alert-description"] {
|
|
@@ -168,7 +170,7 @@
|
|
|
168
170
|
|
|
169
171
|
.ui-skeleton-block {
|
|
170
172
|
border-radius: var(--skeleton-radius);
|
|
171
|
-
background:
|
|
173
|
+
background: var(--skeleton-background);
|
|
172
174
|
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
|
173
175
|
}
|
|
174
176
|
|
|
@@ -29,8 +29,15 @@
|
|
|
29
29
|
border-style: solid;
|
|
30
30
|
border-color: hsl(var(--card-border));
|
|
31
31
|
border-radius: var(--card-radius);
|
|
32
|
-
|
|
32
|
+
/* Fill = base card colour with an opt-in role tint washed over it (--card-tint default
|
|
33
|
+
* transparent → byte-identical at rest). Tint layer sits ABOVE the base colour. */
|
|
34
|
+
background:
|
|
35
|
+
linear-gradient(var(--card-tint), var(--card-tint)),
|
|
36
|
+
hsl(var(--card-background));
|
|
33
37
|
color: hsl(var(--card-foreground));
|
|
38
|
+
/* Resting elevation + opt-in brand glow — both quiet no-ops by default so a service theme can
|
|
39
|
+
* lift (--card-shadow) and/or glow (--card-glow) every card with no markup change. */
|
|
40
|
+
box-shadow: var(--card-shadow), var(--card-glow);
|
|
34
41
|
overflow: hidden;
|
|
35
42
|
}
|
|
36
43
|
|
|
@@ -384,6 +391,31 @@
|
|
|
384
391
|
min-width: 0;
|
|
385
392
|
}
|
|
386
393
|
|
|
394
|
+
/* Optional leading icon medallion — tinted box above the metric. Tone via tokens (default a
|
|
395
|
+
* soft brand-primary tint), so a service rethemes it with --primary or the icon tokens. */
|
|
396
|
+
[data-slot="stat-card-icon"] {
|
|
397
|
+
display: inline-flex;
|
|
398
|
+
align-items: center;
|
|
399
|
+
justify-content: center;
|
|
400
|
+
width: var(--stat-card-icon-size);
|
|
401
|
+
height: var(--stat-card-icon-size);
|
|
402
|
+
margin-bottom: var(--stat-card-gap);
|
|
403
|
+
border-radius: var(--stat-card-icon-radius);
|
|
404
|
+
background: var(--stat-card-icon-background);
|
|
405
|
+
color: var(--stat-card-icon-foreground);
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
[data-slot="stat-card-icon"] svg {
|
|
409
|
+
width: var(--stat-card-icon-glyph-size);
|
|
410
|
+
height: var(--stat-card-icon-glyph-size);
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
/* Inline layout: medallion floats to the trailing edge so label/value keep the start column. */
|
|
414
|
+
[data-slot="card"][data-stat-layout="inline"] [data-slot="stat-card-icon"] {
|
|
415
|
+
margin-bottom: 0;
|
|
416
|
+
order: 1;
|
|
417
|
+
}
|
|
418
|
+
|
|
387
419
|
[data-slot="stat-card-label"] {
|
|
388
420
|
display: flex;
|
|
389
421
|
align-items: center;
|
package/dist/styles/control.css
CHANGED
|
@@ -50,13 +50,13 @@
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
.ui-toggle[data-state="on"] {
|
|
53
|
-
background:
|
|
53
|
+
background: var(--toggle-on-background);
|
|
54
54
|
color: hsl(var(--primary-foreground));
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
.ui-toggle:focus-visible {
|
|
58
58
|
outline: none;
|
|
59
|
-
box-shadow: 0 0 0 3px hsl(var(--ring) / 0.35);
|
|
59
|
+
box-shadow: 0 0 0 3px hsl(var(--focus-ring-color) / 0.35);
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
.ui-toggle:disabled,
|
|
@@ -85,7 +85,7 @@
|
|
|
85
85
|
|
|
86
86
|
.ui-button:focus-visible {
|
|
87
87
|
outline: none;
|
|
88
|
-
box-shadow: 0 0 0 var(--
|
|
88
|
+
box-shadow: 0 0 0 var(--focus-ring-width) hsl(var(--focus-ring-color));
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
.ui-button:disabled {
|
|
@@ -102,7 +102,9 @@
|
|
|
102
102
|
.ui-button--default {
|
|
103
103
|
background: hsl(var(--primary));
|
|
104
104
|
color: hsl(var(--primary-foreground));
|
|
105
|
-
|
|
105
|
+
/* Brand glow layers on top of the resting shadow; --shadow-glow is invisible by default
|
|
106
|
+
* (quiet) so a service opts the CTA halo in by setting the token alone. */
|
|
107
|
+
box-shadow: var(--shadow-sm), var(--shadow-glow);
|
|
106
108
|
}
|
|
107
109
|
|
|
108
110
|
.ui-button--default:hover {
|
|
@@ -119,9 +121,17 @@
|
|
|
119
121
|
background: hsl(var(--destructive) / 0.9);
|
|
120
122
|
}
|
|
121
123
|
|
|
124
|
+
/* Outline + ghost set their text colour EXPLICITLY (read --foreground) — never rely on inherited
|
|
125
|
+
* body colour. Inheriting breaks in a scoped dark region (e.g. an on-navy hero): the body's
|
|
126
|
+
* computed dark colour would carry in and the label goes near-invisible on the dark fill. */
|
|
122
127
|
.ui-button--outline {
|
|
123
128
|
border: 1px solid hsl(var(--input));
|
|
124
129
|
background: hsl(var(--background));
|
|
130
|
+
color: hsl(var(--foreground));
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.ui-button--ghost {
|
|
134
|
+
color: hsl(var(--foreground));
|
|
125
135
|
}
|
|
126
136
|
|
|
127
137
|
.ui-button--outline:hover,
|
|
@@ -277,7 +287,7 @@
|
|
|
277
287
|
.ui-slider-thumb:focus-visible,
|
|
278
288
|
.ui-switch:focus-visible {
|
|
279
289
|
outline: none;
|
|
280
|
-
box-shadow: 0 0 0 var(--
|
|
290
|
+
box-shadow: 0 0 0 var(--focus-ring-width) hsl(var(--focus-ring-color));
|
|
281
291
|
}
|
|
282
292
|
|
|
283
293
|
.ui-checkbox:disabled,
|
|
@@ -289,7 +299,7 @@
|
|
|
289
299
|
}
|
|
290
300
|
|
|
291
301
|
.ui-checkbox[data-state="checked"] {
|
|
292
|
-
background:
|
|
302
|
+
background: var(--checkbox-checked-background);
|
|
293
303
|
color: hsl(var(--primary-foreground));
|
|
294
304
|
}
|
|
295
305
|
|
|
@@ -326,7 +336,7 @@
|
|
|
326
336
|
}
|
|
327
337
|
|
|
328
338
|
.ui-switch[data-state="checked"] {
|
|
329
|
-
background:
|
|
339
|
+
background: var(--switch-checked-background);
|
|
330
340
|
}
|
|
331
341
|
|
|
332
342
|
.ui-switch[data-state="unchecked"] {
|
|
@@ -364,13 +374,13 @@
|
|
|
364
374
|
flex-grow: 1;
|
|
365
375
|
overflow: hidden;
|
|
366
376
|
border-radius: var(--radius-pill);
|
|
367
|
-
background:
|
|
377
|
+
background: var(--slider-track-background);
|
|
368
378
|
}
|
|
369
379
|
|
|
370
380
|
.ui-slider-range {
|
|
371
381
|
position: absolute;
|
|
372
382
|
height: 100%;
|
|
373
|
-
background:
|
|
383
|
+
background: var(--slider-range-background);
|
|
374
384
|
}
|
|
375
385
|
|
|
376
386
|
.ui-slider-thumb {
|
|
@@ -646,13 +656,13 @@
|
|
|
646
656
|
}
|
|
647
657
|
.ui-otp-slot[data-active="true"] {
|
|
648
658
|
z-index: 1;
|
|
649
|
-
box-shadow: 0 0 0
|
|
659
|
+
box-shadow: 0 0 0 var(--focus-ring-width) hsl(var(--focus-ring-color));
|
|
650
660
|
}
|
|
651
661
|
.ui-otp-container:has(.ui-otp-input[aria-invalid="true"]) .ui-otp-slot {
|
|
652
662
|
border-color: hsl(var(--destructive));
|
|
653
663
|
}
|
|
654
664
|
.ui-otp-container:has(.ui-otp-input[aria-invalid="true"]) .ui-otp-slot[data-active="true"] {
|
|
655
|
-
box-shadow: 0 0 0
|
|
665
|
+
box-shadow: 0 0 0 var(--focus-ring-width) hsl(var(--destructive));
|
|
656
666
|
}
|
|
657
667
|
.ui-otp-container:has(.ui-otp-input:disabled) .ui-otp-slot {
|
|
658
668
|
cursor: not-allowed;
|
|
@@ -717,7 +727,7 @@
|
|
|
717
727
|
fill: currentColor;
|
|
718
728
|
}
|
|
719
729
|
.ui-rating-star:focus-visible {
|
|
720
|
-
outline:
|
|
730
|
+
outline: var(--focus-ring-width) solid hsl(var(--focus-ring-color));
|
|
721
731
|
outline-offset: 2px;
|
|
722
732
|
border-radius: var(--radius-sm);
|
|
723
733
|
}
|
|
@@ -735,8 +745,8 @@
|
|
|
735
745
|
background: hsl(var(--background));
|
|
736
746
|
}
|
|
737
747
|
.ui-tag-input:focus-within {
|
|
738
|
-
box-shadow: 0 0 0
|
|
739
|
-
border-color: hsl(var(--ring));
|
|
748
|
+
box-shadow: 0 0 0 var(--focus-ring-width) hsl(var(--focus-ring-color));
|
|
749
|
+
border-color: hsl(var(--focus-ring-color));
|
|
740
750
|
}
|
|
741
751
|
.ui-tag-input-disabled {
|
|
742
752
|
opacity: 0.6;
|
|
@@ -9,7 +9,10 @@
|
|
|
9
9
|
justify-content: center;
|
|
10
10
|
overflow: hidden;
|
|
11
11
|
border-radius: var(--radius-pill);
|
|
12
|
-
background
|
|
12
|
+
/* Tint washes over the role background (default transparent = no-op, rule #44). */
|
|
13
|
+
background:
|
|
14
|
+
linear-gradient(var(--avatar-tint), var(--avatar-tint)),
|
|
15
|
+
var(--avatar-background);
|
|
13
16
|
color: hsl(var(--muted-foreground));
|
|
14
17
|
font-size: var(--font-size-base);
|
|
15
18
|
font-weight: var(--font-weight-medium);
|
|
@@ -27,7 +30,7 @@
|
|
|
27
30
|
height: 100%;
|
|
28
31
|
align-items: center;
|
|
29
32
|
justify-content: center;
|
|
30
|
-
background:
|
|
33
|
+
background: var(--avatar-background);
|
|
31
34
|
}
|
|
32
35
|
|
|
33
36
|
.ui-progress {
|
|
@@ -40,13 +43,13 @@
|
|
|
40
43
|
height: 0.5rem;
|
|
41
44
|
overflow: hidden;
|
|
42
45
|
border-radius: var(--radius-pill);
|
|
43
|
-
background:
|
|
46
|
+
background: var(--progress-track-background);
|
|
44
47
|
}
|
|
45
48
|
|
|
46
49
|
.ui-progress-bar {
|
|
47
50
|
height: 100%;
|
|
48
51
|
border-radius: inherit;
|
|
49
|
-
background:
|
|
52
|
+
background: var(--progress-fill-background);
|
|
50
53
|
}
|
|
51
54
|
|
|
52
55
|
.ui-progress[data-tone="warning"] .ui-progress-bar {
|
|
@@ -75,8 +78,8 @@
|
|
|
75
78
|
}
|
|
76
79
|
|
|
77
80
|
.ui-tree-item[data-active="true"] {
|
|
78
|
-
border-color:
|
|
79
|
-
background:
|
|
81
|
+
border-color: var(--tree-item-active-border);
|
|
82
|
+
background: var(--tree-item-active-background);
|
|
80
83
|
}
|
|
81
84
|
|
|
82
85
|
.ui-tree-item[data-depth="1"] {
|
|
@@ -151,7 +154,7 @@
|
|
|
151
154
|
place-items: center;
|
|
152
155
|
border: 1px solid transparent;
|
|
153
156
|
border-radius: var(--radius-pill);
|
|
154
|
-
background:
|
|
157
|
+
background: var(--timeline-dot-done-background);
|
|
155
158
|
color: hsl(var(--success-foreground));
|
|
156
159
|
font-size: var(--timeline-note-font-size);
|
|
157
160
|
font-weight: var(--font-weight-medium);
|
|
@@ -160,14 +163,14 @@
|
|
|
160
163
|
|
|
161
164
|
/* done → success fill. */
|
|
162
165
|
.ui-timeline-dot[data-status="done"] {
|
|
163
|
-
background:
|
|
166
|
+
background: var(--timeline-dot-done-background);
|
|
164
167
|
color: hsl(var(--success-foreground));
|
|
165
168
|
}
|
|
166
169
|
|
|
167
170
|
/* current → primary fill + ring (also the legacy data-current shorthand). */
|
|
168
171
|
.ui-timeline-dot[data-status="current"],
|
|
169
172
|
.ui-timeline-dot[data-current="true"] {
|
|
170
|
-
background:
|
|
173
|
+
background: var(--timeline-dot-current-background);
|
|
171
174
|
color: hsl(var(--primary-foreground));
|
|
172
175
|
box-shadow: 0 0 0 3px hsl(var(--primary) / 0.18);
|
|
173
176
|
}
|
|
@@ -202,7 +205,7 @@
|
|
|
202
205
|
|
|
203
206
|
/* The segment below a done/current step reads as travelled (completed). */
|
|
204
207
|
.ui-timeline-line[data-completed="true"] {
|
|
205
|
-
background:
|
|
208
|
+
background: var(--timeline-line-completed-background);
|
|
206
209
|
}
|
|
207
210
|
|
|
208
211
|
.ui-timeline-head {
|
|
@@ -256,7 +259,7 @@
|
|
|
256
259
|
text-decoration: underline;
|
|
257
260
|
}
|
|
258
261
|
.ui-accordion-trigger:focus-visible {
|
|
259
|
-
outline:
|
|
262
|
+
outline: var(--focus-ring-width) solid hsl(var(--focus-ring-color));
|
|
260
263
|
outline-offset: 2px;
|
|
261
264
|
border-radius: var(--radius-sm);
|
|
262
265
|
}
|
|
@@ -383,7 +386,7 @@
|
|
|
383
386
|
}
|
|
384
387
|
|
|
385
388
|
.ui-carousel-dot:focus-visible {
|
|
386
|
-
outline:
|
|
389
|
+
outline: var(--focus-ring-width) solid hsl(var(--focus-ring-color));
|
|
387
390
|
outline-offset: 2px;
|
|
388
391
|
}
|
|
389
392
|
|
|
@@ -83,8 +83,8 @@
|
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
.ui-time-input:focus-visible {
|
|
86
|
-
border-color: hsl(var(--ring));
|
|
87
|
-
box-shadow: 0 0 0 3px hsl(var(--ring) / 0.3);
|
|
86
|
+
border-color: hsl(var(--focus-ring-color));
|
|
87
|
+
box-shadow: 0 0 0 3px hsl(var(--focus-ring-color) / 0.3);
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
.ui-time-input[aria-invalid="true"] {
|
|
@@ -21,11 +21,15 @@
|
|
|
21
21
|
border-top: 1px solid hsl(var(--border));
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
.ui-dialog-overlay,
|
|
25
|
+
[data-slot="sheet-overlay"] {
|
|
26
|
+
background-color: var(--overlay-background);
|
|
27
|
+
}
|
|
28
|
+
|
|
24
29
|
.ui-dialog-overlay {
|
|
25
30
|
position: fixed;
|
|
26
31
|
inset: 0;
|
|
27
32
|
z-index: 50;
|
|
28
|
-
background-color: rgb(0 0 0 / 0.5);
|
|
29
33
|
}
|
|
30
34
|
|
|
31
35
|
[data-slot="dialog-content"] {
|
|
@@ -43,7 +47,7 @@
|
|
|
43
47
|
padding: var(--dialog-space-inset);
|
|
44
48
|
/* clip so the full-bleed header/footer bands round with the dialog corners (Ant Modal). */
|
|
45
49
|
overflow: hidden;
|
|
46
|
-
box-shadow: var(--shadow-lg, 0 10px 15px -3px rgb(0 0 0 / 0.1));
|
|
50
|
+
box-shadow: var(--shadow-lg, 0 10px 15px -3px rgb(0 0 0 / 0.1)), var(--dialog-content-glow);
|
|
47
51
|
}
|
|
48
52
|
|
|
49
53
|
@media (min-width: 640px) {
|
package/dist/styles/index.css
CHANGED
|
@@ -1,11 +1,29 @@
|
|
|
1
1
|
@import "sonner/dist/styles.css";
|
|
2
2
|
@import "react-day-picker/style.css";
|
|
3
|
-
/*
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
/* Bundled sans fonts — self-contained so consumers need no font config. The browser only
|
|
4
|
+
* downloads the subset files matching the rendered text:
|
|
5
|
+
* · Noto Sans JP — the DEFAULT face (Japanese + Latin), used for all locales except `vi`.
|
|
6
|
+
* · Montserrat — swapped in for the Vietnamese locale (`<html lang="vi">`), incl. its
|
|
7
|
+
* `vietnamese` subset for full diacritics. See --font-family-sans + :lang(vi). */
|
|
8
|
+
@import "@fontsource/noto-sans-jp/400.css";
|
|
9
|
+
@import "@fontsource/noto-sans-jp/500.css";
|
|
10
|
+
@import "@fontsource/noto-sans-jp/700.css";
|
|
11
|
+
@import "@fontsource/montserrat/400.css";
|
|
12
|
+
@import "@fontsource/montserrat/500.css";
|
|
13
|
+
@import "@fontsource/montserrat/700.css";
|
|
7
14
|
@import "tailwindcss";
|
|
8
15
|
|
|
16
|
+
/* Vietnamese locale → Montserrat (set by AppProvider via <html lang="vi">). Overrides the
|
|
17
|
+
* --font-family-sans token so every body/heading rule that reads it switches automatically. */
|
|
18
|
+
:root:lang(vi),
|
|
19
|
+
[lang="vi"] {
|
|
20
|
+
/* Montserrat for Latin/Vietnamese; Noto Sans JP kept as the tail so any 日本語 in a vi-locale
|
|
21
|
+
* screen still has the bundled JP face (Montserrat has no CJK glyphs). */
|
|
22
|
+
--font-family-sans:
|
|
23
|
+
"Montserrat", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial,
|
|
24
|
+
system-ui, "Noto Sans JP", sans-serif;
|
|
25
|
+
}
|
|
26
|
+
|
|
9
27
|
/* Guarantee the full set of semantic color utilities ships in the compiled CSS
|
|
10
28
|
* even when the library itself only references a few — consumers (and the token
|
|
11
29
|
* docs) must be able to use bg/text/border for EVERY semantic role. Without this
|
|
@@ -23,6 +41,8 @@
|
|
|
23
41
|
* `var(--radius-2xl)` directly; without a generated utility Tailwind drops the unused var). */
|
|
24
42
|
@source inline("rounded-{xs,xl,2xl}");
|
|
25
43
|
@source inline("text-2xs");
|
|
44
|
+
@source inline("text-{3xl,4xl,5xl}");
|
|
45
|
+
@source inline("text-{success,warning,info,error}-strong");
|
|
26
46
|
/* `.js` matters: the published package ships only compiled JS under dist (no
|
|
27
47
|
* .tsx sources), and this file is copied verbatim into dist/styles — without
|
|
28
48
|
* it Tailwind finds no component classes in consumers (unstyled popovers and
|
|
@@ -46,7 +66,14 @@
|
|
|
46
66
|
@import "./navigation-layout.css";
|
|
47
67
|
@import "./chart-layout.css";
|
|
48
68
|
|
|
49
|
-
@theme
|
|
69
|
+
/* `inline` (NOT a bare @theme): Tailwind inlines each expression — e.g. `hsl(var(--primary))` —
|
|
70
|
+
* directly into every utility (`bg-primary` becomes `background-color: hsl(var(--primary))`) instead
|
|
71
|
+
* of emitting `var(--color-primary)` computed once at :root. This is THE enabler for scoped /
|
|
72
|
+
* multi-tenant theming: a `[data-tenant]{ --primary: … }` override now re-resolves at the element,
|
|
73
|
+
* so colors and radius propagate into a subtree (a plain @theme froze them at :root, so scoped
|
|
74
|
+
* overrides never reached the color utilities). Components read raw tokens like `hsl(var(--primary))`
|
|
75
|
+
* directly in their own CSS, so they re-theme the same way. */
|
|
76
|
+
@theme inline {
|
|
50
77
|
--color-background: hsl(var(--background));
|
|
51
78
|
--color-foreground: hsl(var(--foreground));
|
|
52
79
|
--color-card: hsl(var(--card));
|
|
@@ -74,6 +101,12 @@
|
|
|
74
101
|
--color-info-foreground: hsl(var(--info-foreground));
|
|
75
102
|
--color-attention: hsl(var(--attention));
|
|
76
103
|
--color-attention-foreground: hsl(var(--attention-foreground));
|
|
104
|
+
/* AA-strong status TEXT colours (text-{success,warning,info,error}-strong) — darker than the
|
|
105
|
+
* fills so small coloured labels clear WCAG AA on white; flip light on the dark theme. */
|
|
106
|
+
--color-success-strong: hsl(var(--text-success));
|
|
107
|
+
--color-warning-strong: hsl(var(--text-warning));
|
|
108
|
+
--color-info-strong: hsl(var(--text-info));
|
|
109
|
+
--color-error-strong: hsl(var(--text-error));
|
|
77
110
|
--color-chart-1: var(--chart-1);
|
|
78
111
|
--color-chart-2: var(--chart-2);
|
|
79
112
|
--color-chart-3: var(--chart-3);
|
|
@@ -127,6 +160,10 @@
|
|
|
127
160
|
--text-lg: var(--font-size-lg);
|
|
128
161
|
--text-xl: var(--font-size-xl);
|
|
129
162
|
--text-2xl: var(--font-size-2xl);
|
|
163
|
+
/* Opt-in DISPLAY ramp (marketing/hero) — wired to the display tokens, unused by the admin scale. */
|
|
164
|
+
--text-3xl: var(--font-size-3xl);
|
|
165
|
+
--text-4xl: var(--font-size-4xl);
|
|
166
|
+
--text-5xl: var(--font-size-5xl);
|
|
130
167
|
}
|
|
131
168
|
|
|
132
169
|
@layer base {
|
|
@@ -154,7 +191,9 @@
|
|
|
154
191
|
body {
|
|
155
192
|
background-color: hsl(var(--background));
|
|
156
193
|
color: hsl(var(--foreground));
|
|
157
|
-
font-family
|
|
194
|
+
/* Body reads --font-family-body (defaults to --font-family-sans → unchanged); a service that
|
|
195
|
+
* wants a dual-font brand (display + body face) overrides --font-family-body alone. */
|
|
196
|
+
font-family: var(--font-family-body);
|
|
158
197
|
font-size: var(--font-size-base);
|
|
159
198
|
line-height: var(--line-height-body);
|
|
160
199
|
font-feature-settings:
|
|
@@ -168,7 +207,13 @@
|
|
|
168
207
|
|
|
169
208
|
/* Semantic heading scale — SEO + accessibility: real <h1>–<h6> elements carry
|
|
170
209
|
* the document outline (one <h1> per page, levels never skipped). Visual size
|
|
171
|
-
* follows the dxs-kintai scale; component titles override via their own class.
|
|
210
|
+
* follows the dxs-kintai scale; component titles override via their own class.
|
|
211
|
+
* Headings read --font-family-display (defaults to --font-family-sans → unchanged) for dual-font
|
|
212
|
+
* brands (display face on headings, body face on prose). */
|
|
213
|
+
:where(h1, h2, h3, h4, h5, h6) {
|
|
214
|
+
font-family: var(--font-family-display);
|
|
215
|
+
}
|
|
216
|
+
|
|
172
217
|
h1 {
|
|
173
218
|
font-size: var(--heading-h1);
|
|
174
219
|
font-weight: var(--font-weight-medium);
|
package/dist/styles/layout.css
CHANGED
|
@@ -345,6 +345,9 @@
|
|
|
345
345
|
gap: var(--space-stack-sm);
|
|
346
346
|
padding-bottom: var(--page-header-pad-bottom);
|
|
347
347
|
border-bottom: var(--page-header-divider);
|
|
348
|
+
/* Hero banner hook — invisible by default (--gradient-hero: none); a service paints a hero
|
|
349
|
+
* gradient across the page header (full-bleed) by configuring the token alone. */
|
|
350
|
+
background-image: var(--gradient-hero);
|
|
348
351
|
}
|
|
349
352
|
|
|
350
353
|
.ui-page-header-row {
|