@godxjp/ui 18.9.0 → 18.11.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/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/index.d.ts +2 -0
- package/dist/components/data-entry/index.js +2 -0
- package/dist/components/data-entry/select.d.ts +7 -1
- package/dist/components/data-entry/select.js +46 -26
- 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 +19 -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 +61 -15
- package/dist/components/layout/resizable.d.ts +1 -1
- package/dist/components/layout/resizable.js +26 -8
- 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/pagination.js +20 -1
- package/dist/components/navigation/tabs.js +6 -1
- package/dist/i18n/messages/en.json +59 -4
- package/dist/i18n/messages/ja.json +54 -5
- package/dist/i18n/messages/vi.json +53 -4
- package/dist/lib/field-a11y.d.ts +7 -0
- package/dist/lib/field-a11y.js +6 -0
- package/dist/lib/hooks.d.ts +15 -0
- package/dist/lib/hooks.js +37 -0
- package/dist/props/components/data-display.prop.d.ts +66 -0
- package/dist/props/components/data-entry.prop.d.ts +54 -0
- 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 +80 -51
- package/dist/props/components/navigation.prop.d.ts +77 -50
- package/dist/props/registry.d.ts +274 -54
- package/dist/props/registry.js +362 -73
- 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/control.css +5 -0
- package/dist/styles/layout.css +118 -108
- package/dist/styles/shell-layout.css +16 -7
- package/dist/styles/table-layout.css +92 -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/navigation.css +10 -25
- package/dist/tokens/components/shell.css +20 -9
- package/dist/tokens/components/table.css +41 -1
- package/dist/tokens/semantic/layout.css +8 -7
- package/package.json +15 -2
- package/dist/components/layout/page-header.d.ts +0 -22
- package/dist/components/layout/page-header.js +0 -89
package/dist/styles/layout.css
CHANGED
|
@@ -521,47 +521,35 @@
|
|
|
521
521
|
width: 100%;
|
|
522
522
|
}
|
|
523
523
|
|
|
524
|
-
.
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
line-height: var(--line-height-tight);
|
|
529
|
-
overflow-wrap: anywhere;
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
/* Title + `meta` share one baseline-aligned band (gh#255). The band only exists when `meta` is
|
|
533
|
-
* passed, so a header without it keeps its historical bare-`<h1>` DOM. `wrap` is what keeps a
|
|
534
|
-
* long JA/VI title and a status Badge legible at 390px instead of squeezing the title column. */
|
|
535
|
-
.ui-page-title-band {
|
|
524
|
+
/* Title line + status/meta band (PageContainer `status`, godxjp-ui#255). The band sits on
|
|
525
|
+
* the title's baseline row at the token-owned gap and WRAPS under the title when the
|
|
526
|
+
* viewport (390px) or a long JA/VI title leaves no room — never clips, never overlaps. */
|
|
527
|
+
.ui-page-header-title-row {
|
|
536
528
|
display: flex;
|
|
537
529
|
flex-wrap: wrap;
|
|
538
|
-
align-items:
|
|
539
|
-
gap: var(--page-header-
|
|
530
|
+
align-items: center;
|
|
531
|
+
gap: var(--page-header-status-gap);
|
|
540
532
|
min-inline-size: 0;
|
|
541
533
|
}
|
|
542
534
|
|
|
543
|
-
.ui-page-header-
|
|
535
|
+
.ui-page-header-title-row > .ui-page-title {
|
|
536
|
+
min-inline-size: 0;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
.ui-page-header-status {
|
|
544
540
|
display: flex;
|
|
545
541
|
flex-wrap: wrap;
|
|
546
542
|
align-items: center;
|
|
547
|
-
gap: var(--page-header-
|
|
543
|
+
gap: var(--page-header-status-gap);
|
|
548
544
|
min-inline-size: 0;
|
|
549
545
|
}
|
|
550
546
|
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
max-inline-size: 100%;
|
|
558
|
-
min-block-size: var(--page-title-placeholder-block-size);
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
-
.ui-page-subtitle-placeholder {
|
|
562
|
-
inline-size: var(--page-subtitle-placeholder-measure);
|
|
563
|
-
max-inline-size: 100%;
|
|
564
|
-
min-block-size: var(--page-subtitle-placeholder-block-size);
|
|
547
|
+
.ui-page-title {
|
|
548
|
+
font-size: var(--page-title-font-size);
|
|
549
|
+
font-weight: var(--font-weight-medium);
|
|
550
|
+
letter-spacing: var(--letter-spacing-tight);
|
|
551
|
+
line-height: var(--line-height-tight);
|
|
552
|
+
overflow-wrap: anywhere;
|
|
565
553
|
}
|
|
566
554
|
|
|
567
555
|
/* Compact viewports use a responsive type step, not compact density: body/control text and
|
|
@@ -638,6 +626,22 @@
|
|
|
638
626
|
margin-top: var(--space-1);
|
|
639
627
|
}
|
|
640
628
|
|
|
629
|
+
/* `headerLoading` placeholders — the real `<h1>`/`<p>` wearing the shared `.ui-skeleton-block`
|
|
630
|
+
* skin, so the pending band occupies the same rhythm the settled band will. `max-inline-size:
|
|
631
|
+
* 100%` keeps them inside a 390px column; the block size replaces the line box the (sr-only)
|
|
632
|
+
* text no longer fills. */
|
|
633
|
+
.ui-page-title-placeholder {
|
|
634
|
+
inline-size: var(--page-title-placeholder-measure);
|
|
635
|
+
max-inline-size: 100%;
|
|
636
|
+
min-block-size: var(--page-title-placeholder-block-size);
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
.ui-page-subtitle-placeholder {
|
|
640
|
+
inline-size: var(--page-subtitle-placeholder-measure);
|
|
641
|
+
max-inline-size: 100%;
|
|
642
|
+
min-block-size: var(--page-subtitle-placeholder-block-size);
|
|
643
|
+
}
|
|
644
|
+
|
|
641
645
|
/* Default: content-height + top-packed. The container's min-height:100% keeps
|
|
642
646
|
* the page background spanning the viewport-tall shell, but the body itself is
|
|
643
647
|
* NOT stretched — so short pages no longer leave a jarring void below their
|
|
@@ -953,84 +957,6 @@
|
|
|
953
957
|
font-size: var(--filter-label-font-size);
|
|
954
958
|
}
|
|
955
959
|
|
|
956
|
-
/* ── FilterBar typed model (#258) ──────────────────────────────────────────────────────────
|
|
957
|
-
* Every rule below is scoped to a region the bar only emits when its prop is passed, so a bar
|
|
958
|
-
* built the old way (children + onClear) matches none of them and is geometrically untouched.
|
|
959
|
-
*
|
|
960
|
-
* SEARCH — full-width while the strip is stacked (a bounded search box on a 390px screen wastes
|
|
961
|
-
* the row), then one shared token-owned measure from the 640px step up. This single measure is
|
|
962
|
-
* what the issue was filed against: as a plain child, every page picked its own width. */
|
|
963
|
-
.ui-filter-bar-search {
|
|
964
|
-
width: 100%;
|
|
965
|
-
min-width: 0;
|
|
966
|
-
}
|
|
967
|
-
|
|
968
|
-
@media (min-width: 640px) {
|
|
969
|
-
.ui-filter-bar-search {
|
|
970
|
-
width: var(--filter-bar-search-width);
|
|
971
|
-
max-width: 100%;
|
|
972
|
-
flex: 0 0 auto;
|
|
973
|
-
}
|
|
974
|
-
}
|
|
975
|
-
|
|
976
|
-
/* CHIPS — always their own full-width line. Applied filters are a record of state, not another
|
|
977
|
-
* control in the row; wrapping them in beside the pickers makes both harder to scan. */
|
|
978
|
-
.ui-filter-bar-chips {
|
|
979
|
-
display: flex;
|
|
980
|
-
width: 100%;
|
|
981
|
-
flex-basis: 100%;
|
|
982
|
-
flex-wrap: wrap;
|
|
983
|
-
align-items: center;
|
|
984
|
-
gap: var(--filter-bar-chip-row-gap);
|
|
985
|
-
min-width: 0;
|
|
986
|
-
}
|
|
987
|
-
|
|
988
|
-
.ui-filter-bar-chip {
|
|
989
|
-
display: inline-flex;
|
|
990
|
-
max-width: 100%;
|
|
991
|
-
align-items: center;
|
|
992
|
-
gap: var(--filter-bar-chip-gap);
|
|
993
|
-
padding: var(--filter-bar-chip-padding-block) var(--filter-bar-chip-padding-inline);
|
|
994
|
-
border-radius: var(--filter-bar-chip-radius);
|
|
995
|
-
background: hsl(var(--filter-bar-chip-background, var(--muted)));
|
|
996
|
-
color: hsl(var(--filter-bar-chip-foreground, var(--muted-foreground)));
|
|
997
|
-
font-size: var(--filter-bar-chip-font-size);
|
|
998
|
-
}
|
|
999
|
-
|
|
1000
|
-
/* A long JA/VI chip value wraps inside the chip rather than pushing the row into a horizontal
|
|
1001
|
-
* scroll — the remove control must stay reachable at 390px. */
|
|
1002
|
-
.ui-filter-bar-chip-label {
|
|
1003
|
-
min-width: 0;
|
|
1004
|
-
overflow-wrap: anywhere;
|
|
1005
|
-
}
|
|
1006
|
-
|
|
1007
|
-
.ui-filter-bar-chip-remove {
|
|
1008
|
-
flex: none;
|
|
1009
|
-
}
|
|
1010
|
-
|
|
1011
|
-
.ui-filter-bar-count {
|
|
1012
|
-
color: hsl(var(--filter-bar-count-foreground, var(--muted-foreground)));
|
|
1013
|
-
font-size: var(--filter-bar-count-font-size);
|
|
1014
|
-
/* The count is a number that changes in place — tabular figures stop the row from twitching
|
|
1015
|
-
* as it goes 9 → 10 → 100. */
|
|
1016
|
-
font-variant-numeric: tabular-nums;
|
|
1017
|
-
}
|
|
1018
|
-
|
|
1019
|
-
.ui-filter-bar-actions {
|
|
1020
|
-
display: flex;
|
|
1021
|
-
width: 100%;
|
|
1022
|
-
flex-wrap: wrap;
|
|
1023
|
-
align-items: center;
|
|
1024
|
-
gap: var(--space-inline-sm);
|
|
1025
|
-
}
|
|
1026
|
-
|
|
1027
|
-
@media (min-width: 640px) {
|
|
1028
|
-
.ui-filter-bar-actions {
|
|
1029
|
-
width: auto;
|
|
1030
|
-
flex: 0 0 auto;
|
|
1031
|
-
}
|
|
1032
|
-
}
|
|
1033
|
-
|
|
1034
960
|
/* Toolbar/FilterBar `overflow="scroll"` (#216) — one bounded row that scrolls INLINE instead of
|
|
1035
961
|
* wrapping onto extra rows. Below 640px the strip still stacks (the `wrap` base rules above own
|
|
1036
962
|
* that): a 390px viewport must never hide a filter behind a horizontal scroll it cannot see.
|
|
@@ -1063,6 +989,90 @@
|
|
|
1063
989
|
z-index: 1;
|
|
1064
990
|
background: hsl(var(--filter-bar-sticky-background, var(--background)));
|
|
1065
991
|
}
|
|
992
|
+
|
|
993
|
+
/* Typed-model reset+actions cluster gets the same viewport-pinned treatment (gh#258). */
|
|
994
|
+
.ui-toolbar[data-overflow="scroll"] > .ui-filter-bar-end {
|
|
995
|
+
position: sticky;
|
|
996
|
+
inset-inline-end: 0;
|
|
997
|
+
margin-inline-start: auto;
|
|
998
|
+
flex: 0 0 auto;
|
|
999
|
+
z-index: 1;
|
|
1000
|
+
background: hsl(var(--filter-bar-sticky-background, var(--background)));
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
/* ── FilterBar typed model (gh#258) ─────────────────────────────────────────────
|
|
1005
|
+
* Canonical model layout: strip (search → filters → children → reset → actions) →
|
|
1006
|
+
* applied-chips row → result-count/error line. Geometry is entirely token-owned
|
|
1007
|
+
* (`--filter-bar-*`); stacking below 640px reuses the `.ui-toolbar` base rules, so
|
|
1008
|
+
* 1440/1024/390 behave identically to the composition form. */
|
|
1009
|
+
.ui-filter-bar {
|
|
1010
|
+
display: flex;
|
|
1011
|
+
flex-direction: column;
|
|
1012
|
+
gap: var(--filter-bar-section-gap);
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
.ui-filter-bar .ui-filter-bar-search {
|
|
1016
|
+
inline-size: 100%;
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
.ui-filter-bar-end {
|
|
1020
|
+
display: flex;
|
|
1021
|
+
flex-wrap: wrap;
|
|
1022
|
+
align-items: center;
|
|
1023
|
+
gap: var(--space-2);
|
|
1024
|
+
width: 100%;
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
/* Inside the end cluster the clear button gives up its own auto margin — the CLUSTER is what
|
|
1028
|
+
* parks at the inline end, so reset and actions stay adjacent in the keyboard/DOM order. */
|
|
1029
|
+
.ui-filter-bar-end .ui-toolbar-clear {
|
|
1030
|
+
margin-inline-start: 0;
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
.ui-filter-bar-actions {
|
|
1034
|
+
display: flex;
|
|
1035
|
+
flex-wrap: wrap;
|
|
1036
|
+
align-items: center;
|
|
1037
|
+
gap: var(--space-2);
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1040
|
+
@media (min-width: 640px) {
|
|
1041
|
+
.ui-filter-bar .ui-filter-bar-search {
|
|
1042
|
+
inline-size: min(100%, var(--filter-bar-search-width));
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
.ui-filter-bar .ui-filter-bar-filter {
|
|
1046
|
+
min-inline-size: min(100%, var(--filter-bar-filter-width));
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
.ui-filter-bar-end {
|
|
1050
|
+
width: auto;
|
|
1051
|
+
margin-inline-start: auto;
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
.ui-filter-bar-chips {
|
|
1056
|
+
display: flex;
|
|
1057
|
+
flex-wrap: wrap;
|
|
1058
|
+
align-items: center;
|
|
1059
|
+
gap: var(--filter-bar-chip-gap);
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1062
|
+
.ui-filter-bar-chip {
|
|
1063
|
+
display: inline-flex;
|
|
1064
|
+
align-items: center;
|
|
1065
|
+
gap: var(--space-1);
|
|
1066
|
+
min-width: 0;
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
.ui-filter-bar-meta {
|
|
1070
|
+
font-size: var(--filter-label-font-size);
|
|
1071
|
+
color: hsl(var(--muted-foreground));
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
.ui-filter-bar-error {
|
|
1075
|
+
color: hsl(var(--destructive));
|
|
1066
1076
|
}
|
|
1067
1077
|
|
|
1068
1078
|
/* ── LegalDocumentShell (#222) ─────────────────────────────────────────────────
|
|
@@ -343,12 +343,21 @@
|
|
|
343
343
|
.ui-auth-shell[data-variant="canonical"] .ui-form-field {
|
|
344
344
|
--field-label-gap: var(--auth-shell-field-label-gap);
|
|
345
345
|
}
|
|
346
|
+
}
|
|
346
347
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
348
|
+
/* INTENTIONALLY UNLAYERED (like density.css) — the Label primitive carries `text-sm leading-none`
|
|
349
|
+
* Tailwind utility classes, and the utilities layer is declared after `components`, so a
|
|
350
|
+
* components-layer declaration of the same properties can NEVER win regardless of specificity.
|
|
351
|
+
* That left `--auth-shell-field-label-font-size` / `--auth-shell-field-label-line-height` dead and
|
|
352
|
+
* the canonical field label rendering as a 14px/1.0 line box instead of the canonical 12px/1.5 =
|
|
353
|
+
* 18px, sitting the email input 4px high (gh#263). Unlayered author CSS out-cascades every layer;
|
|
354
|
+
* the two tokens remain the public tuning knobs. */
|
|
355
|
+
.ui-auth-shell[data-variant="canonical"] [data-slot="form-field-label"] [data-slot="label"] {
|
|
356
|
+
font-size: var(--auth-shell-field-label-font-size);
|
|
357
|
+
line-height: var(--auth-shell-field-label-line-height);
|
|
358
|
+
}
|
|
351
359
|
|
|
360
|
+
@layer components {
|
|
352
361
|
/*
|
|
353
362
|
* Compact auth card density — the two card axes are wired to SEPARATE knobs (gh#232), so a
|
|
354
363
|
* service can shorten the canonical Login card without narrowing its column (or vice versa):
|
|
@@ -384,7 +393,7 @@
|
|
|
384
393
|
gap: var(--auth-shell-divider-gap);
|
|
385
394
|
color: hsl(var(--auth-shell-divider-label-color));
|
|
386
395
|
font-size: var(--auth-shell-divider-label-font-size);
|
|
387
|
-
line-height:
|
|
396
|
+
line-height: var(--auth-shell-divider-label-line-height);
|
|
388
397
|
}
|
|
389
398
|
|
|
390
399
|
.ui-auth-divider-rule {
|
|
@@ -423,8 +432,8 @@
|
|
|
423
432
|
|
|
424
433
|
/* registration = 15px inline at 390 (card x=15, width=360 — the same page rhythm as Login, so
|
|
425
434
|
* sign-in → sign-up never jumps on a phone). The block insets tighten but the footer clearance
|
|
426
|
-
* stays deliberately larger than
|
|
427
|
-
*
|
|
435
|
+
* stays deliberately larger than a bare gutter: at 390 the form is at its tallest and the
|
|
436
|
+
* consent/legal footer must not sit flush against the submit button. */
|
|
428
437
|
.ui-auth-shell[data-preset="registration"] {
|
|
429
438
|
--auth-shell-main-padding: var(--auth-shell-registration-main-padding-block-start-mobile)
|
|
430
439
|
var(--auth-shell-registration-main-padding-inline-mobile)
|
|
@@ -186,6 +186,21 @@
|
|
|
186
186
|
padding-inline: 0;
|
|
187
187
|
}
|
|
188
188
|
|
|
189
|
+
/* Same reset, same reason, for a table sitting straight on a FLUSH page. The bleed above exists
|
|
190
|
+
* to cancel the page gutter so the scroll region reaches the page edges — but
|
|
191
|
+
* `.ui-page-container--flush .ui-page-body` zeroes that gutter, leaving nothing to bleed into.
|
|
192
|
+
* The -16px then escapes the page: nothing clips it, so the whole page gained 16px of
|
|
193
|
+
* horizontal scroll at 320/375/390 (WCAG 2.2 SC 1.4.10 Reflow). Scoped by child combinator so a
|
|
194
|
+
* table inside a Card keeps its own bleed — the card supplies the padding that one compensates. */
|
|
195
|
+
.ui-page-container--flush > .ui-page-body > .ui-data-table-root > .ui-data-table-scroll {
|
|
196
|
+
margin-inline: 0;
|
|
197
|
+
padding-inline: 0;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
.ui-page-container--flush > .ui-page-body > .ui-data-table-root > .ui-data-table-scroll::after {
|
|
201
|
+
inset-inline-end: 0;
|
|
202
|
+
}
|
|
203
|
+
|
|
189
204
|
[data-slot="card-content"][data-flush] .ui-data-table-scroll::after {
|
|
190
205
|
inset-inline-end: 0;
|
|
191
206
|
}
|
|
@@ -284,8 +299,23 @@
|
|
|
284
299
|
|
|
285
300
|
.ui-table-collection :is([data-slot="table-head"], [data-slot="table-cell"]) {
|
|
286
301
|
/* The column measure comes from `priority`; an unmarked column takes what is left (`auto`),
|
|
287
|
-
* which is the free-text column
|
|
288
|
-
|
|
302
|
+
* which is the free-text column — EXCEPT past the seven-column budget below the collapse
|
|
303
|
+
* step, where the `:has()` tier re-points the middle fallback at the flex floor (gh#262):
|
|
304
|
+
* the fixed algorithm hands an auto column 0px once the marked columns over-constrain the
|
|
305
|
+
* table, which is the one-character-per-line shredding this preset must never produce.
|
|
306
|
+
* There every column carries a rem floor-measure; once the floors outgrow the container the
|
|
307
|
+
* table's used width grows past its specified 100% (CSS 2.1 §17.5.2.1) and the DIRECT
|
|
308
|
+
* wrapper's keyboard-reachable overflow-x region scrolls — the SC 1.4.10-permitted
|
|
309
|
+
* one-dimensional scroll, instead of unreadable shredding (see tokens/components/table.css). */
|
|
310
|
+
inline-size: var(
|
|
311
|
+
--table-action-collection-column-width,
|
|
312
|
+
var(--table-action-collection-flex-width, auto)
|
|
313
|
+
);
|
|
314
|
+
/* Wrapping guard, considered for gh#262: this stays `overflow-wrap: anywhere`, NOT
|
|
315
|
+
* `word-break: keep-all`. Under `table-layout: fixed` a column cannot grow to fit an
|
|
316
|
+
* unbreakable CJK run, so keep-all would overflow/clip a long JA header instead of widening
|
|
317
|
+
* its column. With the floors guaranteeing a ~5-glyph measure, a wrapped JA header is two
|
|
318
|
+
* readable lines — never a vertical character column — and losing no text beats clipping. */
|
|
289
319
|
overflow-wrap: anywhere;
|
|
290
320
|
white-space: normal;
|
|
291
321
|
vertical-align: top;
|
|
@@ -346,6 +376,21 @@
|
|
|
346
376
|
[data-collapse-below="sm"] [data-slot="table-cell"] * {
|
|
347
377
|
white-space: normal;
|
|
348
378
|
}
|
|
379
|
+
|
|
380
|
+
/* SEVEN columns and up — the wide-collection floor tier (gh#262). Percent shares are
|
|
381
|
+
* guaranteed to sum past 100% here and fixed layout would normalize them into sub-glyph
|
|
382
|
+
* columns, so every column (the unmarked free-text one included) takes its rem floor
|
|
383
|
+
* instead; the over-constrained table grows past 100% and its wrapper scrolls. Up to six
|
|
384
|
+
* columns this rule never matches and the percent tier above keeps the canonical queues
|
|
385
|
+
* scroll-free — the preset's documented column-count ceiling. */
|
|
386
|
+
[data-collapse-below="sm"] [data-slot="table"]:has([data-slot="table-head"]:nth-child(7)) {
|
|
387
|
+
--table-action-collection-primary-width: var(--table-action-collection-primary-width-floor);
|
|
388
|
+
--table-action-collection-secondary-width: var(
|
|
389
|
+
--table-action-collection-secondary-width-floor
|
|
390
|
+
);
|
|
391
|
+
--table-action-collection-meta-width: var(--table-action-collection-meta-width-floor);
|
|
392
|
+
--table-action-collection-flex-width: var(--table-action-collection-flex-width-floor);
|
|
393
|
+
}
|
|
349
394
|
}
|
|
350
395
|
|
|
351
396
|
@container ui-table-collection (width < 48rem) {
|
|
@@ -371,6 +416,21 @@
|
|
|
371
416
|
[data-collapse-below="md"] [data-slot="table-cell"] * {
|
|
372
417
|
white-space: normal;
|
|
373
418
|
}
|
|
419
|
+
|
|
420
|
+
/* SEVEN columns and up — the wide-collection floor tier (gh#262). Percent shares are
|
|
421
|
+
* guaranteed to sum past 100% here and fixed layout would normalize them into sub-glyph
|
|
422
|
+
* columns, so every column (the unmarked free-text one included) takes its rem floor
|
|
423
|
+
* instead; the over-constrained table grows past 100% and its wrapper scrolls. Up to six
|
|
424
|
+
* columns this rule never matches and the percent tier above keeps the canonical queues
|
|
425
|
+
* scroll-free — the preset's documented column-count ceiling. */
|
|
426
|
+
[data-collapse-below="md"] [data-slot="table"]:has([data-slot="table-head"]:nth-child(7)) {
|
|
427
|
+
--table-action-collection-primary-width: var(--table-action-collection-primary-width-floor);
|
|
428
|
+
--table-action-collection-secondary-width: var(
|
|
429
|
+
--table-action-collection-secondary-width-floor
|
|
430
|
+
);
|
|
431
|
+
--table-action-collection-meta-width: var(--table-action-collection-meta-width-floor);
|
|
432
|
+
--table-action-collection-flex-width: var(--table-action-collection-flex-width-floor);
|
|
433
|
+
}
|
|
374
434
|
}
|
|
375
435
|
|
|
376
436
|
@container ui-table-collection (width < 64rem) {
|
|
@@ -396,6 +456,21 @@
|
|
|
396
456
|
[data-collapse-below="lg"] [data-slot="table-cell"] * {
|
|
397
457
|
white-space: normal;
|
|
398
458
|
}
|
|
459
|
+
|
|
460
|
+
/* SEVEN columns and up — the wide-collection floor tier (gh#262). Percent shares are
|
|
461
|
+
* guaranteed to sum past 100% here and fixed layout would normalize them into sub-glyph
|
|
462
|
+
* columns, so every column (the unmarked free-text one included) takes its rem floor
|
|
463
|
+
* instead; the over-constrained table grows past 100% and its wrapper scrolls. Up to six
|
|
464
|
+
* columns this rule never matches and the percent tier above keeps the canonical queues
|
|
465
|
+
* scroll-free — the preset's documented column-count ceiling. */
|
|
466
|
+
[data-collapse-below="lg"] [data-slot="table"]:has([data-slot="table-head"]:nth-child(7)) {
|
|
467
|
+
--table-action-collection-primary-width: var(--table-action-collection-primary-width-floor);
|
|
468
|
+
--table-action-collection-secondary-width: var(
|
|
469
|
+
--table-action-collection-secondary-width-floor
|
|
470
|
+
);
|
|
471
|
+
--table-action-collection-meta-width: var(--table-action-collection-meta-width-floor);
|
|
472
|
+
--table-action-collection-flex-width: var(--table-action-collection-flex-width-floor);
|
|
473
|
+
}
|
|
399
474
|
}
|
|
400
475
|
|
|
401
476
|
@container ui-table-collection (width < 80rem) {
|
|
@@ -421,5 +496,20 @@
|
|
|
421
496
|
[data-collapse-below="xl"] [data-slot="table-cell"] * {
|
|
422
497
|
white-space: normal;
|
|
423
498
|
}
|
|
499
|
+
|
|
500
|
+
/* SEVEN columns and up — the wide-collection floor tier (gh#262). Percent shares are
|
|
501
|
+
* guaranteed to sum past 100% here and fixed layout would normalize them into sub-glyph
|
|
502
|
+
* columns, so every column (the unmarked free-text one included) takes its rem floor
|
|
503
|
+
* instead; the over-constrained table grows past 100% and its wrapper scrolls. Up to six
|
|
504
|
+
* columns this rule never matches and the percent tier above keeps the canonical queues
|
|
505
|
+
* scroll-free — the preset's documented column-count ceiling. */
|
|
506
|
+
[data-collapse-below="xl"] [data-slot="table"]:has([data-slot="table-head"]:nth-child(7)) {
|
|
507
|
+
--table-action-collection-primary-width: var(--table-action-collection-primary-width-floor);
|
|
508
|
+
--table-action-collection-secondary-width: var(
|
|
509
|
+
--table-action-collection-secondary-width-floor
|
|
510
|
+
);
|
|
511
|
+
--table-action-collection-meta-width: var(--table-action-collection-meta-width-floor);
|
|
512
|
+
--table-action-collection-flex-width: var(--table-action-collection-flex-width-floor);
|
|
513
|
+
}
|
|
424
514
|
}
|
|
425
515
|
}
|
|
@@ -107,6 +107,19 @@
|
|
|
107
107
|
* having to add `min-w-0` — the documented flex-truncate idiom (issue #114). */
|
|
108
108
|
min-width: 0;
|
|
109
109
|
}
|
|
110
|
+
/* Multi-line clamp (`clamp` prop, issue #261) — the token-owned line-clamp so consumers never
|
|
111
|
+
* write a page-local `line-clamp-N` utility. Visual-only: the full text stays in the DOM and
|
|
112
|
+
* the accessible name. `--text-clamp` is set inline by the component from the prop value. */
|
|
113
|
+
[data-slot="text"][data-clamp] {
|
|
114
|
+
display: -webkit-box;
|
|
115
|
+
-webkit-box-orient: vertical;
|
|
116
|
+
-webkit-line-clamp: var(--text-clamp, 2);
|
|
117
|
+
line-clamp: var(--text-clamp, 2);
|
|
118
|
+
overflow: hidden;
|
|
119
|
+
/* Same flex-shrink contract as truncate (issue #114): clamps inside a flex row without
|
|
120
|
+
* the consumer adding `min-w-0`. */
|
|
121
|
+
min-width: 0;
|
|
122
|
+
}
|
|
110
123
|
[data-slot="text"][data-tabular] {
|
|
111
124
|
font-variant-numeric: tabular-nums;
|
|
112
125
|
}
|
package/dist/tokens/base.css
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
@import "./components/descriptions.css";
|
|
14
14
|
@import "./components/table.css";
|
|
15
15
|
@import "./components/feedback.css";
|
|
16
|
+
@import "./components/banner.css";
|
|
16
17
|
@import "./components/sheet.css";
|
|
17
18
|
@import "./components/badge.css";
|
|
18
19
|
@import "./components/navigation.css";
|
|
@@ -7,4 +7,9 @@
|
|
|
7
7
|
/* Small-by-design (badge/pill/counter). A knob (rule #45) so a service can
|
|
8
8
|
* re-tune badge text without touching the global --font-size-xs step. */
|
|
9
9
|
--badge-font-size: var(--font-size-xs);
|
|
10
|
+
/* Companion to --badge-font-size (gh#260). The cva's old `text-xs` utility also set
|
|
11
|
+
* line-height via Tailwind's default `--text-xs--line-height: calc(1 / 0.75)` (the theme
|
|
12
|
+
* remaps --text-xs but never that companion). Same unitless ratio here keeps the default
|
|
13
|
+
* badge pixel-identical now that badge-layout.css owns the type metrics. */
|
|
14
|
+
--badge-line-height: calc(1 / 0.75);
|
|
10
15
|
}
|
|
@@ -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
|
+
}
|
|
@@ -65,29 +65,14 @@
|
|
|
65
65
|
* (0 on an overlay-scrollbar platform). */
|
|
66
66
|
--filter-bar-scroll-padding-y: var(--space-1);
|
|
67
67
|
|
|
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;
|
|
68
|
+
/* FilterBar typed model (gh#258) — token-owned geometry so every list page gets the SAME
|
|
69
|
+
* search width, filter width, chip rhythm and section stacking without page-local CSS.
|
|
70
|
+
* All are rule-#45 knobs: a service theme retunes them once, props/className override per
|
|
71
|
+
* instance. Below 640px the strip stacks (search/filters full-width); the widths apply from
|
|
72
|
+
* the 640px breakpoint up, always clamped by min(100%, …) so a narrow container never
|
|
73
|
+
* overflows at 390px with long JA/EN/VI labels. */
|
|
74
|
+
--filter-bar-search-width: 20rem;
|
|
75
|
+
--filter-bar-filter-width: var(--filter-picker-width-md);
|
|
76
|
+
--filter-bar-chip-gap: var(--space-2);
|
|
77
|
+
--filter-bar-section-gap: var(--space-2);
|
|
93
78
|
}
|
|
@@ -183,9 +183,11 @@
|
|
|
183
183
|
--auth-shell-login-main-padding-block-end: 1rem;
|
|
184
184
|
--auth-shell-login-identity-slot-block-size: 7rem;
|
|
185
185
|
--auth-shell-login-card-stack-gap: 1.25rem;
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
186
|
+
/* Canonical SCR-001 block inset is a FLAT 24px — the same measure as the inline inset. The card
|
|
187
|
+
* draws its own 1px border and a border-box rect already contains it, so the former
|
|
188
|
+
* `+ 2 x --control-border-width` double-counted the border and pushed the passkey CTA to y=390
|
|
189
|
+
* instead of the canonical y=388 (gh#263). */
|
|
190
|
+
--auth-shell-login-card-padding-block-compact: var(--auth-shell-compact-card-inset);
|
|
189
191
|
|
|
190
192
|
/* Device-authorization preset — 380px card measure, 15px block · 5px inline mobile gutter
|
|
191
193
|
* (at a 390px viewport the card is x=5px, width=380px). */
|
|
@@ -256,14 +258,19 @@
|
|
|
256
258
|
--auth-shell-registration-main-padding-block-end-mobile: 2rem;
|
|
257
259
|
--auth-shell-registration-card-stack-gap: 1.25rem;
|
|
258
260
|
/* 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
|
-
*
|
|
261
|
+
* with the title/requester line count, so the canonical y above would hold for exactly one copy
|
|
262
|
+
* length and drift for every other. The slot absorbs absent / one-line / two-line identity
|
|
263
|
+
* content instead. */
|
|
262
264
|
--auth-shell-registration-identity-slot-block-size: 7rem;
|
|
263
265
|
|
|
264
|
-
/* Labelled auth divider geometry.
|
|
266
|
+
/* Labelled auth divider geometry. The canonical SCR-001 divider row is 19px tall at the 11px
|
|
267
|
+
* label (the artboard label inherits the page's line-height instead of collapsing to a 1.0 line
|
|
268
|
+
* box). 19/11 pins the row at exactly 19px and keeps it proportional if a service retunes the
|
|
269
|
+
* label font-size. The previous hardcoded `line-height: 1` rendered an 11px row, sitting the
|
|
270
|
+
* whole lower half of the Login card 8px high (gh#263). */
|
|
265
271
|
--auth-shell-divider-gap: 0.625rem;
|
|
266
272
|
--auth-shell-divider-label-font-size: 0.6875rem;
|
|
273
|
+
--auth-shell-divider-label-line-height: calc(19 / 11);
|
|
267
274
|
--auth-shell-divider-rule-color: var(--border);
|
|
268
275
|
--auth-shell-divider-label-color: var(--muted-foreground);
|
|
269
276
|
--auth-identity-gap: 0.375rem;
|
|
@@ -281,8 +288,12 @@
|
|
|
281
288
|
--auth-footer-text-font-size: 0.6875rem;
|
|
282
289
|
--auth-stack-gap: var(--space-3);
|
|
283
290
|
--auth-shell-field-label-gap: var(--space-1);
|
|
284
|
-
|
|
285
|
-
|
|
291
|
+
/* Canonical SCR-001 field label: a LITERAL 12px (the golden-ratio --font-size-xs ≈ 12.47px would
|
|
292
|
+
* drift the 18px line box to 18.7px and push the email input off its y=489 anchor) with a 1.5
|
|
293
|
+
* line box = 18px. The former var(--font-size-xs)/1.25 pair rendered a 14px box, sitting the
|
|
294
|
+
* email input 4px high (gh#263). */
|
|
295
|
+
--auth-shell-field-label-font-size: 0.75rem;
|
|
296
|
+
--auth-shell-field-label-line-height: 1.5;
|
|
286
297
|
|
|
287
298
|
/* CenteredShell — authenticated, no-sidebar, centred-column page shell (hosted-ID "My Page",
|
|
288
299
|
* 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);
|