@godxjp/ui 16.10.0 → 17.0.1
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 +30 -5
- package/dist/components/charts/chart-cartesian.js +1 -6
- package/dist/components/charts/pie-chart.js +1 -8
- package/dist/components/data-display/empty-state.d.ts +1 -1
- package/dist/components/data-display/empty-state.js +25 -7
- package/dist/components/data-entry/form-field.js +13 -4
- package/dist/components/data-entry/search-select.d.ts +1 -1
- package/dist/components/data-entry/search-select.js +97 -19
- package/dist/components/data-entry/select.js +15 -4
- package/dist/components/feedback/alert.d.ts +11 -2
- package/dist/components/feedback/alert.js +51 -9
- package/dist/components/general/button.js +2 -0
- package/dist/components/general/index.d.ts +2 -0
- package/dist/components/general/index.js +2 -0
- package/dist/components/general/reveal.d.ts +14 -0
- package/dist/components/general/reveal.js +21 -0
- package/dist/components/layout/auth-shell.d.ts +11 -0
- package/dist/components/layout/auth-shell.js +15 -0
- package/dist/components/layout/flex.js +1 -1
- package/dist/components/layout/index.d.ts +2 -0
- package/dist/components/layout/index.js +2 -0
- package/dist/components/layout/page-container.js +4 -4
- package/dist/components/navigation/app-setting-picker.js +19 -4
- package/dist/components/navigation/pagination.d.ts +1 -1
- package/dist/components/navigation/pagination.js +2 -1
- package/dist/components/query/data-state.d.ts +1 -1
- package/dist/components/query/data-state.js +27 -4
- package/dist/components/query/index.d.ts +2 -0
- package/dist/components/query/index.js +4 -1
- package/dist/i18n/messages/en.json +30 -2
- package/dist/i18n/messages/ja.json +30 -2
- package/dist/i18n/messages/vi.json +30 -2
- package/dist/lib/query-error.d.ts +17 -0
- package/dist/lib/query-error.js +58 -0
- package/dist/props/components/app.prop.d.ts +9 -1
- package/dist/props/components/data-display.prop.d.ts +15 -0
- package/dist/props/components/data-entry.prop.d.ts +8 -0
- package/dist/props/components/feedback.prop.d.ts +6 -0
- package/dist/props/components/general.prop.d.ts +23 -1
- package/dist/props/components/layout.prop.d.ts +17 -0
- package/dist/props/components/query.prop.d.ts +7 -1
- package/dist/props/registry.d.ts +31 -2
- package/dist/props/registry.js +44 -2
- package/dist/props/vocabulary/index.d.ts +1 -1
- package/dist/props/vocabulary/interaction.prop.d.ts +17 -1
- package/dist/styles/alert-layout.css +1 -2
- package/dist/styles/base.css +1 -1
- package/dist/styles/card-layout.css +6 -6
- package/dist/styles/index.css +1 -0
- package/dist/styles/layout.css +28 -0
- package/dist/styles/motion.css +52 -0
- package/dist/styles/shell-layout.css +42 -0
- package/dist/styles/text-layout.css +1 -1
- package/dist/theme/famgia.service.css +15 -14
- package/dist/tokens/components/card.css +1 -1
- package/dist/tokens/components/feedback.css +4 -0
- package/dist/tokens/components/shell.css +10 -0
- package/dist/tokens/foundation.css +11 -5
- package/package.json +7 -3
- package/scripts/ui-audit.mjs +2 -2
- package/scripts/visual-audit-rules.mjs +2 -2
- package/scripts/visual-audit.mjs +293 -126
|
@@ -8,13 +8,19 @@ import type { ClassNameProp, HandlerProp } from "../vocabulary/index.js";
|
|
|
8
8
|
export type DataStateProp<T> = {
|
|
9
9
|
query: UseQueryResult<T>;
|
|
10
10
|
skeleton: React.ReactNode;
|
|
11
|
+
/** Rendered when a query is disabled/unstarted (`fetchStatus: "idle"` with no data). */
|
|
12
|
+
prerequisite?: React.ReactNode;
|
|
11
13
|
empty?: React.ReactNode;
|
|
12
14
|
isEmpty?: (data: NonNullable<T>) => boolean;
|
|
13
15
|
errorRenderer?: (error: unknown, retry: () => void) => React.ReactNode;
|
|
14
|
-
/**
|
|
16
|
+
/** Force the Retry affordance even for non-transient causes. Retry is offered automatically for
|
|
17
|
+
* transient/network/5xx errors regardless of this flag; default `false` for all other causes. */
|
|
15
18
|
showRetry?: boolean;
|
|
16
19
|
/** Default `() => query.refetch()`. */
|
|
17
20
|
onRetry?: HandlerProp;
|
|
21
|
+
/** Recovery for authentication errors (401 / expired token): renew the session or sign in again.
|
|
22
|
+
* When provided, a 401 renders this action instead of Retry. */
|
|
23
|
+
onAuthError?: HandlerProp;
|
|
18
24
|
children: (data: NonNullable<T>) => React.ReactNode;
|
|
19
25
|
};
|
|
20
26
|
type MutationLike = Pick<UseMutationResult<unknown, unknown, unknown, unknown>, "isError" | "error" | "isPending">;
|
package/dist/props/registry.d.ts
CHANGED
|
@@ -209,6 +209,11 @@ export declare const VOCABULARY_REGISTRY: {
|
|
|
209
209
|
readonly category: "interaction";
|
|
210
210
|
readonly description: "Badge visual variant (default | secondary | outline | dashed)";
|
|
211
211
|
};
|
|
212
|
+
readonly AppSettingPickerAppearanceProp: {
|
|
213
|
+
readonly file: "vocabulary/interaction.prop.ts";
|
|
214
|
+
readonly category: "interaction";
|
|
215
|
+
readonly description: "AppSettingPicker trigger presentation: labeled (icon + value) | icon (square icon-only topbar trigger)";
|
|
216
|
+
};
|
|
212
217
|
readonly ShapeProp: {
|
|
213
218
|
readonly file: "vocabulary/interaction.prop.ts";
|
|
214
219
|
readonly category: "interaction";
|
|
@@ -289,6 +294,11 @@ export declare const VOCABULARY_REGISTRY: {
|
|
|
289
294
|
readonly category: "interaction";
|
|
290
295
|
readonly description: "Active table sort";
|
|
291
296
|
};
|
|
297
|
+
readonly RevealDelayProp: {
|
|
298
|
+
readonly file: "vocabulary/interaction.prop.ts";
|
|
299
|
+
readonly category: "interaction";
|
|
300
|
+
readonly description: "Reveal entrance-stagger ordinal (0..6) — an index into the motion ladder, never a raw ms";
|
|
301
|
+
};
|
|
292
302
|
readonly BreadcrumbItemProp: {
|
|
293
303
|
readonly file: "vocabulary/navigation.prop.ts";
|
|
294
304
|
readonly category: "navigation";
|
|
@@ -380,7 +390,7 @@ export declare const COMPONENT_PROP_REGISTRY: {
|
|
|
380
390
|
readonly AppSettingPickerProp: {
|
|
381
391
|
readonly group: "app";
|
|
382
392
|
readonly file: "components/app.prop.ts";
|
|
383
|
-
readonly vocabulary: readonly ["ValueProp", "OnValueChangeProp", "DisabledProp", "IdProp", "ClassNameProp"];
|
|
393
|
+
readonly vocabulary: readonly ["ValueProp", "OnValueChangeProp", "DisabledProp", "IdProp", "ClassNameProp", "AppSettingPickerAppearanceProp"];
|
|
384
394
|
};
|
|
385
395
|
readonly PageContainerProp: {
|
|
386
396
|
readonly group: "layout";
|
|
@@ -438,6 +448,11 @@ export declare const COMPONENT_PROP_REGISTRY: {
|
|
|
438
448
|
readonly file: "components/layout.prop.ts";
|
|
439
449
|
readonly vocabulary: readonly ["ChildrenProp"];
|
|
440
450
|
};
|
|
451
|
+
readonly AuthShellProp: {
|
|
452
|
+
readonly group: "layout";
|
|
453
|
+
readonly file: "components/layout.prop.ts";
|
|
454
|
+
readonly vocabulary: readonly ["ChildrenProp", "ClassNameProp"];
|
|
455
|
+
};
|
|
441
456
|
readonly SidebarProductProp: {
|
|
442
457
|
readonly group: "layout";
|
|
443
458
|
readonly file: "components/layout.prop.ts";
|
|
@@ -468,6 +483,15 @@ export declare const COMPONENT_PROP_REGISTRY: {
|
|
|
468
483
|
readonly file: "components/general.prop.ts";
|
|
469
484
|
readonly vocabulary: readonly ["ButtonVariantProp", "SizeProp", "ShapeProp", "AsChildProp", "DisabledProp", "OnClickProp", "PendingProp"];
|
|
470
485
|
};
|
|
486
|
+
readonly RevealProp: {
|
|
487
|
+
readonly group: "general";
|
|
488
|
+
readonly file: "components/general.prop.ts";
|
|
489
|
+
readonly vocabulary: readonly ["ChildrenProp", "RevealDelayProp", "AsChildProp", "ClassNameProp", {
|
|
490
|
+
readonly field: "delay";
|
|
491
|
+
readonly local: true;
|
|
492
|
+
readonly reason: "Reveal stagger ordinal — RevealDelayProp vocabulary.";
|
|
493
|
+
}];
|
|
494
|
+
};
|
|
471
495
|
readonly TextProp: {
|
|
472
496
|
readonly group: "general";
|
|
473
497
|
readonly file: "components/general.prop.ts";
|
|
@@ -663,7 +687,12 @@ export declare const COMPONENT_PROP_REGISTRY: {
|
|
|
663
687
|
readonly EmptyStateProp: {
|
|
664
688
|
readonly group: "data-display";
|
|
665
689
|
readonly file: "components/data-display.prop.ts";
|
|
666
|
-
readonly vocabulary: readonly ["IconProp", "TitleProp", "DescriptionProp", "ActionProp"];
|
|
690
|
+
readonly vocabulary: readonly ["IconProp", "TitleProp", "DescriptionProp", "ActionProp", "ToneProp"];
|
|
691
|
+
};
|
|
692
|
+
readonly EmptyStateToneProp: {
|
|
693
|
+
readonly group: "data-display";
|
|
694
|
+
readonly file: "components/data-display.prop.ts";
|
|
695
|
+
readonly vocabulary: readonly [];
|
|
667
696
|
};
|
|
668
697
|
readonly DescriptionsProp: {
|
|
669
698
|
readonly group: "data-display";
|
package/dist/props/registry.js
CHANGED
|
@@ -208,6 +208,11 @@ const VOCABULARY_REGISTRY = {
|
|
|
208
208
|
category: "interaction",
|
|
209
209
|
description: "Badge visual variant (default | secondary | outline | dashed)"
|
|
210
210
|
},
|
|
211
|
+
AppSettingPickerAppearanceProp: {
|
|
212
|
+
file: "vocabulary/interaction.prop.ts",
|
|
213
|
+
category: "interaction",
|
|
214
|
+
description: "AppSettingPicker trigger presentation: labeled (icon + value) | icon (square icon-only topbar trigger)"
|
|
215
|
+
},
|
|
211
216
|
ShapeProp: {
|
|
212
217
|
file: "vocabulary/interaction.prop.ts",
|
|
213
218
|
category: "interaction",
|
|
@@ -288,6 +293,11 @@ const VOCABULARY_REGISTRY = {
|
|
|
288
293
|
category: "interaction",
|
|
289
294
|
description: "Active table sort"
|
|
290
295
|
},
|
|
296
|
+
RevealDelayProp: {
|
|
297
|
+
file: "vocabulary/interaction.prop.ts",
|
|
298
|
+
category: "interaction",
|
|
299
|
+
description: "Reveal entrance-stagger ordinal (0..6) \u2014 an index into the motion ladder, never a raw ms"
|
|
300
|
+
},
|
|
291
301
|
// navigation.prop.ts
|
|
292
302
|
BreadcrumbItemProp: {
|
|
293
303
|
file: "vocabulary/navigation.prop.ts",
|
|
@@ -376,7 +386,14 @@ const COMPONENT_PROP_REGISTRY = {
|
|
|
376
386
|
AppSettingPickerProp: {
|
|
377
387
|
group: "app",
|
|
378
388
|
file: "components/app.prop.ts",
|
|
379
|
-
vocabulary: [
|
|
389
|
+
vocabulary: [
|
|
390
|
+
"ValueProp",
|
|
391
|
+
"OnValueChangeProp",
|
|
392
|
+
"DisabledProp",
|
|
393
|
+
"IdProp",
|
|
394
|
+
"ClassNameProp",
|
|
395
|
+
"AppSettingPickerAppearanceProp"
|
|
396
|
+
]
|
|
380
397
|
},
|
|
381
398
|
PageContainerProp: {
|
|
382
399
|
group: "layout",
|
|
@@ -416,6 +433,11 @@ const COMPONENT_PROP_REGISTRY = {
|
|
|
416
433
|
file: "components/layout.prop.ts",
|
|
417
434
|
vocabulary: ["ChildrenProp"]
|
|
418
435
|
},
|
|
436
|
+
AuthShellProp: {
|
|
437
|
+
group: "layout",
|
|
438
|
+
file: "components/layout.prop.ts",
|
|
439
|
+
vocabulary: ["ChildrenProp", "ClassNameProp"]
|
|
440
|
+
},
|
|
419
441
|
SidebarProductProp: {
|
|
420
442
|
group: "layout",
|
|
421
443
|
file: "components/layout.prop.ts",
|
|
@@ -454,6 +476,21 @@ const COMPONENT_PROP_REGISTRY = {
|
|
|
454
476
|
"PendingProp"
|
|
455
477
|
]
|
|
456
478
|
},
|
|
479
|
+
RevealProp: {
|
|
480
|
+
group: "general",
|
|
481
|
+
file: "components/general.prop.ts",
|
|
482
|
+
vocabulary: [
|
|
483
|
+
"ChildrenProp",
|
|
484
|
+
"RevealDelayProp",
|
|
485
|
+
"AsChildProp",
|
|
486
|
+
"ClassNameProp",
|
|
487
|
+
{
|
|
488
|
+
field: "delay",
|
|
489
|
+
local: true,
|
|
490
|
+
reason: "Reveal stagger ordinal \u2014 RevealDelayProp vocabulary."
|
|
491
|
+
}
|
|
492
|
+
]
|
|
493
|
+
},
|
|
457
494
|
TextProp: {
|
|
458
495
|
group: "general",
|
|
459
496
|
file: "components/general.prop.ts",
|
|
@@ -705,7 +742,12 @@ const COMPONENT_PROP_REGISTRY = {
|
|
|
705
742
|
EmptyStateProp: {
|
|
706
743
|
group: "data-display",
|
|
707
744
|
file: "components/data-display.prop.ts",
|
|
708
|
-
vocabulary: ["IconProp", "TitleProp", "DescriptionProp", "ActionProp"]
|
|
745
|
+
vocabulary: ["IconProp", "TitleProp", "DescriptionProp", "ActionProp", "ToneProp"]
|
|
746
|
+
},
|
|
747
|
+
EmptyStateToneProp: {
|
|
748
|
+
group: "data-display",
|
|
749
|
+
file: "components/data-display.prop.ts",
|
|
750
|
+
vocabulary: []
|
|
709
751
|
},
|
|
710
752
|
DescriptionsProp: {
|
|
711
753
|
group: "data-display",
|
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
export type { ClassNameProp, ChildrenProp, IdProp, OpenProp, DefaultOpenProp, OnOpenChangeProp, HandlerProp, PendingProp, RequiredProp, DisabledProp, LabelProp, HelperProp, ErrorProp, PlaceholderProp, NameProp, ValueProp, DefaultValueProp, OnValueChangeProp, OnChangeProp, OnClickProp, AsChildProp, WidthProp, } from "./shared.prop.js";
|
|
3
3
|
export type { TitleProp, SubtitleProp, DescriptionProp, ExtraProp, FooterProp, ActionProp, IconProp, ConfirmLabelProp, CancelLabelProp, ActionsProp, EmptyMessageProp, } from "./content.prop.js";
|
|
4
4
|
export type { PageDensityProp, PageContainerVariantProp, TableDensityProp, DensityProp, GapProp, } from "./layout.prop.js";
|
|
5
|
-
export type { ButtonVariantProp, ButtonSizeProp, BadgeVariantProp, ShapeProp, TextSizeProp, TextToneProp, FontWeightProp, HeadingLevelProp, TextAlignProp, SizeProp, FormLayoutProp, BreakpointProp, ConfirmVariantProp, ToneProp, AlertVariantProp, SortDirectionProp, ColumnAlignProp, SortStateProp, } from "./interaction.prop.js";
|
|
5
|
+
export type { ButtonVariantProp, ButtonSizeProp, BadgeVariantProp, AppSettingPickerAppearanceProp, ShapeProp, TextSizeProp, TextToneProp, FontWeightProp, HeadingLevelProp, TextAlignProp, SizeProp, FormLayoutProp, BreakpointProp, ConfirmVariantProp, ToneProp, AlertVariantProp, SortDirectionProp, ColumnAlignProp, SortStateProp, RevealDelayProp, } from "./interaction.prop.js";
|
|
6
6
|
export type { BreadcrumbItemProp, BreadcrumbProp } from "./navigation.prop.js";
|
|
7
7
|
export type { GetRowIdProp, OnRowClickProp, ColumnDefProp, SelectedIdsProp, OnSelectChangeProp, OnTableDensityChangeProp, OnSortChangeProp, OnSearchChangeProp, OnClearFiltersProp, HasActiveFiltersProp, } from "./data.prop.js";
|
|
@@ -11,7 +11,7 @@ export type ShapeProp = "default" | "pill" | "sharp";
|
|
|
11
11
|
export type TextSizeProp = "2xs" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl";
|
|
12
12
|
/** Text colour intent — maps to semantic foreground tokens (no raw palette). */
|
|
13
13
|
export type TextToneProp = "default" | "muted" | "primary" | "success" | "warning" | "destructive" | "info";
|
|
14
|
-
/** Font weight — the
|
|
14
|
+
/** Font weight — the reference-design canon is THREE weights only: `regular` (400 body), `medium` (500
|
|
15
15
|
* heading/label), `bold` (700 emphasis). 600/`semibold` is forbidden. */
|
|
16
16
|
export type FontWeightProp = "regular" | "medium" | "bold";
|
|
17
17
|
/** Heading level — drives both the `--heading-h*` size token and the semantic `<h1..h4>` element. */
|
|
@@ -20,6 +20,16 @@ export type HeadingLevelProp = 1 | 2 | 3 | 4;
|
|
|
20
20
|
export type TextAlignProp = "start" | "center" | "end";
|
|
21
21
|
/** Badge visual style. */
|
|
22
22
|
export type BadgeVariantProp = "default" | "secondary" | "outline" | "dashed";
|
|
23
|
+
/**
|
|
24
|
+
* AppSettingPicker trigger presentation.
|
|
25
|
+
* - `labeled` (default) — the leading icon + the selected value inside a full-width control
|
|
26
|
+
* (settings forms, preference panels).
|
|
27
|
+
* - `icon` — a square, icon-only utility trigger (e.g. a topbar globe locale switcher). It
|
|
28
|
+
* STRUCTURALLY drops the value text and the picker's owned trigger width, keeping the localized
|
|
29
|
+
* `aria-label`, focus ring, keyboard behaviour and a `--control-height` tap target (which is
|
|
30
|
+
* ≥44px on coarse/touch pointers per Rule #24) — so consumers never hide internal nodes via CSS.
|
|
31
|
+
*/
|
|
32
|
+
export type AppSettingPickerAppearanceProp = "labeled" | "icon";
|
|
23
33
|
/** Button size preset. */
|
|
24
34
|
export type SizeProp = "xs" | "sm" | "md" | "lg";
|
|
25
35
|
/** Button size preset; icon-only sizes are a documented Button subset. */
|
|
@@ -46,3 +56,9 @@ export type SortStateProp = {
|
|
|
46
56
|
key: string;
|
|
47
57
|
direction: SortDirectionProp;
|
|
48
58
|
};
|
|
59
|
+
/**
|
|
60
|
+
* Entrance-stagger ordinal for `Reveal` — an INDEX into the motion ladder, never a raw ms.
|
|
61
|
+
* `0` = enter immediately; `1..6` each add one `--reveal-stagger-step` of delay so a column of
|
|
62
|
+
* revealed rows cascades in. Reduced-motion collapses every step to 0 (content stays visible).
|
|
63
|
+
*/
|
|
64
|
+
export type RevealDelayProp = 0 | 1 | 2 | 3 | 4 | 5 | 6;
|
|
@@ -107,8 +107,7 @@
|
|
|
107
107
|
grid-column: 1;
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
-
[data-slot="alert-body"]:has(> [data-slot="alert-actions"])
|
|
111
|
-
> [data-slot="alert-actions"] {
|
|
110
|
+
[data-slot="alert-body"]:has(> [data-slot="alert-actions"]) > [data-slot="alert-actions"] {
|
|
112
111
|
grid-column: 2;
|
|
113
112
|
grid-row: 1;
|
|
114
113
|
}
|
package/dist/styles/base.css
CHANGED
|
@@ -218,7 +218,7 @@
|
|
|
218
218
|
|
|
219
219
|
/* Semantic heading scale — SEO + accessibility: real <h1>–<h6> elements carry
|
|
220
220
|
* the document outline (one <h1> per page, levels never skipped). Visual size
|
|
221
|
-
* follows the
|
|
221
|
+
* follows the reference-design scale; component titles override via their own class.
|
|
222
222
|
* Headings read --font-family-display (defaults to --font-family-sans → unchanged) for dual-font
|
|
223
223
|
* brands (display face on headings, body face on prose). */
|
|
224
224
|
:where(h1, h2, h3, h4, h5, h6) {
|
|
@@ -34,8 +34,7 @@
|
|
|
34
34
|
* --card-background defaults to the LIVE --card role at the call site (re-resolves under a
|
|
35
35
|
* scoped theme); a service overrides --card-background to win. */
|
|
36
36
|
background:
|
|
37
|
-
linear-gradient(var(--card-tint), var(--card-tint)),
|
|
38
|
-
hsl(var(--card-background, var(--card)));
|
|
37
|
+
linear-gradient(var(--card-tint), var(--card-tint)), hsl(var(--card-background, var(--card)));
|
|
39
38
|
color: hsl(var(--card-foreground));
|
|
40
39
|
/* Resting elevation + opt-in brand glow — both quiet no-ops by default so a service theme can
|
|
41
40
|
* lift (--card-shadow) and/or glow (--card-glow) every card with no markup change. */
|
|
@@ -100,9 +99,7 @@
|
|
|
100
99
|
[data-slot="card"][data-accent] > [data-slot="card-header"],
|
|
101
100
|
[data-slot="card"][data-accent] > [data-slot="card-content"]:not([data-flush]),
|
|
102
101
|
[data-slot="card"][data-accent] > [data-slot="card-footer"]:not([data-flush]) {
|
|
103
|
-
padding-inline-start: calc(
|
|
104
|
-
var(--card-space-inset) - var(--card-accent-rail-width)
|
|
105
|
-
);
|
|
102
|
+
padding-inline-start: calc(var(--card-space-inset) - var(--card-accent-rail-width));
|
|
106
103
|
}
|
|
107
104
|
|
|
108
105
|
/* ── Header ──────────────────────────────────────────────────────────── */
|
|
@@ -156,7 +153,10 @@
|
|
|
156
153
|
}
|
|
157
154
|
|
|
158
155
|
.ui-card-header--banded {
|
|
159
|
-
border-bottom: var(
|
|
156
|
+
border-bottom: var(
|
|
157
|
+
--card-header-border-bottom,
|
|
158
|
+
1px solid hsl(var(--card-border, var(--border)))
|
|
159
|
+
);
|
|
160
160
|
background-color: hsl(
|
|
161
161
|
var(--card-header-background, var(--muted)) / var(--card-header-background-alpha)
|
|
162
162
|
);
|
package/dist/styles/index.css
CHANGED
package/dist/styles/layout.css
CHANGED
|
@@ -46,6 +46,15 @@
|
|
|
46
46
|
flex-direction: column;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
+
.ui-empty-state[data-variant="section"] {
|
|
50
|
+
padding: var(--empty-state-section-space-y) var(--empty-state-section-space-x);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.ui-empty-state[data-variant="compact"] {
|
|
54
|
+
padding: var(--empty-state-compact-space-y) var(--empty-state-compact-space-x);
|
|
55
|
+
gap: var(--space-stack-xs);
|
|
56
|
+
}
|
|
57
|
+
|
|
49
58
|
.ui-flex[data-wrap="true"] {
|
|
50
59
|
flex-wrap: wrap;
|
|
51
60
|
}
|
|
@@ -512,6 +521,25 @@
|
|
|
512
521
|
background-color: var(--empty-state-icon-tint, hsl(var(--muted)));
|
|
513
522
|
color: var(--empty-state-icon-foreground, hsl(var(--muted-foreground)));
|
|
514
523
|
}
|
|
524
|
+
|
|
525
|
+
/* tone — set the medallion foreground + tint from the matching role token, so a consumer never
|
|
526
|
+
* hand-rolls a `.ui-success-state` class. `muted` (default) keeps the neutral role fallback. */
|
|
527
|
+
.ui-empty-state[data-tone="success"] {
|
|
528
|
+
--empty-state-icon-foreground: hsl(var(--success));
|
|
529
|
+
--empty-state-icon-tint: hsl(var(--success) / 0.12);
|
|
530
|
+
}
|
|
531
|
+
.ui-empty-state[data-tone="warning"] {
|
|
532
|
+
--empty-state-icon-foreground: hsl(var(--warning));
|
|
533
|
+
--empty-state-icon-tint: hsl(var(--warning) / 0.12);
|
|
534
|
+
}
|
|
535
|
+
.ui-empty-state[data-tone="destructive"] {
|
|
536
|
+
--empty-state-icon-foreground: hsl(var(--destructive));
|
|
537
|
+
--empty-state-icon-tint: hsl(var(--destructive) / 0.12);
|
|
538
|
+
}
|
|
539
|
+
.ui-empty-state[data-tone="info"] {
|
|
540
|
+
--empty-state-icon-foreground: hsl(var(--info));
|
|
541
|
+
--empty-state-icon-tint: hsl(var(--info) / 0.12);
|
|
542
|
+
}
|
|
515
543
|
}
|
|
516
544
|
|
|
517
545
|
@layer components {
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* MOTION — entrance/reveal animation for the `Reveal` primitive.
|
|
3
|
+
* Reads the DS motion tokens (--duration-slow / --ease-emphasized / --reveal-distance) instead of
|
|
4
|
+
* a hand-rolled @keyframes, and staggers via the --reveal-stagger-step ladder. Under
|
|
5
|
+
* prefers-reduced-motion the animation is dropped: content renders in its final, fully-visible
|
|
6
|
+
* position with no transform and no layout shift.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
@layer components {
|
|
10
|
+
.ui-reveal {
|
|
11
|
+
animation: ui-reveal-in var(--duration-slow) var(--ease-emphasized) both;
|
|
12
|
+
will-change: transform, opacity;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.ui-reveal[data-reveal-delay="1"] {
|
|
16
|
+
animation-delay: calc(var(--reveal-stagger-step) * 1);
|
|
17
|
+
}
|
|
18
|
+
.ui-reveal[data-reveal-delay="2"] {
|
|
19
|
+
animation-delay: calc(var(--reveal-stagger-step) * 2);
|
|
20
|
+
}
|
|
21
|
+
.ui-reveal[data-reveal-delay="3"] {
|
|
22
|
+
animation-delay: calc(var(--reveal-stagger-step) * 3);
|
|
23
|
+
}
|
|
24
|
+
.ui-reveal[data-reveal-delay="4"] {
|
|
25
|
+
animation-delay: calc(var(--reveal-stagger-step) * 4);
|
|
26
|
+
}
|
|
27
|
+
.ui-reveal[data-reveal-delay="5"] {
|
|
28
|
+
animation-delay: calc(var(--reveal-stagger-step) * 5);
|
|
29
|
+
}
|
|
30
|
+
.ui-reveal[data-reveal-delay="6"] {
|
|
31
|
+
animation-delay: calc(var(--reveal-stagger-step) * 6);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
@keyframes ui-reveal-in {
|
|
35
|
+
from {
|
|
36
|
+
opacity: 0;
|
|
37
|
+
transform: translateY(var(--reveal-distance));
|
|
38
|
+
}
|
|
39
|
+
to {
|
|
40
|
+
opacity: 1;
|
|
41
|
+
transform: none;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/* Accessibility: no motion → no animation, content stays visible (WCAG 2.3.3 / 2.2.2). */
|
|
46
|
+
@media (prefers-reduced-motion: reduce) {
|
|
47
|
+
.ui-reveal,
|
|
48
|
+
.ui-reveal[data-reveal-delay] {
|
|
49
|
+
animation: none;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -81,6 +81,48 @@
|
|
|
81
81
|
max-width: none;
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
+
/*
|
|
85
|
+
* AUTH SHELL — centred auth/login page shell (brand bar + centred card + footer).
|
|
86
|
+
* Comfortable control density + a larger auth heading are scoped to the shell so login/mfa/reset
|
|
87
|
+
* forms read at the right size without a consumer scope class. Everything reads a token knob.
|
|
88
|
+
*/
|
|
89
|
+
.ui-auth-shell {
|
|
90
|
+
--control-height: var(--auth-shell-control-height);
|
|
91
|
+
--heading-h1: var(--auth-shell-heading-size);
|
|
92
|
+
display: flex;
|
|
93
|
+
min-height: 100dvh;
|
|
94
|
+
flex-direction: column;
|
|
95
|
+
background:
|
|
96
|
+
linear-gradient(180deg, hsl(var(--primary) / 0.035), transparent 14rem),
|
|
97
|
+
hsl(var(--background));
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.ui-auth-shell-bar {
|
|
101
|
+
display: flex;
|
|
102
|
+
align-items: center;
|
|
103
|
+
padding: var(--auth-shell-bar-padding);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.ui-auth-shell-main {
|
|
107
|
+
display: flex;
|
|
108
|
+
flex: 1 1 auto;
|
|
109
|
+
flex-direction: column;
|
|
110
|
+
align-items: center;
|
|
111
|
+
justify-content: center;
|
|
112
|
+
padding: var(--auth-shell-main-padding);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.ui-auth-shell-card {
|
|
116
|
+
width: 100%;
|
|
117
|
+
max-width: var(--auth-shell-card-max-width);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.ui-auth-shell-footer {
|
|
121
|
+
padding: var(--auth-shell-footer-padding);
|
|
122
|
+
text-align: center;
|
|
123
|
+
color: hsl(var(--muted-foreground));
|
|
124
|
+
}
|
|
125
|
+
|
|
84
126
|
.app-topbar-rail {
|
|
85
127
|
display: flex;
|
|
86
128
|
min-width: 0;
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
font-size: var(--font-size-2xl);
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
/* Weight — the
|
|
36
|
+
/* Weight — the reference-design canon (400 body · 500 heading/label · 700 emphasis). No 600.
|
|
37
37
|
* Shared by text + heading; the two-attribute heading selectors outrank the base heading
|
|
38
38
|
* rule below, so `<Heading weight="bold">` renders a semantic, emphasised title. */
|
|
39
39
|
[data-slot="text"][data-weight="regular"],
|
|
@@ -11,33 +11,34 @@
|
|
|
11
11
|
/* ── Light (default) ── */
|
|
12
12
|
:root {
|
|
13
13
|
/* Brand primary ramp — electric blue */
|
|
14
|
-
--primary:
|
|
14
|
+
--primary: 221 83% 53%; /* #2563EB */
|
|
15
15
|
--primary-foreground: 0 0% 100%;
|
|
16
|
-
--primary-hover:
|
|
17
|
-
--primary-active:
|
|
18
|
-
--ring:
|
|
16
|
+
--primary-hover: 224 71% 48%; /* #1D4ED8 */
|
|
17
|
+
--primary-active: 226 71% 40%; /* #1E40AF */
|
|
18
|
+
--ring: 221 83% 53%;
|
|
19
19
|
|
|
20
20
|
/* Brand-colored text (AA on tint/white) */
|
|
21
|
-
--text-link:
|
|
22
|
-
--text-brand:
|
|
21
|
+
--text-link: 224 76% 45%;
|
|
22
|
+
--text-brand: 221 83% 53%;
|
|
23
23
|
--text-primary: 224 76% 42%;
|
|
24
24
|
|
|
25
25
|
/* Signature brand gradient: blue → violet */
|
|
26
26
|
--gradient-brand: linear-gradient(135deg, hsl(221 83% 53%), hsl(262 83% 58%));
|
|
27
27
|
|
|
28
28
|
/* Typography — Inter (Latin/VI) + Noto Sans JP (kana/kanji) */
|
|
29
|
-
--font-family-sans:
|
|
30
|
-
"
|
|
29
|
+
--font-family-sans:
|
|
30
|
+
"Inter", "Noto Sans JP", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
|
31
|
+
"Helvetica Neue", Arial, sans-serif;
|
|
31
32
|
}
|
|
32
33
|
|
|
33
34
|
/* ── Dark ── lifted blue for contrast */
|
|
34
35
|
.dark {
|
|
35
|
-
--primary:
|
|
36
|
+
--primary: 221 90% 66%;
|
|
36
37
|
--primary-foreground: 222 47% 11%;
|
|
37
|
-
--primary-hover:
|
|
38
|
+
--primary-hover: 221 90% 72%;
|
|
38
39
|
--primary-active: 221 90% 60%;
|
|
39
|
-
--ring:
|
|
40
|
-
--text-link:
|
|
41
|
-
--text-brand:
|
|
42
|
-
--text-primary:
|
|
40
|
+
--ring: 221 90% 66%;
|
|
41
|
+
--text-link: 221 90% 72%;
|
|
42
|
+
--text-brand: 221 90% 70%;
|
|
43
|
+
--text-primary: 221 90% 68%;
|
|
43
44
|
}
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
--card-header-border-bottom: initial;
|
|
44
44
|
--card-radius: var(--radius);
|
|
45
45
|
/* Resting elevation — quiet by default (rule #44): cards are flat (1px border, no shadow) in the
|
|
46
|
-
*
|
|
46
|
+
* reference-design baseline. A service that wants lifted cards sets this to an elevation token once,
|
|
47
47
|
* e.g. --card-shadow: var(--shadow-sm), and every Card picks up the shadow with no markup change. */
|
|
48
48
|
--card-shadow: 0 0 0 0 transparent;
|
|
49
49
|
/* Brand glow layer — invisible no-op at rest (rule #44). Paired AFTER --card-shadow in the
|
|
@@ -22,6 +22,10 @@
|
|
|
22
22
|
--dialog-content-glow: 0 0 0 0 transparent;
|
|
23
23
|
--empty-state-space-y: var(--space-10);
|
|
24
24
|
--empty-state-space-x: var(--space-6);
|
|
25
|
+
--empty-state-section-space-y: var(--space-6);
|
|
26
|
+
--empty-state-section-space-x: var(--space-4);
|
|
27
|
+
--empty-state-compact-space-y: var(--space-3);
|
|
28
|
+
--empty-state-compact-space-x: var(--space-2);
|
|
25
29
|
/* EmptyState icon medallion colour — `initial` so the role defaults re-resolve at the call site
|
|
26
30
|
* under a scoped theme (rule #44). A service recolours the glyph (--empty-state-icon-foreground)
|
|
27
31
|
* or washes the medallion fill (--empty-state-icon-tint) without forking.
|
|
@@ -32,4 +32,14 @@
|
|
|
32
32
|
* Defaults = hsl(var(--accent)) fill · hsl(var(--foreground)) text. */
|
|
33
33
|
--sidebar-item-active-background: initial;
|
|
34
34
|
--sidebar-item-active-foreground: initial;
|
|
35
|
+
|
|
36
|
+
/* AuthShell — centred auth/login page shell. Comfortable control density (44px, WCAG touch floor)
|
|
37
|
+
* + a larger auth heading, scoped to the shell; a service re-tunes the auth card width, insets
|
|
38
|
+
* and heading size without forking. */
|
|
39
|
+
--auth-shell-control-height: var(--control-height-comfortable);
|
|
40
|
+
--auth-shell-heading-size: var(--font-size-2xl);
|
|
41
|
+
--auth-shell-card-max-width: 24rem;
|
|
42
|
+
--auth-shell-bar-padding: var(--space-5) var(--space-6);
|
|
43
|
+
--auth-shell-main-padding: var(--space-6);
|
|
44
|
+
--auth-shell-footer-padding: var(--space-3) var(--space-6) var(--space-4);
|
|
35
45
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/* Foundation tokens: color, typography, raw spacing, ratio, radius, shadow. */
|
|
2
2
|
|
|
3
3
|
:root {
|
|
4
|
-
/* Color system (HSL components) —
|
|
4
|
+
/* Color system (HSL components) — the reference design: warm hue-60 neutral spine,
|
|
5
5
|
* SmartHR blue primary, 和色/wa-iro semantics. */
|
|
6
6
|
--background: 60 33% 99%; /* #fdfdfb warm off-white */
|
|
7
7
|
--foreground: 48 8% 13%; /* #23221e SmartHR TEXT_BLACK */
|
|
@@ -83,7 +83,8 @@
|
|
|
83
83
|
--disabled-opacity: 0.5;
|
|
84
84
|
|
|
85
85
|
/* Shape and elevation */
|
|
86
|
-
|
|
86
|
+
/* 6px base × scaling; override to retheme every radius step */
|
|
87
|
+
--radius: calc(0.375rem * var(--scaling));
|
|
87
88
|
--radius-ratio: 1.618; /* φ — radii scale by the golden ratio (steps derive in @theme) */
|
|
88
89
|
--radius-pill: 9999px; /* fully-round: switch / radio / slider / pill badges (NOT --radius-derived) */
|
|
89
90
|
--radius-sharp: 0; /* squared corners: table cells, flush inputs */
|
|
@@ -202,7 +203,9 @@
|
|
|
202
203
|
--font-size-3xl: calc(
|
|
203
204
|
var(--font-size-display) / var(--font-size-display-ratio) / var(--font-size-display-ratio)
|
|
204
205
|
); /* ≈ 33 → 28px feature heading */
|
|
205
|
-
--font-size-4xl: calc(
|
|
206
|
+
--font-size-4xl: calc(
|
|
207
|
+
var(--font-size-display) / var(--font-size-display-ratio)
|
|
208
|
+
); /* ≈ 36px section */
|
|
206
209
|
--font-size-5xl: var(--font-size-display); /* 54px hero */
|
|
207
210
|
|
|
208
211
|
/* Headings — also golden-derived. h1=ratio³, h2=ratio²; h3/h4 reuse body sizes (single source). */
|
|
@@ -217,7 +220,7 @@
|
|
|
217
220
|
|
|
218
221
|
--font-weight-normal: 400;
|
|
219
222
|
--font-weight-medium: 500;
|
|
220
|
-
/*
|
|
223
|
+
/* the reference design uses three weights only: 400 body · 500 heading/label · 700 emphasis. 600 is
|
|
221
224
|
* forbidden (ambiguous between 500 and 700) — the legacy "semibold" token collapses to medium
|
|
222
225
|
* so any remaining reference renders at 500. `bold` is the 700 emphasis weight. */
|
|
223
226
|
--font-weight-semibold: 500;
|
|
@@ -322,7 +325,7 @@
|
|
|
322
325
|
|
|
323
326
|
/* Motion — the primitive tier for animation, so enter/transition timing reads a token
|
|
324
327
|
* instead of a literal 0.5s / cubic-bezier(...) / translateY(10px) (cardinal rule #2).
|
|
325
|
-
*
|
|
328
|
+
* the reference design keeps motion LOW: short durations, a calm decelerate curve, a small reveal shift.
|
|
326
329
|
* Consumers honour prefers-reduced-motion at the call site. */
|
|
327
330
|
--duration-fast: 150ms;
|
|
328
331
|
--duration-base: 250ms;
|
|
@@ -332,6 +335,9 @@
|
|
|
332
335
|
--ease-decelerate: cubic-bezier(0, 0, 0, 1);
|
|
333
336
|
--ease-accelerate: cubic-bezier(0.3, 0, 1, 1);
|
|
334
337
|
--reveal-distance: 10px;
|
|
338
|
+
/* One step of the Reveal stagger ladder — `<Reveal delay={n}>` waits n × this before entering,
|
|
339
|
+
* so a column of reveals cascades. Read instead of a literal `.04s`/`.09s` per-item delay. */
|
|
340
|
+
--reveal-stagger-step: 60ms;
|
|
335
341
|
}
|
|
336
342
|
|
|
337
343
|
.dark,
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@godxjp/ui",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "17.0.1",
|
|
4
|
+
"godxUiMcp": "17.0.0",
|
|
4
5
|
"type": "module",
|
|
5
6
|
"packageManager": "pnpm@10.29.1",
|
|
6
7
|
"sideEffects": false,
|
|
@@ -275,8 +276,9 @@
|
|
|
275
276
|
"test:watch": "vitest",
|
|
276
277
|
"test:coverage": "vitest run --coverage",
|
|
277
278
|
"check:example-imports": "node scripts/check-example-imports.mjs",
|
|
278
|
-
"verify": "pnpm typecheck && pnpm lint && pnpm format && pnpm build && pnpm preview:build && pnpm check:example-imports && pnpm check:core-isolation && pnpm check:prop-vocabulary && pnpm check:token-tiers && pnpm check:control-sizing && pnpm check:rtl && pnpm check:typography && pnpm check:mcp-token-sync && pnpm check:mcp-sync && pnpm check:mcp-orphans && pnpm check:audit-sync && pnpm test",
|
|
279
|
-
"verify:release": "pnpm build && pnpm typecheck && pnpm typecheck:docs && pnpm lint && pnpm preview:build && pnpm check:example-imports && pnpm check:core-isolation && pnpm check:use-client && pnpm check:prop-vocabulary && pnpm check:token-tiers && pnpm check:control-sizing && pnpm check:rtl && pnpm check:typography && pnpm check:mcp-token-sync && pnpm check:mcp-sync && pnpm check:mcp-orphans && pnpm check:audit-sync && pnpm check:mcp-prop-sync && pnpm check:contrast && pnpm test",
|
|
279
|
+
"verify": "pnpm typecheck && pnpm lint && pnpm format && pnpm build && pnpm preview:build && pnpm check:example-imports && pnpm check:core-isolation && pnpm check:no-consumer-coupling && pnpm check:prop-vocabulary && pnpm check:token-tiers && pnpm check:control-sizing && pnpm check:rtl && pnpm check:typography && pnpm check:mcp-token-sync && pnpm check:mcp-lockstep && pnpm check:mcp-sync && pnpm check:mcp-orphans && pnpm check:audit-sync && pnpm test",
|
|
280
|
+
"verify:release": "pnpm build && pnpm typecheck && pnpm typecheck:docs && pnpm lint && pnpm preview:build && pnpm check:example-imports && pnpm check:core-isolation && pnpm check:no-consumer-coupling && pnpm check:use-client && pnpm check:prop-vocabulary && pnpm check:token-tiers && pnpm check:control-sizing && pnpm check:rtl && pnpm check:typography && pnpm check:mcp-token-sync && pnpm check:mcp-lockstep && pnpm check:mcp-sync && pnpm check:mcp-orphans && pnpm check:audit-sync && pnpm check:mcp-prop-sync && pnpm check:contrast && pnpm check:visual-audit && pnpm test",
|
|
281
|
+
"check:mcp-lockstep": "node scripts/check-release-lockstep.mjs",
|
|
280
282
|
"check:mcp-sync": "node scripts/check-mcp-sync.mjs",
|
|
281
283
|
"check:mcp-orphans": "node scripts/check-mcp-orphans.mjs",
|
|
282
284
|
"check:mcp-prop-sync": "node scripts/check-mcp-prop-sync.mjs",
|
|
@@ -288,6 +290,7 @@
|
|
|
288
290
|
"gen:component-tokens": "node scripts/gen-component-tokens.mjs",
|
|
289
291
|
"check:mcp-token-sync": "node scripts/gen-component-tokens.mjs --check",
|
|
290
292
|
"check:core-isolation": "node scripts/check-core-isolation.mjs",
|
|
293
|
+
"check:no-consumer-coupling": "node scripts/check-no-consumer-coupling.mjs",
|
|
291
294
|
"release": "node scripts/release.mjs",
|
|
292
295
|
"preview": "node preview/scripts/kill-port.mjs && vite --config preview/vite.config.ts --port 6008 --strictPort",
|
|
293
296
|
"preview:build": "vite build --config preview/vite.config.ts",
|
|
@@ -300,6 +303,7 @@
|
|
|
300
303
|
"check:audit-sync": "node scripts/check-audit-sync.mjs",
|
|
301
304
|
"check:contrast": "node scripts/check-contrast.mjs",
|
|
302
305
|
"visual-audit": "node scripts/visual-audit.mjs",
|
|
306
|
+
"check:visual-audit": "node scripts/visual-audit-smoke.mjs",
|
|
303
307
|
"postinstall": "node scripts/postinstall.mjs",
|
|
304
308
|
"init-agent": "node scripts/init-agent-kit.mjs",
|
|
305
309
|
"check:use-client": "node scripts/check-use-client.mjs"
|
package/scripts/ui-audit.mjs
CHANGED
|
@@ -281,9 +281,9 @@ const RULES = [
|
|
|
281
281
|
{
|
|
282
282
|
id: "no-em-dash-in-copy",
|
|
283
283
|
severity: "warn",
|
|
284
|
-
// Em-dash (U+2014) in JSX text —
|
|
284
|
+
// Em-dash (U+2014) in JSX text — the reference design uses the middot `·` for JP/EN pairs and calm copy.
|
|
285
285
|
test: /[A-Za-z0-9-ヿ一-鿿]\s*—\s*[A-Za-z0-9-ヿ一-鿿]/,
|
|
286
|
-
standard: "@godxjp/ui
|
|
286
|
+
standard: "@godxjp/ui reference-design typography (best-ux) · Unicode punctuation",
|
|
287
287
|
message:
|
|
288
288
|
"No em-dash (—) in product copy. Use a middot `·` for JP/EN label pairs, or restructure into two calm sentences. Keep copy factual and quiet.",
|
|
289
289
|
},
|