@godxjp/ui 18.5.0 → 18.6.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/components/charts/compact-bar-trend.d.ts +2 -1
- package/dist/components/charts/index.d.ts +4 -1
- package/dist/components/data-display/data-table.d.ts +25 -4
- package/dist/components/data-display/data-table.js +13 -2
- package/dist/components/data-display/empty-state.js +1 -1
- package/dist/components/data-display/index.d.ts +1 -1
- package/dist/components/data-display/list-row.d.ts +19 -0
- package/dist/components/data-display/list-row.js +2 -0
- package/dist/components/data-display/qr-code.d.ts +1 -1
- package/dist/components/data-display/table.d.ts +47 -2
- package/dist/components/data-display/table.js +29 -4
- package/dist/components/data-entry/command.d.ts +10 -10
- package/dist/components/data-entry/index.d.ts +1 -0
- package/dist/components/data-entry/input-otp.d.ts +1 -0
- package/dist/components/feedback/dialog.d.ts +14 -1
- package/dist/components/feedback/dialog.js +4 -0
- package/dist/components/feedback/index.d.ts +1 -1
- package/dist/components/feedback/index.js +2 -0
- package/dist/components/general/logo.d.ts +7 -1
- package/dist/components/general/logo.js +1 -1
- package/dist/components/layout/app-shell.d.ts +1 -1
- package/dist/components/layout/app-shell.js +55 -46
- package/dist/components/layout/auth-account-summary.d.ts +5 -0
- package/dist/components/layout/auth-account-summary.js +31 -0
- package/dist/components/layout/auth-shell.d.ts +3 -2
- package/dist/components/layout/centered-shell.d.ts +1 -1
- package/dist/components/layout/centered-shell.js +28 -19
- package/dist/components/layout/error-surface.d.ts +35 -0
- package/dist/components/layout/error-surface.js +155 -0
- package/dist/components/layout/flex.d.ts +1 -1
- package/dist/components/layout/flex.js +4 -0
- package/dist/components/layout/index.d.ts +5 -0
- package/dist/components/layout/index.js +4 -0
- package/dist/components/layout/page-container.d.ts +1 -1
- package/dist/components/layout/page-container.js +4 -0
- package/dist/components/navigation/steps.js +38 -19
- package/dist/components/navigation/tabs.js +12 -3
- package/dist/components/ui/avatar.d.ts +2 -1
- package/dist/components/ui/avatar.js +2 -1
- package/dist/components/ui/input-otp.d.ts +4 -1
- package/dist/components/ui/input-otp.js +2 -1
- package/dist/components/ui/toggle-group.d.ts +7 -4
- package/dist/components/ui/toggle-group.js +32 -21
- package/dist/email/brand-mark.d.ts +21 -5
- package/dist/email/brand-mark.js +5 -0
- package/dist/email/color.d.ts +2 -1
- package/dist/email/geometry.d.ts +9 -1
- package/dist/email/geometry.js +1 -0
- package/dist/email/index.d.ts +6 -1
- package/dist/email/index.js +6 -0
- package/dist/email/inline-style.d.ts +7 -5
- package/dist/email/inline-style.js +5 -0
- package/dist/email/tokens.generated.d.ts +40 -20
- package/dist/email/tokens.generated.js +40 -20
- package/dist/email/urgency.d.ts +22 -0
- package/dist/email/urgency.js +14 -0
- package/dist/i18n/messages/en.json +15 -1
- package/dist/i18n/messages/ja.json +15 -1
- package/dist/i18n/messages/vi.json +15 -1
- package/dist/props/components/data-display.prop.d.ts +63 -1
- package/dist/props/components/data-entry.prop.d.ts +6 -0
- package/dist/props/components/index.d.ts +1 -1
- package/dist/props/components/layout.prop.d.ts +191 -4
- package/dist/props/components/navigation.prop.d.ts +5 -1
- package/dist/props/registry.d.ts +145 -4
- package/dist/props/registry.js +189 -5
- package/dist/props/vocabulary/data.prop.d.ts +27 -0
- package/dist/props/vocabulary/index.d.ts +3 -3
- package/dist/props/vocabulary/interaction.prop.d.ts +9 -0
- package/dist/props/vocabulary/layout.prop.d.ts +38 -7
- package/dist/styles/control.css +28 -0
- package/dist/styles/data-display-layout.css +26 -0
- package/dist/styles/layout.css +99 -0
- package/dist/styles/logo-layout.css +42 -9
- package/dist/styles/navigation-layout.css +109 -0
- package/dist/styles/shell-layout.css +302 -0
- package/dist/styles/table-layout.css +164 -1
- package/dist/theme/dxs.canonical.css +5 -4
- package/dist/tokens/axes.css +4 -3
- package/dist/tokens/base.css +1 -0
- package/dist/tokens/components/data-display.css +13 -0
- package/dist/tokens/components/email.css +43 -16
- package/dist/tokens/components/error-surface.css +36 -0
- package/dist/tokens/components/list-row.css +20 -0
- package/dist/tokens/components/logo.css +52 -10
- package/dist/tokens/components/navigation.css +15 -0
- package/dist/tokens/components/shell.css +72 -0
- package/dist/tokens/components/table.css +45 -0
- package/dist/tokens/foundation.css +26 -0
- package/dist/tokens/semantic/layout.css +25 -0
- package/package.json +8 -2
|
@@ -147,6 +147,51 @@
|
|
|
147
147
|
gap: var(--auth-shell-card-stack-gap);
|
|
148
148
|
}
|
|
149
149
|
|
|
150
|
+
/* Login is an anchored three-part composition: AuthIdentity · Card · AuthFooter. The fixed
|
|
151
|
+
* identity track absorbs absent, one-line and wrapped two-line requester states while its
|
|
152
|
+
* content remains visually adjacent to the Card. This keeps real requester data intact without
|
|
153
|
+
* allowing its line count to move the canonical SCR-001 card anchor (gh#237). */
|
|
154
|
+
.ui-auth-shell[data-preset="login"] {
|
|
155
|
+
--auth-shell-card-max-width: var(--auth-shell-login-card-max-width);
|
|
156
|
+
--auth-shell-main-align: flex-start;
|
|
157
|
+
--auth-shell-main-padding: var(--auth-shell-login-flow-offset-block)
|
|
158
|
+
var(--auth-shell-login-main-padding-inline) var(--auth-shell-login-main-padding-block-end);
|
|
159
|
+
--auth-shell-card-stack-gap: var(--auth-shell-login-card-stack-gap);
|
|
160
|
+
--auth-shell-card-padding-block-compact: var(--auth-shell-login-card-padding-block-compact);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
.ui-auth-shell[data-preset="login"] .ui-auth-shell-card {
|
|
164
|
+
display: grid;
|
|
165
|
+
grid-template-rows: var(--auth-shell-login-identity-slot-block-size) auto auto;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
.ui-auth-shell[data-preset="login"] .ui-auth-shell-card > .ui-auth-identity,
|
|
169
|
+
.ui-auth-shell[data-preset="login"] .ui-auth-shell-card > :has(> .ui-auth-identity) {
|
|
170
|
+
min-width: 0;
|
|
171
|
+
min-height: 0;
|
|
172
|
+
block-size: var(--auth-shell-login-identity-slot-block-size);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.ui-auth-shell[data-preset="login"] .ui-auth-shell-card > .ui-auth-identity,
|
|
176
|
+
.ui-auth-shell[data-preset="login"]
|
|
177
|
+
.ui-auth-shell-card
|
|
178
|
+
> :has(> .ui-auth-identity)
|
|
179
|
+
> .ui-auth-identity {
|
|
180
|
+
height: 100%;
|
|
181
|
+
justify-content: flex-end;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
.ui-auth-shell[data-preset="login"] .ui-auth-requester {
|
|
185
|
+
max-width: 100%;
|
|
186
|
+
justify-content: center;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
.ui-auth-shell[data-preset="login"] .ui-auth-requester > :last-child {
|
|
190
|
+
min-width: 0;
|
|
191
|
+
overflow-wrap: anywhere;
|
|
192
|
+
text-align: center;
|
|
193
|
+
}
|
|
194
|
+
|
|
150
195
|
.ui-auth-shell[data-preset="device-authorization"] {
|
|
151
196
|
--auth-shell-card-max-width: var(--auth-shell-device-card-max-width);
|
|
152
197
|
--auth-shell-main-padding: var(--auth-shell-device-main-padding);
|
|
@@ -197,6 +242,52 @@
|
|
|
197
242
|
height: var(--auth-requester-glyph-size);
|
|
198
243
|
}
|
|
199
244
|
|
|
245
|
+
.ui-auth-account-summary {
|
|
246
|
+
display: flex;
|
|
247
|
+
min-height: var(--auth-account-summary-min-height);
|
|
248
|
+
flex-wrap: wrap;
|
|
249
|
+
align-items: center;
|
|
250
|
+
gap: var(--auth-account-summary-gap);
|
|
251
|
+
padding: var(--auth-account-summary-padding);
|
|
252
|
+
border-radius: var(--radius-md);
|
|
253
|
+
background: hsl(var(--muted));
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
.ui-auth-account-identity {
|
|
257
|
+
display: flex;
|
|
258
|
+
min-width: min(100%, var(--auth-account-summary-identity-min-width));
|
|
259
|
+
flex: 1 1 var(--auth-account-summary-identity-min-width);
|
|
260
|
+
align-items: center;
|
|
261
|
+
gap: var(--auth-account-summary-gap);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
.ui-auth-account-avatar {
|
|
265
|
+
width: var(--auth-account-summary-avatar-size);
|
|
266
|
+
height: var(--auth-account-summary-avatar-size);
|
|
267
|
+
flex: none;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
.ui-auth-account-fallback-icon {
|
|
271
|
+
width: var(--auth-account-summary-avatar-glyph-size);
|
|
272
|
+
height: var(--auth-account-summary-avatar-glyph-size);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
.ui-auth-account-email {
|
|
276
|
+
min-width: 0;
|
|
277
|
+
overflow: hidden;
|
|
278
|
+
color: hsl(var(--foreground));
|
|
279
|
+
font-size: var(--auth-account-summary-email-font-size);
|
|
280
|
+
/* Declares its own line box because it CLIPS — see gh#254. */
|
|
281
|
+
line-height: var(--auth-account-summary-email-line-height);
|
|
282
|
+
font-weight: var(--font-weight-medium);
|
|
283
|
+
text-overflow: ellipsis;
|
|
284
|
+
white-space: nowrap;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
.ui-auth-account-summary > [data-slot="button"] {
|
|
288
|
+
margin-inline-start: auto;
|
|
289
|
+
}
|
|
290
|
+
|
|
200
291
|
.ui-auth-legal-footer {
|
|
201
292
|
display: flex;
|
|
202
293
|
flex-wrap: wrap;
|
|
@@ -277,6 +368,12 @@
|
|
|
277
368
|
--auth-shell-main-padding: var(--auth-shell-canonical-main-padding-mobile);
|
|
278
369
|
}
|
|
279
370
|
|
|
371
|
+
.ui-auth-shell[data-preset="login"] {
|
|
372
|
+
--auth-shell-main-padding: var(--auth-shell-login-flow-offset-block-mobile)
|
|
373
|
+
var(--auth-shell-login-main-padding-inline-mobile)
|
|
374
|
+
var(--auth-shell-login-main-padding-block-end);
|
|
375
|
+
}
|
|
376
|
+
|
|
280
377
|
/* Declared after the canonical mobile inset so a preset's mobile gutter wins at equal
|
|
281
378
|
* specificity: device-authorization = 5px inline (card x=5, width=380 at 390px);
|
|
282
379
|
* context-selection = edge-to-edge (0 inline). */
|
|
@@ -479,6 +576,33 @@
|
|
|
479
576
|
.app-mobile-nav-trigger {
|
|
480
577
|
display: inline-flex;
|
|
481
578
|
}
|
|
579
|
+
|
|
580
|
+
/* Some approved application contracts retain their navigation rail at narrow widths. This is
|
|
581
|
+
* an explicit AppShell mode, never a consumer media-query fork: the same sidebar node, footer,
|
|
582
|
+
* active items and token-owned rail width remain in the canonical two-track grid. */
|
|
583
|
+
.app-root[data-responsive-navigation="docked"] {
|
|
584
|
+
grid-template-areas:
|
|
585
|
+
"sidebar topbar"
|
|
586
|
+
"sidebar main"
|
|
587
|
+
"sidebar footer";
|
|
588
|
+
grid-template-columns: var(--app-shell-sidebar-width) minmax(0, 1fr);
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
.app-root[data-responsive-navigation="docked"][data-collapsed="true"] {
|
|
592
|
+
grid-template-columns: var(--app-shell-rail-width) minmax(0, 1fr);
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
.app-root[data-responsive-navigation="docked"] > .app-sidebar {
|
|
596
|
+
display: flex;
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
.app-root[data-responsive-navigation="docked"] > .app-topbar {
|
|
600
|
+
padding-inline: var(--app-shell-bar-inset);
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
.app-root[data-responsive-navigation="docked"] .app-mobile-nav-trigger {
|
|
604
|
+
display: none;
|
|
605
|
+
}
|
|
482
606
|
}
|
|
483
607
|
|
|
484
608
|
.sb-root {
|
|
@@ -781,6 +905,10 @@
|
|
|
781
905
|
min-width: 0;
|
|
782
906
|
flex: 1;
|
|
783
907
|
overflow: hidden;
|
|
908
|
+
/* gh#254 — MUST NOT inherit the row's `line-height: 1`. This element clips, so its line box is
|
|
909
|
+
* its clip box, and a 1em box is shorter than the font's ascent+descent: every descender and
|
|
910
|
+
* Vietnamese tone mark below the baseline gets sheared off. Knob, not constant (rule #45). */
|
|
911
|
+
line-height: var(--sidebar-nav-item-line-height);
|
|
784
912
|
text-overflow: ellipsis;
|
|
785
913
|
white-space: nowrap;
|
|
786
914
|
}
|
|
@@ -1093,6 +1221,16 @@
|
|
|
1093
1221
|
.ui-topbar-start {
|
|
1094
1222
|
flex: 0 1 auto;
|
|
1095
1223
|
}
|
|
1224
|
+
.ui-topbar-start > :last-child {
|
|
1225
|
+
max-width: 100%;
|
|
1226
|
+
min-width: 0;
|
|
1227
|
+
flex: 0 1 auto;
|
|
1228
|
+
overflow: hidden;
|
|
1229
|
+
/* Declares its own line box because it CLIPS — see gh#254. */
|
|
1230
|
+
line-height: var(--topbar-start-truncate-line-height);
|
|
1231
|
+
text-overflow: ellipsis;
|
|
1232
|
+
white-space: nowrap;
|
|
1233
|
+
}
|
|
1096
1234
|
.ui-topbar-center {
|
|
1097
1235
|
flex: 1 1 0%;
|
|
1098
1236
|
justify-content: center;
|
|
@@ -1103,6 +1241,17 @@
|
|
|
1103
1241
|
margin-inline-start: auto;
|
|
1104
1242
|
}
|
|
1105
1243
|
|
|
1244
|
+
/* COLLISION CONTRACT (gh#244) — with a docked 16rem sidebar, 901–1100px viewports do not have
|
|
1245
|
+
* enough room for a breadcrumb/title, full search trigger and end utilities. The center slot is
|
|
1246
|
+
* optional by definition, so remove it before it can cover either owned edge. This also gives
|
|
1247
|
+
* phones the same deterministic allocation. A consumer with a real compact center presentation
|
|
1248
|
+
* can opt it back in through the public token instead of a page-local media query. */
|
|
1249
|
+
@media (width <= 68.75rem) {
|
|
1250
|
+
.ui-topbar-center {
|
|
1251
|
+
display: var(--topbar-center-compact-display);
|
|
1252
|
+
}
|
|
1253
|
+
}
|
|
1254
|
+
|
|
1106
1255
|
.tb-chip {
|
|
1107
1256
|
display: inline-flex;
|
|
1108
1257
|
max-width: 15rem;
|
|
@@ -1156,6 +1305,10 @@
|
|
|
1156
1305
|
min-width: 0;
|
|
1157
1306
|
overflow: hidden;
|
|
1158
1307
|
font-weight: 500;
|
|
1308
|
+
/* gh#254 — same trap as `.sb-label`: this clips, so it must own a line box tall enough for the
|
|
1309
|
+
* font's descenders. `.tb-chip` uses `font: inherit`, so without this the chip would shear its
|
|
1310
|
+
* glyphs the moment a service set a tight line-height on the bar. */
|
|
1311
|
+
line-height: 1.5;
|
|
1159
1312
|
text-overflow: ellipsis;
|
|
1160
1313
|
white-space: nowrap;
|
|
1161
1314
|
}
|
|
@@ -1286,3 +1439,152 @@
|
|
|
1286
1439
|
transition: none;
|
|
1287
1440
|
}
|
|
1288
1441
|
}
|
|
1442
|
+
|
|
1443
|
+
/*
|
|
1444
|
+
* ERROR SURFACE — the 403 / 404 / 500 / 503 exception surface (gh#221, gh#251).
|
|
1445
|
+
*
|
|
1446
|
+
* Geometry is PACKAGE-OWNED at 1440 / 1024 / 390: a consumer never writes `min-h-dvh`, a
|
|
1447
|
+
* flex-centring class or a media query for an error page. In `system` mode the viewport centring
|
|
1448
|
+
* comes from `CenteredShell align="center"` (which the component renders itself); this block owns
|
|
1449
|
+
* the surface block that is identical in BOTH modes — measure, rhythm, metadata list.
|
|
1450
|
+
*
|
|
1451
|
+
* The narrow step is a CONTAINER query, not a viewport one (the SplitPane precedent, gh#165): the
|
|
1452
|
+
* surface reads its OWN width, so it compacts correctly whether the shrinking came from a 390px
|
|
1453
|
+
* phone or from an application shell whose sidebar is expanded on a laptop.
|
|
1454
|
+
*/
|
|
1455
|
+
@layer components {
|
|
1456
|
+
.ui-error-surface {
|
|
1457
|
+
container: error-surface / inline-size;
|
|
1458
|
+
display: flex;
|
|
1459
|
+
width: 100%;
|
|
1460
|
+
max-width: var(--error-surface-max-width);
|
|
1461
|
+
flex-direction: column;
|
|
1462
|
+
align-items: center;
|
|
1463
|
+
/* Logical, so the surface stays centred and its text start-aligns correctly under `dir="rtl"`. */
|
|
1464
|
+
margin-inline: auto;
|
|
1465
|
+
gap: var(--error-surface-gap);
|
|
1466
|
+
padding-block: var(--error-surface-padding-block);
|
|
1467
|
+
text-align: center;
|
|
1468
|
+
}
|
|
1469
|
+
|
|
1470
|
+
.ui-error-surface-brand {
|
|
1471
|
+
display: flex;
|
|
1472
|
+
justify-content: center;
|
|
1473
|
+
padding-block-end: var(--error-surface-brand-gap);
|
|
1474
|
+
}
|
|
1475
|
+
|
|
1476
|
+
/* The EmptyState body already owns its own vertical rhythm and description measure
|
|
1477
|
+
* (--empty-state-*); the surface only removes the duplicated block padding so the two spacing
|
|
1478
|
+
* systems do not stack into a hole between the status code and the icon. */
|
|
1479
|
+
.ui-error-surface .ui-error-surface-body {
|
|
1480
|
+
width: 100%;
|
|
1481
|
+
padding-block: 0;
|
|
1482
|
+
}
|
|
1483
|
+
|
|
1484
|
+
.ui-error-surface-status {
|
|
1485
|
+
margin: 0;
|
|
1486
|
+
}
|
|
1487
|
+
|
|
1488
|
+
.ui-error-surface-meta {
|
|
1489
|
+
display: flex;
|
|
1490
|
+
width: 100%;
|
|
1491
|
+
flex-direction: column;
|
|
1492
|
+
gap: var(--error-surface-meta-gap);
|
|
1493
|
+
/* Chrome is a token, default quiet (rule #44) — `none` unless a service opts in. */
|
|
1494
|
+
border-block-start: var(--error-surface-meta-border);
|
|
1495
|
+
padding-block-start: var(--error-surface-meta-padding-block);
|
|
1496
|
+
margin: 0;
|
|
1497
|
+
}
|
|
1498
|
+
|
|
1499
|
+
.ui-error-surface-meta-row {
|
|
1500
|
+
display: flex;
|
|
1501
|
+
flex-wrap: wrap;
|
|
1502
|
+
justify-content: center;
|
|
1503
|
+
gap: var(--error-surface-meta-row-gap);
|
|
1504
|
+
}
|
|
1505
|
+
|
|
1506
|
+
.ui-error-surface-meta-row > dd {
|
|
1507
|
+
margin-inline-start: 0;
|
|
1508
|
+
}
|
|
1509
|
+
|
|
1510
|
+
.ui-error-surface-progress {
|
|
1511
|
+
width: 100%;
|
|
1512
|
+
max-width: var(--error-surface-progress-max-width);
|
|
1513
|
+
}
|
|
1514
|
+
|
|
1515
|
+
/*
|
|
1516
|
+
* NARROW STEP (the 390 case). Reclaim vertical space and stop a long ja / vi metadata row from
|
|
1517
|
+
* wrapping into a ragged two-column shape: each label stacks over its value, centred.
|
|
1518
|
+
*/
|
|
1519
|
+
@container error-surface (width < 30rem) {
|
|
1520
|
+
.ui-error-surface {
|
|
1521
|
+
padding-block: var(--error-surface-padding-block-compact);
|
|
1522
|
+
}
|
|
1523
|
+
|
|
1524
|
+
.ui-error-surface-meta-row {
|
|
1525
|
+
flex-direction: column;
|
|
1526
|
+
gap: 0;
|
|
1527
|
+
}
|
|
1528
|
+
}
|
|
1529
|
+
}
|
|
1530
|
+
|
|
1531
|
+
@layer components {
|
|
1532
|
+
/* ── CenteredShell · `preset="public-landing"` (gh#252) ──────────────────────────────────────
|
|
1533
|
+
* A PUBLIC landing page (marketing header · hero · sections · legal footer) is a COMPOSITION,
|
|
1534
|
+
* not a framework component (docs/COMPOSITION-VS-COMPONENT.md: Hero / Navbar / Footer / Pricing
|
|
1535
|
+
* all FAIL the Framework-Component Test). What the consumer must NOT own is the SHELL geometry —
|
|
1536
|
+
* the content measure, the header/footer measure alignment, the section rhythm and the flat
|
|
1537
|
+
* public-surface chrome. This preset owns all of it through `--centered-shell-landing-*` knobs,
|
|
1538
|
+
* so a landing composes real primitives with ZERO page-local CSS and zero descendant selectors.
|
|
1539
|
+
*
|
|
1540
|
+
* `preset="default"` emits NO `data-preset` attribute at all, so none of this can match and every
|
|
1541
|
+
* existing CenteredShell keeps its exact box (the gh#231 inert-default contract). */
|
|
1542
|
+
.ui-centered-shell[data-preset="public-landing"] {
|
|
1543
|
+
--centered-shell-main-padding: var(--centered-shell-landing-main-padding-block)
|
|
1544
|
+
var(--centered-shell-landing-inset-inline);
|
|
1545
|
+
/* The hero title is a real `Heading level={1}`; the preset re-points the h1 tier the same way
|
|
1546
|
+
* `.ui-auth-shell` re-points it — never a consumer font-size. */
|
|
1547
|
+
--heading-h1: var(--centered-shell-landing-heading-size);
|
|
1548
|
+
/* Flat public surface: every Card in the subtree loses its elevation from ONE knob instead of
|
|
1549
|
+
* a consumer `.landing .card { box-shadow: none }` descendant selector. */
|
|
1550
|
+
--card-shadow: var(--centered-shell-landing-card-shadow);
|
|
1551
|
+
background: hsl(var(--centered-shell-landing-background, var(--background)));
|
|
1552
|
+
}
|
|
1553
|
+
|
|
1554
|
+
.ui-centered-shell[data-preset="public-landing"] .ui-centered-shell-column {
|
|
1555
|
+
display: flex;
|
|
1556
|
+
max-width: var(--centered-shell-landing-max-width);
|
|
1557
|
+
flex-direction: column;
|
|
1558
|
+
/* Section rhythm — the consumer stacks plain `<section>` layout elements and never sets a gap. */
|
|
1559
|
+
gap: var(--centered-shell-landing-section-gap);
|
|
1560
|
+
}
|
|
1561
|
+
|
|
1562
|
+
/* Header and footer share the column's measure WITHOUT a consumer max-width wrapper: the inline
|
|
1563
|
+
* padding is the page gutter until the viewport is wider than the measure, then it grows so the
|
|
1564
|
+
* bar content starts on exactly the same inline edge as the centred column. */
|
|
1565
|
+
.ui-centered-shell[data-preset="public-landing"] .ui-centered-shell-bar,
|
|
1566
|
+
.ui-centered-shell[data-preset="public-landing"] .ui-centered-shell-footer {
|
|
1567
|
+
padding-inline: max(
|
|
1568
|
+
var(--centered-shell-landing-inset-inline),
|
|
1569
|
+
calc((100% - var(--centered-shell-landing-max-width)) / 2)
|
|
1570
|
+
);
|
|
1571
|
+
}
|
|
1572
|
+
|
|
1573
|
+
.ui-centered-shell[data-preset="public-landing"] .ui-centered-shell-footer {
|
|
1574
|
+
padding-block: var(--centered-shell-landing-footer-padding-block);
|
|
1575
|
+
text-align: start;
|
|
1576
|
+
}
|
|
1577
|
+
|
|
1578
|
+
/* Compact step (the 390px acceptance width sits here): the gutter, the section rhythm and the
|
|
1579
|
+
* hero tier switch to their compact knobs. One media query, owned by the package. */
|
|
1580
|
+
@media (width < 40rem) {
|
|
1581
|
+
.ui-centered-shell[data-preset="public-landing"] {
|
|
1582
|
+
--centered-shell-landing-inset-inline: var(--centered-shell-landing-inset-inline-compact);
|
|
1583
|
+
--centered-shell-landing-main-padding-block: var(
|
|
1584
|
+
--centered-shell-landing-main-padding-block-compact
|
|
1585
|
+
);
|
|
1586
|
+
--centered-shell-landing-section-gap: var(--centered-shell-landing-section-gap-compact);
|
|
1587
|
+
--centered-shell-landing-heading-size: var(--centered-shell-landing-heading-size-compact);
|
|
1588
|
+
}
|
|
1589
|
+
}
|
|
1590
|
+
}
|
|
@@ -74,12 +74,17 @@
|
|
|
74
74
|
gap: var(--space-inline-sm);
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
+
/* The footer owns its own inset on BOTH axes (gh#236) — it is a self-contained slot that is
|
|
78
|
+
* usually dropped straight into a flush container, so relying on an ancestor for inline/block-end
|
|
79
|
+
* padding left the label and the page-size Select flush against the container edge and its
|
|
80
|
+
* closing border. Logical properties only (RTL-safe); both axes are tunable tokens (#45). */
|
|
77
81
|
.ui-data-table-pagination {
|
|
78
82
|
display: flex;
|
|
79
83
|
align-items: center;
|
|
80
84
|
justify-content: flex-end;
|
|
81
85
|
gap: var(--space-inline-sm);
|
|
82
|
-
padding-
|
|
86
|
+
padding-block: var(--table-pagination-padding-y, var(--space-stack-sm));
|
|
87
|
+
padding-inline: var(--table-pagination-padding-x, var(--table-cell-space-x));
|
|
83
88
|
}
|
|
84
89
|
|
|
85
90
|
/* Numbered footer may wrap only between its two semantic groups. The supported JA/EN/VI locale
|
|
@@ -115,10 +120,22 @@
|
|
|
115
120
|
|
|
116
121
|
.ui-data-table-surface {
|
|
117
122
|
overflow: hidden;
|
|
123
|
+
/* Narrow-viewport legibility floor — a TOKEN, not the old `min-w-[640px]` literal (gh#253,
|
|
124
|
+
* rule #45). Cleared at the `sm` step below, and opted out of entirely by the collection
|
|
125
|
+
* preset, which owns its width through the column-priority measures. */
|
|
126
|
+
min-inline-size: var(--table-surface-min-inline-size);
|
|
118
127
|
border: 1px solid hsl(var(--border));
|
|
119
128
|
border-radius: var(--radius-md);
|
|
120
129
|
}
|
|
121
130
|
|
|
131
|
+
/* `preset="action-collection"` (gh#253) — the priority measures fit the table to its container at
|
|
132
|
+
* every width, so the desktop floor would re-introduce exactly the horizontal scroll the preset
|
|
133
|
+
* removes. Attribute-scoped: `preset="default"` emits NO attribute, so an untouched DataTable
|
|
134
|
+
* never matches this rule (the inert-default contract, gh#231). */
|
|
135
|
+
.ui-data-table-surface[data-preset="action-collection"] {
|
|
136
|
+
min-inline-size: 0;
|
|
137
|
+
}
|
|
138
|
+
|
|
122
139
|
/* Zebra striping (opt-in via the `striped` prop). Selected rows keep their
|
|
123
140
|
* own emphasis, so they are excluded from the stripe. */
|
|
124
141
|
.ui-data-table-surface[data-striped] tbody tr:nth-child(even):not([data-state="selected"]) {
|
|
@@ -187,6 +204,12 @@
|
|
|
187
204
|
.ui-data-table-scroll::after {
|
|
188
205
|
inset-inline-end: 0;
|
|
189
206
|
}
|
|
207
|
+
|
|
208
|
+
/* From `sm` up the viewport is already wider than the floor, so it is released and the surface
|
|
209
|
+
* simply fills its container (this is the `sm:min-w-0` half of the old utility pair). */
|
|
210
|
+
.ui-data-table-surface {
|
|
211
|
+
min-inline-size: 0;
|
|
212
|
+
}
|
|
190
213
|
}
|
|
191
214
|
|
|
192
215
|
/* ── Pinned (sticky) inline-end column ────────────────────────────────
|
|
@@ -233,3 +256,143 @@
|
|
|
233
256
|
);
|
|
234
257
|
}
|
|
235
258
|
}
|
|
259
|
+
|
|
260
|
+
@layer components {
|
|
261
|
+
/* ── Table · `preset="action-collection"` (gh#253) ───────────────────────────────────────────
|
|
262
|
+
* The canonical dense approval / action queue: requester · target · reason · requested date ·
|
|
263
|
+
* row actions, all five discoverable in the initial 390px frame, WITHOUT a consumer width, a
|
|
264
|
+
* hidden column or a page-local breakpoint.
|
|
265
|
+
*
|
|
266
|
+
* It keeps the REAL table: no `display` change, no role rewriting, no card transformation — so
|
|
267
|
+
* `<table>/<thead>/<tr>/<th>/<td>` semantics, header association, `aria-sort` and screen-reader
|
|
268
|
+
* table navigation survive exactly as they are at 1440. What the preset replaces is the SIZING
|
|
269
|
+
* model: the desktop INTRINSIC column widths (a `white-space: nowrap` reason column is what
|
|
270
|
+
* makes a five-column queue 1511px wide and forces the horizontal scroll gh#253 reports) give
|
|
271
|
+
* way to `table-layout: fixed` plus token-owned column-PRIORITY measures, and cells wrap.
|
|
272
|
+
*
|
|
273
|
+
* The collapse step is measured against the TABLE'S OWN container, not the viewport (a table in
|
|
274
|
+
* a master rail must collapse before the page does), so it is a container query. Below the step
|
|
275
|
+
* only the MEASURES and the type/padding tier change — the structure is identical. */
|
|
276
|
+
.ui-table-collection {
|
|
277
|
+
container: ui-table-collection / inline-size;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
.ui-table-collection [data-slot="table"] {
|
|
281
|
+
table-layout: fixed;
|
|
282
|
+
inline-size: 100%;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
.ui-table-collection :is([data-slot="table-head"], [data-slot="table-cell"]) {
|
|
286
|
+
/* The column measure comes from `priority`; an unmarked column takes what is left (`auto`),
|
|
287
|
+
* which is the free-text column. */
|
|
288
|
+
inline-size: var(--table-action-collection-column-width, auto);
|
|
289
|
+
overflow-wrap: anywhere;
|
|
290
|
+
white-space: normal;
|
|
291
|
+
vertical-align: top;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
.ui-table-collection [data-priority="primary"] {
|
|
295
|
+
--table-action-collection-column-width: var(--table-action-collection-primary-width);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
.ui-table-collection [data-priority="secondary"] {
|
|
299
|
+
--table-action-collection-column-width: var(--table-action-collection-secondary-width);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
.ui-table-collection [data-priority="meta"] {
|
|
303
|
+
--table-action-collection-column-width: var(--table-action-collection-meta-width);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
.ui-table-collection [data-priority="actions"] {
|
|
307
|
+
--table-action-collection-column-width: var(--table-action-collection-actions-width);
|
|
308
|
+
text-align: end;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/* Below the step the SOURCE measures are re-pointed to their compact tier (and the type / row
|
|
312
|
+
* density with them); nothing else moves. One block per canonical step — a media/container
|
|
313
|
+
* query cannot read a `var()`, so the tokenized scale is written out (sm 40rem · md 48rem ·
|
|
314
|
+
* lg 64rem · xl 80rem, the same steps as `--master-detail-collapse-below`). */
|
|
315
|
+
@container ui-table-collection (width < 40rem) {
|
|
316
|
+
[data-collapse-below="sm"] [data-slot="table"] {
|
|
317
|
+
--table-action-collection-primary-width: var(--table-action-collection-primary-width-compact);
|
|
318
|
+
--table-action-collection-secondary-width: var(
|
|
319
|
+
--table-action-collection-secondary-width-compact
|
|
320
|
+
);
|
|
321
|
+
--table-action-collection-meta-width: var(--table-action-collection-meta-width-compact);
|
|
322
|
+
--table-action-collection-actions-width: var(--table-action-collection-actions-width-compact);
|
|
323
|
+
--table-row-height: var(--table-action-collection-row-height-compact);
|
|
324
|
+
--table-cell-space-x: var(--table-action-collection-cell-space-x-compact);
|
|
325
|
+
--table-cell-padding-y: var(--table-action-collection-cell-padding-y-compact);
|
|
326
|
+
font-size: var(--table-action-collection-font-size-compact);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/* A nowrap child (a Badge pill, a chip) would otherwise bleed into the next column at the
|
|
330
|
+
* compact measure — inside a collapsed action cell everything wraps. */
|
|
331
|
+
[data-collapse-below="sm"] [data-slot="table-cell"] * {
|
|
332
|
+
white-space: normal;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
@container ui-table-collection (width < 48rem) {
|
|
337
|
+
[data-collapse-below="md"] [data-slot="table"] {
|
|
338
|
+
--table-action-collection-primary-width: var(--table-action-collection-primary-width-compact);
|
|
339
|
+
--table-action-collection-secondary-width: var(
|
|
340
|
+
--table-action-collection-secondary-width-compact
|
|
341
|
+
);
|
|
342
|
+
--table-action-collection-meta-width: var(--table-action-collection-meta-width-compact);
|
|
343
|
+
--table-action-collection-actions-width: var(--table-action-collection-actions-width-compact);
|
|
344
|
+
--table-row-height: var(--table-action-collection-row-height-compact);
|
|
345
|
+
--table-cell-space-x: var(--table-action-collection-cell-space-x-compact);
|
|
346
|
+
--table-cell-padding-y: var(--table-action-collection-cell-padding-y-compact);
|
|
347
|
+
font-size: var(--table-action-collection-font-size-compact);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/* A nowrap child (a Badge pill, a chip) would otherwise bleed into the next column at the
|
|
351
|
+
* compact measure — inside a collapsed action cell everything wraps. */
|
|
352
|
+
[data-collapse-below="md"] [data-slot="table-cell"] * {
|
|
353
|
+
white-space: normal;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
@container ui-table-collection (width < 64rem) {
|
|
358
|
+
[data-collapse-below="lg"] [data-slot="table"] {
|
|
359
|
+
--table-action-collection-primary-width: var(--table-action-collection-primary-width-compact);
|
|
360
|
+
--table-action-collection-secondary-width: var(
|
|
361
|
+
--table-action-collection-secondary-width-compact
|
|
362
|
+
);
|
|
363
|
+
--table-action-collection-meta-width: var(--table-action-collection-meta-width-compact);
|
|
364
|
+
--table-action-collection-actions-width: var(--table-action-collection-actions-width-compact);
|
|
365
|
+
--table-row-height: var(--table-action-collection-row-height-compact);
|
|
366
|
+
--table-cell-space-x: var(--table-action-collection-cell-space-x-compact);
|
|
367
|
+
--table-cell-padding-y: var(--table-action-collection-cell-padding-y-compact);
|
|
368
|
+
font-size: var(--table-action-collection-font-size-compact);
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/* A nowrap child (a Badge pill, a chip) would otherwise bleed into the next column at the
|
|
372
|
+
* compact measure — inside a collapsed action cell everything wraps. */
|
|
373
|
+
[data-collapse-below="lg"] [data-slot="table-cell"] * {
|
|
374
|
+
white-space: normal;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
@container ui-table-collection (width < 80rem) {
|
|
379
|
+
[data-collapse-below="xl"] [data-slot="table"] {
|
|
380
|
+
--table-action-collection-primary-width: var(--table-action-collection-primary-width-compact);
|
|
381
|
+
--table-action-collection-secondary-width: var(
|
|
382
|
+
--table-action-collection-secondary-width-compact
|
|
383
|
+
);
|
|
384
|
+
--table-action-collection-meta-width: var(--table-action-collection-meta-width-compact);
|
|
385
|
+
--table-action-collection-actions-width: var(--table-action-collection-actions-width-compact);
|
|
386
|
+
--table-row-height: var(--table-action-collection-row-height-compact);
|
|
387
|
+
--table-cell-space-x: var(--table-action-collection-cell-space-x-compact);
|
|
388
|
+
--table-cell-padding-y: var(--table-action-collection-cell-padding-y-compact);
|
|
389
|
+
font-size: var(--table-action-collection-font-size-compact);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/* A nowrap child (a Badge pill, a chip) would otherwise bleed into the next column at the
|
|
393
|
+
* compact measure — inside a collapsed action cell everything wraps. */
|
|
394
|
+
[data-collapse-below="xl"] [data-slot="table-cell"] * {
|
|
395
|
+
white-space: normal;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
@@ -33,10 +33,11 @@
|
|
|
33
33
|
|
|
34
34
|
:root {
|
|
35
35
|
/* ── Brand palette — the shipped GodX Navy ramp (identical to the `brand`
|
|
36
|
-
* axis preset). The
|
|
37
|
-
* `--logo-godx-color` / `--logo-wordmark-color` default to the `--
|
|
38
|
-
*
|
|
39
|
-
*
|
|
36
|
+
* axis preset). The emerald IDENTITY mark is deliberately NOT here:
|
|
37
|
+
* `--logo-godx-color` / `--logo-wordmark-color` default to the `--brand`
|
|
38
|
+
* IDENTITY role at their call sites and never read `--primary` (nor the
|
|
39
|
+
* `--success` status green — gh#250), so a re-themed action colour can
|
|
40
|
+
* never recolour the GoDX mark or wordmark. */
|
|
40
41
|
--primary: 211 73% 15%;
|
|
41
42
|
--primary-foreground: 0 0% 100%;
|
|
42
43
|
--ring: 24 99% 46%;
|
package/dist/tokens/axes.css
CHANGED
|
@@ -73,9 +73,10 @@
|
|
|
73
73
|
* `src/theme/dxs.canonical.css` mirrors this block for stylesheet-only apps;
|
|
74
74
|
* `src/tokens/__tests__/dxs-canonical-theme.test.ts` fails if the two drift.
|
|
75
75
|
*
|
|
76
|
-
* The
|
|
77
|
-
* `--logo-wordmark-color` already default to the `--
|
|
78
|
-
* their call sites and never reference `--primary
|
|
76
|
+
* The GoDX identity mark needs no binding: `--logo-godx-color` /
|
|
77
|
+
* `--logo-wordmark-color` already default to the `--brand` IDENTITY role (the
|
|
78
|
+
* canonical emerald) at their call sites, and never reference `--primary` — nor
|
|
79
|
+
* the `--success` status green they wrongly borrowed before gh#250. */
|
|
79
80
|
:root[data-brand="dxs"] {
|
|
80
81
|
--primary: 211 73% 15%;
|
|
81
82
|
--primary-foreground: 0 0% 100%;
|
package/dist/tokens/base.css
CHANGED
|
@@ -15,6 +15,19 @@
|
|
|
15
15
|
Painted as an overlay so a service sets --avatar-tint: hsl(var(--primary) / 0.08). */
|
|
16
16
|
--avatar-tint: transparent;
|
|
17
17
|
|
|
18
|
+
/* Entity-header mark — `<Avatar shape="square">` (gh#249): the compact rounded SQUARE an
|
|
19
|
+
organization/service header uses, as opposed to the round person avatar. Every value is a knob
|
|
20
|
+
(rule #45) so a service matches the mark to its own grid without a className override.
|
|
21
|
+
--avatar-square-background / --avatar-square-foreground are role-mirror knobs: `initial` so the
|
|
22
|
+
--primary / --primary-foreground defaults re-resolve at the CALL SITE under a scoped
|
|
23
|
+
[data-tenant]/.dark theme (a :root binding to a role var would freeze at the :root value).
|
|
24
|
+
Defaults = --radius-lg corners · --control-height box (same as the circle avatar, so swapping
|
|
25
|
+
shape never reflows a header) · hsl(var(--primary)) fill · hsl(var(--primary-foreground)) glyph. */
|
|
26
|
+
--avatar-square-radius: var(--radius-lg);
|
|
27
|
+
--avatar-square-size: var(--control-height);
|
|
28
|
+
--avatar-square-background: initial;
|
|
29
|
+
--avatar-square-foreground: initial;
|
|
30
|
+
|
|
18
31
|
/* Progress track + fill — `initial` so the role defaults re-resolve under a scoped theme.
|
|
19
32
|
Track reads --secondary, fill reads --success; a service re-tones once.
|
|
20
33
|
Defaults = hsl(var(--secondary)) track · hsl(var(--success)) fill. */
|