@godxjp/ui 18.8.0 → 18.10.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/LICENSE +202 -0
- package/dist/components/data-display/badge.d.ts +7 -0
- package/dist/components/data-display/badge.js +1 -1
- package/dist/components/data-display/card.d.ts +3 -27
- package/dist/components/data-display/card.js +1 -4
- package/dist/components/data-display/data-table.js +2 -2
- package/dist/components/data-display/index.d.ts +2 -0
- package/dist/components/data-display/index.js +2 -0
- package/dist/components/data-display/permission-matrix.d.ts +26 -0
- package/dist/components/data-display/permission-matrix.js +219 -0
- package/dist/components/data-display/table.d.ts +12 -0
- package/dist/components/data-entry/branch-scope-picker.d.ts +43 -0
- package/dist/components/data-entry/branch-scope-picker.js +200 -0
- package/dist/components/data-entry/command-palette.js +8 -1
- package/dist/components/data-entry/index.d.ts +2 -0
- package/dist/components/data-entry/index.js +2 -0
- package/dist/components/data-entry/input-otp.d.ts +1 -1
- package/dist/components/feedback/alert.d.ts +2 -20
- package/dist/components/feedback/alert.js +1 -11
- package/dist/components/feedback/banner.d.ts +21 -0
- package/dist/components/feedback/banner.js +15 -0
- package/dist/components/feedback/index.d.ts +4 -2
- package/dist/components/feedback/index.js +2 -2
- package/dist/components/general/typography.d.ts +1 -0
- package/dist/components/general/typography.js +32 -13
- package/dist/components/layout/auth-shell.d.ts +2 -2
- package/dist/components/layout/index.d.ts +2 -2
- package/dist/components/layout/index.js +2 -2
- package/dist/components/layout/page-container.d.ts +1 -1
- package/dist/components/layout/page-container.js +45 -19
- package/dist/components/layout/service-role-panel.d.ts +25 -0
- package/dist/components/layout/service-role-panel.js +206 -0
- package/dist/components/navigation/filter-bar.d.ts +2 -2
- package/dist/components/navigation/filter-bar.js +113 -34
- package/dist/components/navigation/index.d.ts +1 -1
- package/dist/components/navigation/steps.d.ts +2 -2
- package/dist/components/navigation/steps.js +2 -4
- package/dist/components/ui/avatar.d.ts +1 -1
- package/dist/components/ui/avatar.js +1 -2
- package/dist/components/ui/input-otp.d.ts +3 -15
- package/dist/components/ui/input-otp.js +1 -2
- package/dist/email/tokens.generated.d.ts +2 -2
- package/dist/email/tokens.generated.js +2 -2
- package/dist/i18n/messages/en.json +56 -4
- package/dist/i18n/messages/ja.json +51 -5
- package/dist/i18n/messages/vi.json +50 -4
- package/dist/props/components/data-display.prop.d.ts +66 -16
- package/dist/props/components/data-entry.prop.d.ts +54 -7
- package/dist/props/components/feedback.prop.d.ts +3 -3
- package/dist/props/components/general.prop.d.ts +8 -1
- package/dist/props/components/layout.prop.d.ts +75 -54
- package/dist/props/components/navigation.prop.d.ts +77 -59
- package/dist/props/registry.d.ts +273 -72
- package/dist/props/registry.js +361 -92
- package/dist/props/vocabulary/content.prop.d.ts +5 -0
- package/dist/props/vocabulary/index.d.ts +1 -1
- package/dist/props/vocabulary/interaction.prop.d.ts +4 -7
- package/dist/props/vocabulary/layout.prop.d.ts +2 -2
- package/dist/styles/alert-layout.css +15 -32
- package/dist/styles/badge-layout.css +5 -0
- package/dist/styles/card-layout.css +13 -49
- package/dist/styles/control.css +2 -12
- package/dist/styles/data-display-layout.css +0 -16
- package/dist/styles/layout.css +102 -108
- package/dist/styles/navigation-layout.css +3 -8
- package/dist/styles/shell-layout.css +17 -17
- package/dist/styles/table-layout.css +77 -2
- package/dist/styles/text-layout.css +13 -0
- package/dist/tokens/base.css +1 -0
- package/dist/tokens/components/badge.css +5 -0
- package/dist/tokens/components/banner.css +16 -0
- package/dist/tokens/components/card.css +0 -12
- package/dist/tokens/components/control.css +0 -16
- package/dist/tokens/components/data-display.css +0 -12
- package/dist/tokens/components/email.css +2 -8
- package/dist/tokens/components/feedback.css +0 -20
- package/dist/tokens/components/navigation.css +10 -34
- package/dist/tokens/components/shell.css +24 -36
- package/dist/tokens/components/table.css +41 -1
- package/dist/tokens/semantic/layout.css +5 -12
- package/package.json +15 -2
- package/dist/components/layout/page-header.d.ts +0 -22
- package/dist/components/layout/page-header.js +0 -89
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/* Banner — the full-bleed attention strip (<Banner> = Alert variant="banner").
|
|
2
|
+
* Colour stays with the alert tone rules; these tokens own ONLY the strip geometry,
|
|
3
|
+
* so a service retunes the banner once here instead of forking alert-layout.css
|
|
4
|
+
* (rule #45 — every service-tunable constant gets a knob). */
|
|
5
|
+
|
|
6
|
+
:root {
|
|
7
|
+
/* Square corners — a strip spans its container edge-to-edge, so it carries no radius. */
|
|
8
|
+
--banner-radius: 0;
|
|
9
|
+
/* The strip keeps a single hairline block-end rule (tone-coloured via the alert
|
|
10
|
+
* border rules); inline/block-start edges are open so it reads as part of the frame. */
|
|
11
|
+
--banner-border-width: 1px;
|
|
12
|
+
/* Strip inset. Block is denser than the inline Alert card; inline defaults to the
|
|
13
|
+
* page gutter so banner text aligns with page content under AppShell/PageContainer. */
|
|
14
|
+
--banner-space-inset-block: var(--space-3);
|
|
15
|
+
--banner-space-inset-inline: var(--space-page-active-x, var(--space-6));
|
|
16
|
+
}
|
|
@@ -74,18 +74,6 @@
|
|
|
74
74
|
* The slot padding compensation in card-layout.css subtracts the same token,
|
|
75
75
|
* so content stays aligned on the shell whatever the rail width. */
|
|
76
76
|
--card-accent-rail-width: 6px;
|
|
77
|
-
/* Accent placement `perimeter` (gh#12) — the FULL attention border. Two knobs so a service can
|
|
78
|
-
* tune the edge weight and the outer ring independently; the defaults reproduce the optical
|
|
79
|
-
* weight of `variant="featured"` (1px border + 1px ring) in the card's own semantic accent tone
|
|
80
|
-
* instead of --primary. Structural 1px literals, like the base card hairline. */
|
|
81
|
-
--card-accent-perimeter-width: 1px;
|
|
82
|
-
--card-accent-perimeter-ring-width: 1px;
|
|
83
|
-
/* `variant="featured"` edge — role-mirror knob (docs/TOKENS.md). `initial` so the --primary
|
|
84
|
-
* default resolves at the CALL SITE and a scoped [data-tenant]/.dark override of --primary
|
|
85
|
-
* reaches it; a service points it anywhere (e.g. var(--attention)) to retint every featured card
|
|
86
|
-
* at once. Default = hsl(var(--primary)). */
|
|
87
|
-
--card-featured-border-color: initial;
|
|
88
|
-
--card-featured-ring-width: 1px;
|
|
89
77
|
--stat-card-label-font-size: var(--font-size-xs);
|
|
90
78
|
--stat-card-label-font-weight: var(--font-weight-medium);
|
|
91
79
|
--stat-card-label-letter-spacing: 0.04em;
|
|
@@ -67,22 +67,6 @@
|
|
|
67
67
|
* re-scopes --control-height to 36px, would silently shrink. Verified in Chromium: 36px before
|
|
68
68
|
* and after. A service opts in with a NAMED tier (`var(--control-height-lg)`), never a calc. */
|
|
69
69
|
--otp-slot-size: initial; /* default = var(--control-height) at the call site */
|
|
70
|
-
/* Per-AXIS overrides of the slot box (gh#12). --otp-slot-size stays the square shorthand; these
|
|
71
|
-
* two win over it when set, so a code field can be WIDER-than-tall or TALLER-than-wide without
|
|
72
|
-
* abandoning the token. A canonical device-grant code field is 27.5x52 per slot (a 4-slot
|
|
73
|
-
* `appearance="grouped"` box of 112x54 with its 1px group border) — not expressible with one
|
|
74
|
-
* square knob, which is why grouped OTP measured 146x38 against that artboard. `initial` for the
|
|
75
|
-
* same tier-mirror reason as --otp-slot-size: the whole fallback chain
|
|
76
|
-
* (axis → square → --control-height) must resolve at the CALL SITE so a shell that re-scopes
|
|
77
|
-
* --control-height still reaches an OTP row that sets neither axis. */
|
|
78
|
-
--otp-slot-inline-size: initial; /* default = var(--otp-slot-size, var(--control-height)) */
|
|
79
|
-
--otp-slot-block-size: initial; /* default = var(--otp-slot-size, var(--control-height)) */
|
|
80
|
-
/* Main-axis alignment of the whole OTP row (rule #44/#45 — chrome is a token, default quiet).
|
|
81
|
-
* `flex-start` is the historical behaviour, so an existing field is byte-identical; a centred
|
|
82
|
-
* code field is `align="center"` on InputOTP (which wins over this knob) or this token set once
|
|
83
|
-
* in a service theme. It exists because EVERY consumer was wrapping .ui-otp-container in a
|
|
84
|
-
* flex-centring div to get a centred challenge. */
|
|
85
|
-
--otp-container-align: flex-start;
|
|
86
70
|
|
|
87
71
|
/* Checked/on/active fills — `initial` so the --primary default re-resolves at the call site
|
|
88
72
|
* under a scoped theme (a :root binding to var(--primary) freezes at the :root value and a scoped
|
|
@@ -28,18 +28,6 @@
|
|
|
28
28
|
--avatar-square-background: initial;
|
|
29
29
|
--avatar-square-foreground: initial;
|
|
30
30
|
|
|
31
|
-
/* Capability medallion — `<Avatar appearance="tinted">` (gh#12): the tinted plate a capability /
|
|
32
|
-
feature glyph sits on, as opposed to the SOLID entity mark above. Pair it with shape="square"
|
|
33
|
-
for the canonical rounded square. --avatar-tinted-background / --avatar-tinted-foreground are
|
|
34
|
-
role-mirror knobs (`initial`, docs/TOKENS.md) so the --primary defaults resolve at the CALL
|
|
35
|
-
SITE and a scoped [data-tenant]/.dark override of --primary reaches them — the exact reason
|
|
36
|
-
this is a token and not the `hsl(var(--primary) / 0.1)` literal consumers were writing in page
|
|
37
|
-
CSS. Defaults = hsl(var(--primary) / 0.1) wash · hsl(var(--primary)) glyph ·
|
|
38
|
-
--control-icon-size glyph box. */
|
|
39
|
-
--avatar-tinted-background: initial;
|
|
40
|
-
--avatar-tinted-foreground: initial;
|
|
41
|
-
--avatar-tinted-glyph-size: var(--control-icon-size);
|
|
42
|
-
|
|
43
31
|
/* Progress track + fill — `initial` so the role defaults re-resolve under a scoped theme.
|
|
44
32
|
Track reads --secondary, fill reads --success; a service re-tones once.
|
|
45
33
|
Defaults = hsl(var(--secondary)) track · hsl(var(--success)) fill. */
|
|
@@ -63,14 +63,8 @@
|
|
|
63
63
|
--email-heading-font-weight: 500; /* mirrors --font-weight-medium — an email title is calm, not bold */
|
|
64
64
|
|
|
65
65
|
/* ── Primary CTA — the one action button ────────────────────────────────────────────────── */
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
* pointer, and mail clients do not reliably offer zoom or a focus affordance — so the web's AA
|
|
69
|
-
* floor (SC 2.5.8, 24x24, which 36px clears) is the wrong bar here. 44px is the AAA target size
|
|
70
|
-
* (SC 2.5.5, 44x44) and the Apple HIG 44pt / Material 48dp convention. A service that must keep
|
|
71
|
-
* the old box sets --email-cta-height + --email-cta-line-height in its own theme. */
|
|
72
|
-
--email-cta-height: 44px;
|
|
73
|
-
--email-cta-line-height: 44px; /* equal to the height: bulletproof vertical centring in Outlook */
|
|
66
|
+
--email-cta-height: 36px; /* mirrors --control-height-lg (2.25rem) — the canonical CTA box */
|
|
67
|
+
--email-cta-line-height: 36px; /* equal to the height: bulletproof vertical centring in Outlook */
|
|
74
68
|
--email-cta-padding-x: 16px; /* mirrors --space-4 */
|
|
75
69
|
--email-cta-radius: 6px; /* mirrors the --radius base (0.375rem) */
|
|
76
70
|
--email-cta-font-size: 14px; /* mirrors --font-size-base */
|
|
@@ -29,26 +29,6 @@
|
|
|
29
29
|
* (a brand's success-bg/-border are often more present than the faint 5%/30% default). */
|
|
30
30
|
--alert-bg-alpha: 0.05;
|
|
31
31
|
--alert-border-alpha: 0.3;
|
|
32
|
-
/* BANNER — the page-level Alert treatment (gh#255). Every constant a service would want to
|
|
33
|
-
* match to its page grid is a knob (rule #45): a banner that must keep the app's rounded card
|
|
34
|
-
* language sets --banner-radius, one that rules its top edge too sets --banner-border-width.
|
|
35
|
-
* The inline inset tracks the live page gutter, so a banner mounted above a PageContainer lines
|
|
36
|
-
* its text up with the page title instead of sitting at a second, unrelated margin. */
|
|
37
|
-
--banner-radius: 0;
|
|
38
|
-
--banner-border-width: 0;
|
|
39
|
-
--banner-border-block-end-width: 1px;
|
|
40
|
-
--banner-space-block: var(--space-3);
|
|
41
|
-
/* Inline inset tracks the page gutter so a banner's text lines up with the page title.
|
|
42
|
-
* `--space-page-active-x` steps down to the compact gutter on `.ui-page-container` only, and
|
|
43
|
-
* custom properties inherit — so a banner rendered INSIDE the container picks the compact value
|
|
44
|
-
* up for free, while the normal case (a banner mounted ABOVE the container, or in AppShell) would
|
|
45
|
-
* keep the desktop gutter and sit 8px out at 390px. The compact step below is what actually keeps
|
|
46
|
-
* the two aligned; retune it rather than hard-coding a mobile inset at the call site. */
|
|
47
|
-
--banner-space-inline: var(--space-page-active-x);
|
|
48
|
-
--banner-space-inline-compact: var(--space-page-compact-x);
|
|
49
|
-
/* Dismiss offset is measured from the banner's own (shorter) block inset, so the ✕ stays
|
|
50
|
-
* optically centred on a one-line strip instead of floating at the inline-alert offset. */
|
|
51
|
-
--banner-dismiss-space-offset: var(--space-2);
|
|
52
32
|
/* Brand glow layer for the raised dialog/sheet panel — invisible no-op at rest (rule #44).
|
|
53
33
|
* Paired AFTER --shadow-lg in the surface box-shadow so a service can wash the overlay with the
|
|
54
34
|
* global glow, e.g. --dialog-content-glow: var(--shadow-glow), with no markup change. */
|
|
@@ -14,15 +14,6 @@
|
|
|
14
14
|
--steps-inline-item-gap: var(--space-1);
|
|
15
15
|
--steps-inline-font-size: var(--font-size-xs);
|
|
16
16
|
--steps-inline-separator-size: var(--control-icon-size-sm);
|
|
17
|
-
/* Inline-step emphasis (gh#12). The step number's weight and tint are separate knobs so a
|
|
18
|
-
* service can express progression the canonical way — an accent TINT at normal weight — instead
|
|
19
|
-
* of the original bold. --steps-inline-index-color / --steps-inline-separator-color are
|
|
20
|
-
* role-mirror knobs (docs/TOKENS.md): `initial` so their defaults (the inherited step colour and
|
|
21
|
-
* the --muted-foreground role) resolve at the CALL SITE and a scoped [data-tenant]/.dark
|
|
22
|
-
* override still reaches them. Defaults reproduce today's row byte for byte. */
|
|
23
|
-
--steps-inline-index-font-weight: var(--font-weight-bold);
|
|
24
|
-
--steps-inline-index-color: initial; /* default = currentColor at the call site */
|
|
25
|
-
--steps-inline-separator-color: initial; /* default = hsl(var(--muted-foreground)) */
|
|
26
17
|
|
|
27
18
|
/* AppSettingPicker `compact` (gh#217) — the small, content-hugging labelled trigger used in an
|
|
28
19
|
* auth/legal footer, where the square icon-only default reads as a stray button and the full
|
|
@@ -65,29 +56,14 @@
|
|
|
65
56
|
* (0 on an overlay-scrollbar platform). */
|
|
66
57
|
--filter-bar-scroll-padding-y: var(--space-1);
|
|
67
58
|
|
|
68
|
-
/* FilterBar typed model (#258) —
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
|
|
75
|
-
--filter-bar-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
--filter-bar-chip-gap: var(--space-inline-xs);
|
|
79
|
-
--filter-bar-chip-row-gap: var(--space-inline-xs);
|
|
80
|
-
--filter-bar-chip-padding-inline: var(--space-2);
|
|
81
|
-
--filter-bar-chip-padding-block: var(--space-1);
|
|
82
|
-
--filter-bar-chip-radius: var(--radius-sm);
|
|
83
|
-
--filter-bar-chip-font-size: var(--font-size-xs);
|
|
84
|
-
/* Role-mirror knobs (docs/TOKENS.md) — `initial` at :root so --muted / --muted-foreground
|
|
85
|
-
* re-resolve at the CALL SITE under a scoped [data-tenant]/.dark theme. Binding a role var here
|
|
86
|
-
* would freeze the chip at the :root palette and a tenant override would never reach it. */
|
|
87
|
-
--filter-bar-chip-background: initial;
|
|
88
|
-
--filter-bar-chip-foreground: initial;
|
|
89
|
-
|
|
90
|
-
/* Result-count live region. */
|
|
91
|
-
--filter-bar-count-font-size: var(--font-size-xs);
|
|
92
|
-
--filter-bar-count-foreground: initial;
|
|
59
|
+
/* FilterBar typed model (gh#258) — token-owned geometry so every list page gets the SAME
|
|
60
|
+
* search width, filter width, chip rhythm and section stacking without page-local CSS.
|
|
61
|
+
* All are rule-#45 knobs: a service theme retunes them once, props/className override per
|
|
62
|
+
* instance. Below 640px the strip stacks (search/filters full-width); the widths apply from
|
|
63
|
+
* the 640px breakpoint up, always clamped by min(100%, …) so a narrow container never
|
|
64
|
+
* overflows at 390px with long JA/EN/VI labels. */
|
|
65
|
+
--filter-bar-search-width: 20rem;
|
|
66
|
+
--filter-bar-filter-width: var(--filter-picker-width-md);
|
|
67
|
+
--filter-bar-chip-gap: var(--space-2);
|
|
68
|
+
--filter-bar-section-gap: var(--space-2);
|
|
93
69
|
}
|
|
@@ -81,21 +81,10 @@
|
|
|
81
81
|
--topbar-height: auto;
|
|
82
82
|
--topbar-inset: 0px;
|
|
83
83
|
--topbar-gap: var(--space-2);
|
|
84
|
-
/*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
* global search trigger placed in `center` is INVISIBLE from 1100px down — including on every
|
|
89
|
-
* phone — unless the consumer opts back in. That default arrived in 18.6.0 and removed the slot
|
|
90
|
-
* for consumers who never changed a line of their own code (gh#12); it stays because the
|
|
91
|
-
* overlap it prevents is a real defect and flipping a shipped default twice is worse than
|
|
92
|
-
* documenting it once, but it is a DECISION, not an accident:
|
|
93
|
-
*
|
|
94
|
-
* :root { --topbar-center-compact-display: flex; } ← restore the slot at every width
|
|
95
|
-
*
|
|
96
|
-
* Opt back in only once the center content has a compact presentation of its own (an icon-only
|
|
97
|
-
* search trigger, a collapsing field). A page-local media query is the anti-pattern this knob
|
|
98
|
-
* replaces. */
|
|
84
|
+
/* At compact desktop/tablet widths the docked sidebar leaves too little inline room for three
|
|
85
|
+
* intrinsically-sized clusters. The package hides the optional center slot before it can cover
|
|
86
|
+
* the breadcrumb/title or end utilities. Consumers may opt back into another display strategy
|
|
87
|
+
* (for example `flex`) once their center content has its own compact presentation. */
|
|
99
88
|
--topbar-center-compact-display: none;
|
|
100
89
|
--org-switcher-trigger-height: 2.75rem;
|
|
101
90
|
--org-switcher-trigger-padding-x: var(--space-2);
|
|
@@ -183,27 +172,17 @@
|
|
|
183
172
|
--auth-shell-login-main-padding-block-end: 1rem;
|
|
184
173
|
--auth-shell-login-identity-slot-block-size: 7rem;
|
|
185
174
|
--auth-shell-login-card-stack-gap: 1.25rem;
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
175
|
+
/* Canonical SCR-001 block inset is a FLAT 24px — the same measure as the inline inset. The card
|
|
176
|
+
* draws its own 1px border and a border-box rect already contains it, so the former
|
|
177
|
+
* `+ 2 x --control-border-width` double-counted the border and pushed the passkey CTA to y=390
|
|
178
|
+
* instead of the canonical y=388 (gh#263). */
|
|
179
|
+
--auth-shell-login-card-padding-block-compact: var(--auth-shell-compact-card-inset);
|
|
189
180
|
|
|
190
181
|
/* Device-authorization preset — 380px card measure, 15px block · 5px inline mobile gutter
|
|
191
182
|
* (at a 390px viewport the card is x=5px, width=380px). */
|
|
192
183
|
--auth-shell-device-card-max-width: 23.75rem;
|
|
193
184
|
--auth-shell-device-main-padding: 1rem;
|
|
194
185
|
--auth-shell-device-main-padding-mobile: 0.9375rem 0.3125rem;
|
|
195
|
-
/* CODE FIELD measure — the preset owns it (gh#12). A device grant is the one canonical flow whose
|
|
196
|
-
* PRIMARY control is the code field, so leaving it on the generic square --otp-slot-size made the
|
|
197
|
-
* preset own the page but not its own subject: two 4-slot `appearance="grouped"` boxes rendered
|
|
198
|
-
* 146x38 (4 x the canonical 36px control tier + the 1px group border) against a 112x54 artboard.
|
|
199
|
-
* These are the per-slot boxes that ADD UP to that artboard group:
|
|
200
|
-
* inline 27.5px x 4 + 2 x 1px group border = 112px
|
|
201
|
-
* block 52px + 2 x 1px group border = 54px
|
|
202
|
-
* Literal artboard lengths, like every other preset measure here — they must not drift with
|
|
203
|
-
* --scaling. A service that groups its code differently overrides --otp-slot-inline-size /
|
|
204
|
-
* --otp-slot-block-size on its own field; the generic square knob is untouched everywhere else. */
|
|
205
|
-
--auth-shell-device-otp-slot-inline-size: 1.71875rem;
|
|
206
|
-
--auth-shell-device-otp-slot-block-size: 3.25rem;
|
|
207
186
|
|
|
208
187
|
/* Context-selection preset — 25rem card measure on desktop/tablet, edge-to-edge on mobile
|
|
209
188
|
* (0 inline gutter) with a 16px rhythm between the intro, the card and the remember row. */
|
|
@@ -256,14 +235,19 @@
|
|
|
256
235
|
--auth-shell-registration-main-padding-block-end-mobile: 2rem;
|
|
257
236
|
--auth-shell-registration-card-stack-gap: 1.25rem;
|
|
258
237
|
/* Fixed identity track, the same 112px `login` proved (gh#237). Without it the card anchor moves
|
|
259
|
-
* with the title/requester line count
|
|
260
|
-
*
|
|
261
|
-
*
|
|
238
|
+
* with the title/requester line count, so the canonical y above would hold for exactly one copy
|
|
239
|
+
* length and drift for every other. The slot absorbs absent / one-line / two-line identity
|
|
240
|
+
* content instead. */
|
|
262
241
|
--auth-shell-registration-identity-slot-block-size: 7rem;
|
|
263
242
|
|
|
264
|
-
/* Labelled auth divider geometry.
|
|
243
|
+
/* Labelled auth divider geometry. The canonical SCR-001 divider row is 19px tall at the 11px
|
|
244
|
+
* label (the artboard label inherits the page's line-height instead of collapsing to a 1.0 line
|
|
245
|
+
* box). 19/11 pins the row at exactly 19px and keeps it proportional if a service retunes the
|
|
246
|
+
* label font-size. The previous hardcoded `line-height: 1` rendered an 11px row, sitting the
|
|
247
|
+
* whole lower half of the Login card 8px high (gh#263). */
|
|
265
248
|
--auth-shell-divider-gap: 0.625rem;
|
|
266
249
|
--auth-shell-divider-label-font-size: 0.6875rem;
|
|
250
|
+
--auth-shell-divider-label-line-height: calc(19 / 11);
|
|
267
251
|
--auth-shell-divider-rule-color: var(--border);
|
|
268
252
|
--auth-shell-divider-label-color: var(--muted-foreground);
|
|
269
253
|
--auth-identity-gap: 0.375rem;
|
|
@@ -281,8 +265,12 @@
|
|
|
281
265
|
--auth-footer-text-font-size: 0.6875rem;
|
|
282
266
|
--auth-stack-gap: var(--space-3);
|
|
283
267
|
--auth-shell-field-label-gap: var(--space-1);
|
|
284
|
-
|
|
285
|
-
|
|
268
|
+
/* Canonical SCR-001 field label: a LITERAL 12px (the golden-ratio --font-size-xs ≈ 12.47px would
|
|
269
|
+
* drift the 18px line box to 18.7px and push the email input off its y=489 anchor) with a 1.5
|
|
270
|
+
* line box = 18px. The former var(--font-size-xs)/1.25 pair rendered a 14px box, sitting the
|
|
271
|
+
* email input 4px high (gh#263). */
|
|
272
|
+
--auth-shell-field-label-font-size: 0.75rem;
|
|
273
|
+
--auth-shell-field-label-line-height: 1.5;
|
|
286
274
|
|
|
287
275
|
/* CenteredShell — authenticated, no-sidebar, centred-column page shell (hosted-ID "My Page",
|
|
288
276
|
* account, standalone settings). The bar mirrors AppShell's `.app-topbar` chrome (fixed height +
|
|
@@ -59,11 +59,51 @@
|
|
|
59
59
|
--table-action-collection-secondary-width: 22%; /* target / resource */
|
|
60
60
|
--table-action-collection-meta-width: 12%; /* timestamps, ids — lowest priority */
|
|
61
61
|
--table-action-collection-actions-width: 3.5rem; /* row-action affordance, never clipped */
|
|
62
|
-
/* Compact tier, applied below the collapse step (the 390px acceptance frame).
|
|
62
|
+
/* Compact tier, applied below the collapse step (the 390px acceptance frame). Percentages,
|
|
63
|
+
* like the desktop tier: while the priority ratios FIT (the canonical queues up to the
|
|
64
|
+
* six-column budget below), they keep the table filling its container edge-to-edge with no
|
|
65
|
+
* horizontal scroll — the gh#253 acceptance. */
|
|
63
66
|
--table-action-collection-primary-width-compact: 24%;
|
|
64
67
|
--table-action-collection-secondary-width-compact: 22%;
|
|
65
68
|
--table-action-collection-meta-width-compact: 20%;
|
|
66
69
|
--table-action-collection-actions-width-compact: 2.75rem;
|
|
70
|
+
/* Wide-collection FLOORS — the compact measures from SEVEN columns up (gh#262).
|
|
71
|
+
*
|
|
72
|
+
* Percentage measures stop working once a queue carries enough columns for the shares to sum
|
|
73
|
+
* past 100%: `table-layout: fixed` NORMALIZES them back into the table's specified width, so at
|
|
74
|
+
* ~10 columns on a 390px frame a "24%" column really renders at a tenth of the frame, every
|
|
75
|
+
* column drops below one CJK glyph, and JA headers shred into a vertical one-character-per-line
|
|
76
|
+
* column (the failure mode WCAG 2.2 SC 1.4.10 Reflow exists to prevent). Cell `min-inline-size`
|
|
77
|
+
* and `max(%, length)` widths are equally inert in the fixed algorithm, and the intrinsic
|
|
78
|
+
* (max-content) size of a fixed-layout table is degenerate — all verified in Chromium — so a
|
|
79
|
+
* LENGTH is the only floor an engine respects: length columns are never squeezed, and when
|
|
80
|
+
* their sum outgrows the container the table's used width grows past its specified 100%
|
|
81
|
+
* (CSS 2.1 §17.5.2.1) into the keyboard-reachable overflow-x wrapper, which scrolls.
|
|
82
|
+
* ONE-dimensional scrolling of a data table is explicitly permitted by SC 1.4.10;
|
|
83
|
+
* one-character-per-line is not readable at all.
|
|
84
|
+
*
|
|
85
|
+
* The stylesheet switches tiers on a COLUMN BUDGET, not on width: up to six columns the
|
|
86
|
+
* percentage ratios above still resolve to readable measures at every acceptance artboard
|
|
87
|
+
* (320 · 375 · 390), so the canonical five-column approval queue keeps its documented
|
|
88
|
+
* scroll-free 390 frame byte-for-byte; from seven columns the shares are guaranteed to
|
|
89
|
+
* over-sum and the floors + intentional scroll take over. That budget is the preset's
|
|
90
|
+
* documented column-count ceiling (gh#262 expectation 3): past six columns the preset stops
|
|
91
|
+
* compressing and starts scrolling.
|
|
92
|
+
*
|
|
93
|
+
* Units are rem, not ch: `ch` tracks the "0" glyph (~half a CJK em), so a ch-denominated floor
|
|
94
|
+
* would silently halve for the JA copy these floors exist to protect. At the compact type tier
|
|
95
|
+
* (font-size-xs = 0.75rem, space-2 inline padding each side) the 5rem meta floor keeps a ~4rem
|
|
96
|
+
* text measure = 5 full-width glyphs per line — a JA header wraps to two readable lines, never
|
|
97
|
+
* a character column. */
|
|
98
|
+
--table-action-collection-primary-width-floor: 6rem;
|
|
99
|
+
--table-action-collection-secondary-width-floor: 5.5rem;
|
|
100
|
+
--table-action-collection-meta-width-floor: 5rem;
|
|
101
|
+
/* Floor for a column with NO `priority` (the free-text column, `auto` up to the budget). It
|
|
102
|
+
* cannot stay `auto` past the budget: once the marked columns over-constrain the table, the
|
|
103
|
+
* fixed algorithm hands an auto column exactly 0px (verified in Chromium) — the same
|
|
104
|
+
* shredding, moved to the free-text column. The actions floor is simply
|
|
105
|
+
* `--table-action-collection-actions-width-compact`, already an absolute measure. */
|
|
106
|
+
--table-action-collection-flex-width-floor: 5rem;
|
|
67
107
|
--table-action-collection-font-size-compact: var(--font-size-xs);
|
|
68
108
|
--table-action-collection-cell-space-x-compact: var(--space-2);
|
|
69
109
|
--table-action-collection-cell-padding-y-compact: var(--space-2);
|
|
@@ -83,18 +83,11 @@
|
|
|
83
83
|
* page moves. 11rem = 176px, i.e. the control ends flush with the compact page gutter. */
|
|
84
84
|
--page-header-extra-measure: 11rem; /* 176px */
|
|
85
85
|
|
|
86
|
-
/*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
/* PageHeader `loading` placeholders (gh#255). The title/subtitle elements wear the shared
|
|
92
|
-
* `.ui-skeleton-block` skin, so they need only a MEASURE and a block size — a service retunes the
|
|
93
|
-
* pending band's proportions here instead of per page. */
|
|
94
|
-
--page-title-placeholder-measure: 14rem; /* 224px */
|
|
95
|
-
--page-title-placeholder-block-size: 1.5em;
|
|
96
|
-
--page-subtitle-placeholder-measure: 22rem; /* 352px */
|
|
97
|
-
--page-subtitle-placeholder-block-size: 1.25em;
|
|
86
|
+
/* Gap between the page title and its status/meta band (PageContainer `status`,
|
|
87
|
+
* godxjp-ui#255), and between the band's own items. One knob aligns the badge row
|
|
88
|
+
* to a service's grid; a page that never passes `status` reads neither the token
|
|
89
|
+
* nor the wrapping row. */
|
|
90
|
+
--page-header-status-gap: var(--space-inline-sm);
|
|
98
91
|
|
|
99
92
|
/* Bounded page MEASURE (gh#245 / gh#247) — the shared inline cap applied to the page HEADER and
|
|
100
93
|
* BODY together, so the header `extra` action ends on the same edge as the body surface (the
|
package/package.json
CHANGED
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@godxjp/ui",
|
|
3
|
-
"version": "18.
|
|
4
|
-
"godxUiMcp": "18.
|
|
3
|
+
"version": "18.10.0",
|
|
4
|
+
"godxUiMcp": "18.10.0",
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/godx-jp/godxjp-ui.git"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://github.com/godx-jp/godxjp-ui#readme",
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/godx-jp/godxjp-ui/issues"
|
|
13
|
+
},
|
|
14
|
+
"author": "GoDX (https://godx.jp)",
|
|
5
15
|
"type": "module",
|
|
6
16
|
"packageManager": "pnpm@10.29.1",
|
|
7
17
|
"pnpm": {
|
|
@@ -12,6 +22,7 @@
|
|
|
12
22
|
"sideEffects": false,
|
|
13
23
|
"description": "@godxjp/ui — shared React UI framework (shadcn + Radix + Tailwind v4).",
|
|
14
24
|
"files": [
|
|
25
|
+
"LICENSE",
|
|
15
26
|
"dist",
|
|
16
27
|
"scripts/ui-audit.mjs",
|
|
17
28
|
"README.md",
|
|
@@ -296,7 +307,9 @@
|
|
|
296
307
|
"format:fix": "prettier --write .",
|
|
297
308
|
"test": "vitest run",
|
|
298
309
|
"test:visual:auth-login": "node scripts/auth-shell-login-visual.mjs",
|
|
310
|
+
"test:visual:auth-registration": "node scripts/auth-shell-registration-visual.mjs",
|
|
299
311
|
"test:visual:topbar-collision": "node scripts/topbar-collision-visual.mjs",
|
|
312
|
+
"test:visual:table-collection-cjk": "node scripts/table-collection-cjk-visual.mjs",
|
|
300
313
|
"test:watch": "vitest",
|
|
301
314
|
"test:coverage": "vitest run --coverage",
|
|
302
315
|
"check:example-imports": "node scripts/check-example-imports.mjs",
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* PageHeader — the canonical page title band (gh#255).
|
|
3
|
-
*
|
|
4
|
-
* This is the geometry `PageContainer` has always rendered, lifted into its own export so a
|
|
5
|
-
* consumer can mount it OUTSIDE a full page shell — a Sheet detail, a `MasterDetail` detail pane, a
|
|
6
|
-
* tab body, a nested route header — without re-authoring `.ui-page-header` CSS locally. There is
|
|
7
|
-
* exactly ONE implementation: `PageContainer` renders this component, so the two can never drift.
|
|
8
|
-
*
|
|
9
|
-
* The band owns: breadcrumbs (a named `<nav>` landmark with `aria-current="page"` on the leaf), the
|
|
10
|
-
* `<h1>` title, the subtitle/description, a status/meta slot, the `extra` action region, the
|
|
11
|
-
* responsive overflow arrangement (`layout`), and the pending state (`loading`). It owns no page
|
|
12
|
-
* chrome — padding, measure and body rhythm stay with `PageContainer`.
|
|
13
|
-
*
|
|
14
|
-
* DENIED / ERROR are deliberately NOT states of this component: a page the user may not see must
|
|
15
|
-
* not render its title, breadcrumb trail or actions at all (they leak the resource's existence and
|
|
16
|
-
* its name). That whole-surface contract belongs to `ErrorSurface`, which is the canonical public
|
|
17
|
-
* replacement — see `docs/CANONICAL-CONTRACTS.md`.
|
|
18
|
-
*/
|
|
19
|
-
import * as React from "react";
|
|
20
|
-
import type { PageHeaderProp } from "../../props/components/layout.prop.js";
|
|
21
|
-
export type { PageHeaderProp, PageHeaderProp as PageHeaderProps, } from "../../props/components/layout.prop.js";
|
|
22
|
-
export declare const PageHeader: React.ForwardRefExoticComponent<PageHeaderProp & React.RefAttributes<HTMLElement>>;
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
-
import * as React from "react";
|
|
4
|
-
import { ChevronRight } from "lucide-react";
|
|
5
|
-
import { useTranslation } from "../../i18n/use-translation.js";
|
|
6
|
-
import { cn } from "../../lib/utils.js";
|
|
7
|
-
const PageHeader = React.forwardRef(function PageHeader2({
|
|
8
|
-
title,
|
|
9
|
-
subtitle,
|
|
10
|
-
meta,
|
|
11
|
-
extra,
|
|
12
|
-
breadcrumb,
|
|
13
|
-
breadcrumbLabel,
|
|
14
|
-
breadcrumbAriaLabel,
|
|
15
|
-
linkComponent: LinkComponent = "a",
|
|
16
|
-
layout = "stack",
|
|
17
|
-
loading = false,
|
|
18
|
-
className
|
|
19
|
-
}, ref) {
|
|
20
|
-
const { t } = useTranslation();
|
|
21
|
-
return (
|
|
22
|
-
// `data-layout` is the only hook the header arrangement needs: `stack` (the default)
|
|
23
|
-
// matches no rule, so the historical geometry is untouched, while `responsive-inline`
|
|
24
|
-
// selects the compact-range rules that keep `extra` beside the title band (gh#231).
|
|
25
|
-
/* @__PURE__ */ jsxs(
|
|
26
|
-
"header",
|
|
27
|
-
{
|
|
28
|
-
ref,
|
|
29
|
-
className: cn("ui-page-header", className),
|
|
30
|
-
"data-layout": layout,
|
|
31
|
-
"aria-busy": loading ? "true" : void 0,
|
|
32
|
-
children: [
|
|
33
|
-
breadcrumb && breadcrumb.length > 0 && /* @__PURE__ */ jsx(
|
|
34
|
-
"nav",
|
|
35
|
-
{
|
|
36
|
-
"aria-label": breadcrumbLabel ?? breadcrumbAriaLabel ?? t("navigation.breadcrumb.ariaLabel"),
|
|
37
|
-
className: "ui-breadcrumb",
|
|
38
|
-
children: /* @__PURE__ */ jsx("ol", { className: "ui-breadcrumb-list", children: breadcrumb.map((item, i) => {
|
|
39
|
-
const isLast = i === breadcrumb.length - 1;
|
|
40
|
-
return /* @__PURE__ */ jsxs("li", { className: "ui-inline-xs", children: [
|
|
41
|
-
item.to && !isLast ? /* @__PURE__ */ jsx(
|
|
42
|
-
LinkComponent,
|
|
43
|
-
{
|
|
44
|
-
href: item.to,
|
|
45
|
-
to: item.to,
|
|
46
|
-
className: "hover:text-foreground hover:underline",
|
|
47
|
-
children: item.label
|
|
48
|
-
}
|
|
49
|
-
) : /* @__PURE__ */ jsx(
|
|
50
|
-
"span",
|
|
51
|
-
{
|
|
52
|
-
className: isLast ? "text-foreground" : "",
|
|
53
|
-
"aria-current": isLast ? "page" : void 0,
|
|
54
|
-
children: item.label
|
|
55
|
-
}
|
|
56
|
-
),
|
|
57
|
-
!isLast && /* @__PURE__ */ jsx(ChevronRight, { className: "size-3", "aria-hidden": "true" })
|
|
58
|
-
] }, i);
|
|
59
|
-
}) })
|
|
60
|
-
}
|
|
61
|
-
),
|
|
62
|
-
/* @__PURE__ */ jsxs("div", { className: "ui-page-header-row", children: [
|
|
63
|
-
/* @__PURE__ */ jsxs("div", { className: "ui-page-header-heading min-w-0", children: [
|
|
64
|
-
loading ? /* @__PURE__ */ jsx("h1", { className: "ui-page-title ui-skeleton-block ui-page-title-placeholder", children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: t("layout.pageHeader.loading") }) }) : meta != null ? /* @__PURE__ */ jsxs("div", { className: "ui-page-title-band", children: [
|
|
65
|
-
/* @__PURE__ */ jsx("h1", { className: "ui-page-title", children: title }),
|
|
66
|
-
/* @__PURE__ */ jsx("div", { className: "ui-page-header-meta", children: meta })
|
|
67
|
-
] }) : /* @__PURE__ */ jsx("h1", { className: "ui-page-title", children: title }),
|
|
68
|
-
loading ? (
|
|
69
|
-
// Decorative only — the pending state is already announced once by the heading above,
|
|
70
|
-
// so a second live placeholder here would double-announce it.
|
|
71
|
-
/* @__PURE__ */ jsx(
|
|
72
|
-
"p",
|
|
73
|
-
{
|
|
74
|
-
className: "ui-page-subtitle ui-skeleton-block ui-page-subtitle-placeholder",
|
|
75
|
-
"aria-hidden": "true"
|
|
76
|
-
}
|
|
77
|
-
)
|
|
78
|
-
) : subtitle && /* @__PURE__ */ jsx("p", { className: "ui-page-subtitle", children: subtitle })
|
|
79
|
-
] }),
|
|
80
|
-
extra && /* @__PURE__ */ jsx("div", { className: "ui-page-header-extra", children: extra })
|
|
81
|
-
] })
|
|
82
|
-
]
|
|
83
|
-
}
|
|
84
|
-
)
|
|
85
|
-
);
|
|
86
|
-
});
|
|
87
|
-
export {
|
|
88
|
-
PageHeader
|
|
89
|
-
};
|