@godxjp/ui 18.12.11 → 18.12.13
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/data-display/table.d.ts +17 -60
- package/dist/components/data-display/table.js +38 -93
- package/dist/components/ui/table.js +0 -1
- package/dist/props/vocabulary/data.prop.d.ts +1 -14
- package/dist/styles/shell-layout.css +24 -3
- package/dist/styles/table-layout.css +0 -348
- package/dist/tokens/components/table.css +0 -18
- package/package.json +2 -2
|
@@ -19,13 +19,11 @@ export type TableProps = React.HTMLAttributes<HTMLTableElement> & {
|
|
|
19
19
|
bordered?: boolean;
|
|
20
20
|
/**
|
|
21
21
|
* Named collection contract. `"default"` (the default) emits no attribute and keeps the plain
|
|
22
|
-
* table exactly as it is.
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* (`--table-action-collection-*`) under `table-layout: fixed`, and cells wrap instead of
|
|
28
|
-
* forcing a horizontal scroll. Mark each column with `priority` on its `TableHead`/`TableCell`.
|
|
22
|
+
* table exactly as it is. `"action-collection"` is the canonical dense approval / action queue
|
|
23
|
+
* (gh#253): below `collapseBelow`, the desktop intrinsic column widths — the thing that pushes
|
|
24
|
+
* the last columns outside a 390px viewport — are replaced by the token-owned column PRIORITY
|
|
25
|
+
* measures (`--table-action-collection-*`) under `table-layout: fixed`, and cells wrap instead
|
|
26
|
+
* of forcing a horizontal scroll. Mark each column with `priority` on its `TableHead`/`TableCell`.
|
|
29
27
|
* The table keeps its real semantics: no `display` change, no role rewriting, no card swap, so
|
|
30
28
|
* header association, `aria-sort` and screen-reader table navigation are identical at every width.
|
|
31
29
|
*
|
|
@@ -34,26 +32,12 @@ export type TableProps = React.HTMLAttributes<HTMLTableElement> & {
|
|
|
34
32
|
* its rem floor (`--table-action-collection-*-width-floor`, ~5 CJK glyphs per line) and the
|
|
35
33
|
* table intentionally scrolls inside this wrapper — SC 1.4.10 permits one-dimensional scrolling
|
|
36
34
|
* of a data table; compressing further would shred CJK headers one character per line.
|
|
37
|
-
*
|
|
38
|
-
* `"stacked-record-collection"` (gh#356) is the canonical RECORD list — a table whose columns
|
|
39
|
-
* are independent facts about ONE record (client ID · purpose · scopes · last use · status ·
|
|
40
|
-
* lifecycle actions) rather than a dense queue `action-collection` can reflow into a
|
|
41
|
-
* column-priority budget. Below `collapseBelow` each row renders as a card-like block with
|
|
42
|
-
* every column's label + value stacked vertically (a definition-list composition); row-level
|
|
43
|
-
* actions stay in document flow at the end of the card, never scrolled off-canvas. Supply the
|
|
44
|
-
* stacked-tier legend for each column with `label` on its `TableCell` (leave it unset on a
|
|
45
|
-
* self-evident column, e.g. row actions). This DOES change `display` (table family → block), so
|
|
46
|
-
* table/rowgroup/row/cell roles are re-asserted explicitly on every element that keeps
|
|
47
|
-
* rendering — see the prop doc on `TableCell`. The one element that does NOT keep rendering is
|
|
48
|
-
* the header row: below the step it is removed outright (not just visually hidden), because
|
|
49
|
-
* each `TableCell`'s own `label` becomes the field name for every modality at that tier — see
|
|
50
|
-
* `TableCellLabel`.
|
|
51
35
|
*/
|
|
52
36
|
preset?: TablePresetProp;
|
|
53
37
|
/**
|
|
54
|
-
* Step at which
|
|
55
|
-
* (not the viewport), so a table inside a rail collapses before the
|
|
56
|
-
* `"sm"` (40rem). Ignored while `preset` is `"default"`.
|
|
38
|
+
* Step at which `preset="action-collection"` switches to the priority measures, measured against
|
|
39
|
+
* the TABLE's own container (not the viewport), so a table inside a rail collapses before the
|
|
40
|
+
* page does. Defaults to `"sm"` (40rem). Ignored while `preset` is `"default"`.
|
|
57
41
|
*/
|
|
58
42
|
collapseBelow?: BreakpointProp;
|
|
59
43
|
};
|
|
@@ -76,13 +60,11 @@ export declare const Table: React.ForwardRefExoticComponent<React.HTMLAttributes
|
|
|
76
60
|
bordered?: boolean;
|
|
77
61
|
/**
|
|
78
62
|
* Named collection contract. `"default"` (the default) emits no attribute and keeps the plain
|
|
79
|
-
* table exactly as it is.
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
* (`--table-action-collection-*`) under `table-layout: fixed`, and cells wrap instead of
|
|
85
|
-
* forcing a horizontal scroll. Mark each column with `priority` on its `TableHead`/`TableCell`.
|
|
63
|
+
* table exactly as it is. `"action-collection"` is the canonical dense approval / action queue
|
|
64
|
+
* (gh#253): below `collapseBelow`, the desktop intrinsic column widths — the thing that pushes
|
|
65
|
+
* the last columns outside a 390px viewport — are replaced by the token-owned column PRIORITY
|
|
66
|
+
* measures (`--table-action-collection-*`) under `table-layout: fixed`, and cells wrap instead
|
|
67
|
+
* of forcing a horizontal scroll. Mark each column with `priority` on its `TableHead`/`TableCell`.
|
|
86
68
|
* The table keeps its real semantics: no `display` change, no role rewriting, no card swap, so
|
|
87
69
|
* header association, `aria-sort` and screen-reader table navigation are identical at every width.
|
|
88
70
|
*
|
|
@@ -91,26 +73,12 @@ export declare const Table: React.ForwardRefExoticComponent<React.HTMLAttributes
|
|
|
91
73
|
* its rem floor (`--table-action-collection-*-width-floor`, ~5 CJK glyphs per line) and the
|
|
92
74
|
* table intentionally scrolls inside this wrapper — SC 1.4.10 permits one-dimensional scrolling
|
|
93
75
|
* of a data table; compressing further would shred CJK headers one character per line.
|
|
94
|
-
*
|
|
95
|
-
* `"stacked-record-collection"` (gh#356) is the canonical RECORD list — a table whose columns
|
|
96
|
-
* are independent facts about ONE record (client ID · purpose · scopes · last use · status ·
|
|
97
|
-
* lifecycle actions) rather than a dense queue `action-collection` can reflow into a
|
|
98
|
-
* column-priority budget. Below `collapseBelow` each row renders as a card-like block with
|
|
99
|
-
* every column's label + value stacked vertically (a definition-list composition); row-level
|
|
100
|
-
* actions stay in document flow at the end of the card, never scrolled off-canvas. Supply the
|
|
101
|
-
* stacked-tier legend for each column with `label` on its `TableCell` (leave it unset on a
|
|
102
|
-
* self-evident column, e.g. row actions). This DOES change `display` (table family → block), so
|
|
103
|
-
* table/rowgroup/row/cell roles are re-asserted explicitly on every element that keeps
|
|
104
|
-
* rendering — see the prop doc on `TableCell`. The one element that does NOT keep rendering is
|
|
105
|
-
* the header row: below the step it is removed outright (not just visually hidden), because
|
|
106
|
-
* each `TableCell`'s own `label` becomes the field name for every modality at that tier — see
|
|
107
|
-
* `TableCellLabel`.
|
|
108
76
|
*/
|
|
109
77
|
preset?: TablePresetProp;
|
|
110
78
|
/**
|
|
111
|
-
* Step at which
|
|
112
|
-
* (not the viewport), so a table inside a rail collapses before the
|
|
113
|
-
* `"sm"` (40rem). Ignored while `preset` is `"default"`.
|
|
79
|
+
* Step at which `preset="action-collection"` switches to the priority measures, measured against
|
|
80
|
+
* the TABLE's own container (not the viewport), so a table inside a rail collapses before the
|
|
81
|
+
* page does. Defaults to `"sm"` (40rem). Ignored while `preset` is `"default"`.
|
|
114
82
|
*/
|
|
115
83
|
collapseBelow?: BreakpointProp;
|
|
116
84
|
} & React.RefAttributes<HTMLTableElement>>;
|
|
@@ -126,17 +94,6 @@ export declare const TableRow: React.ForwardRefExoticComponent<React.HTMLAttribu
|
|
|
126
94
|
type TableCellPriority = {
|
|
127
95
|
priority?: TableColumnPriorityProp;
|
|
128
96
|
};
|
|
129
|
-
/**
|
|
130
|
-
* Stacked-tier legend for ONE column, read only by `TableCell` under
|
|
131
|
-
* `Table preset="stacked-record-collection"`. Rendered as an inline label ahead of the cell's
|
|
132
|
-
* value, visible only below the collapse step (a wide container still shows the real `<th>`
|
|
133
|
-
* header instead, so the label stays invisible — never duplicated — above the step). Leave unset
|
|
134
|
-
* on a column whose value is self-evident without one (e.g. a row-actions cell whose buttons
|
|
135
|
-
* already carry their own text). Ignored under every other preset.
|
|
136
|
-
*/
|
|
137
|
-
type TableCellLabel = {
|
|
138
|
-
label?: React.ReactNode;
|
|
139
|
-
};
|
|
140
97
|
export declare const TableHead: React.ForwardRefExoticComponent<React.ThHTMLAttributes<HTMLTableCellElement> & TableCellPriority & React.RefAttributes<HTMLTableCellElement>>;
|
|
141
|
-
export declare const TableCell: React.ForwardRefExoticComponent<React.TdHTMLAttributes<HTMLTableCellElement> & TableCellPriority &
|
|
98
|
+
export declare const TableCell: React.ForwardRefExoticComponent<React.TdHTMLAttributes<HTMLTableCellElement> & TableCellPriority & React.RefAttributes<HTMLTableCellElement>>;
|
|
142
99
|
export {};
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
2
|
import * as React from "react";
|
|
4
3
|
import { tableHeadHeightClass } from "../../lib/control-styles.js";
|
|
5
4
|
import { cn } from "../../lib/utils.js";
|
|
6
|
-
const TablePresetContext = React.createContext("default");
|
|
7
5
|
const Table = React.forwardRef(
|
|
8
6
|
({
|
|
9
7
|
className,
|
|
@@ -25,115 +23,62 @@ const Table = React.forwardRef(
|
|
|
25
23
|
{
|
|
26
24
|
className: cn(
|
|
27
25
|
scrollable ? "relative w-full overflow-auto" : "relative w-full",
|
|
28
|
-
preset
|
|
29
|
-
preset === "stacked-record-collection" && "ui-table-stacked-collection"
|
|
26
|
+
preset !== "default" && "ui-table-collection"
|
|
30
27
|
),
|
|
31
28
|
"data-preset": preset === "default" ? void 0 : preset,
|
|
32
29
|
"data-collapse-below": preset === "default" ? void 0 : collapseBelow,
|
|
33
30
|
...scrollable ? { tabIndex: 0 } : {},
|
|
34
|
-
children: /* @__PURE__ */ jsx(
|
|
31
|
+
children: /* @__PURE__ */ jsx(
|
|
35
32
|
"table",
|
|
36
33
|
{
|
|
37
34
|
ref,
|
|
38
35
|
"data-slot": "table",
|
|
39
|
-
|
|
40
|
-
className: cn(
|
|
41
|
-
"w-full caption-bottom text-sm",
|
|
42
|
-
bordered && "ui-table-bordered",
|
|
43
|
-
className
|
|
44
|
-
),
|
|
36
|
+
className: cn("w-full caption-bottom text-sm", bordered && "ui-table-bordered", className),
|
|
45
37
|
...props
|
|
46
38
|
}
|
|
47
|
-
)
|
|
39
|
+
)
|
|
48
40
|
}
|
|
49
41
|
)
|
|
50
42
|
)
|
|
51
43
|
);
|
|
52
44
|
Table.displayName = "Table";
|
|
53
|
-
const TableHeader = React.forwardRef(({ className, ...props }, ref) => {
|
|
54
|
-
const preset = React.useContext(TablePresetContext);
|
|
55
|
-
const stacked = preset === "stacked-record-collection";
|
|
56
|
-
return /* @__PURE__ */ jsx(
|
|
57
|
-
"thead",
|
|
58
|
-
{
|
|
59
|
-
ref,
|
|
60
|
-
role: stacked ? "rowgroup" : void 0,
|
|
61
|
-
className: cn(
|
|
62
|
-
"[&_tr]:border-b",
|
|
63
|
-
// Removed below the collapse step (the stacked-tier CSS makes it display:none) — the
|
|
64
|
-
// per-cell label TableCell renders inline (real text, not aria-hidden) replaces it for
|
|
65
|
-
// every modality, so the raw header is fully redundant there, not just visually.
|
|
66
|
-
stacked && "ui-table-stacked-collection-head",
|
|
67
|
-
className
|
|
68
|
-
),
|
|
69
|
-
...props
|
|
70
|
-
}
|
|
71
|
-
);
|
|
72
|
-
});
|
|
45
|
+
const TableHeader = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("thead", { ref, className: cn("[&_tr]:border-b", className), ...props }));
|
|
73
46
|
TableHeader.displayName = "TableHeader";
|
|
74
|
-
const TableBody = React.forwardRef(({ className, ...props }, ref) => {
|
|
75
|
-
const preset = React.useContext(TablePresetContext);
|
|
76
|
-
return /* @__PURE__ */ jsx(
|
|
77
|
-
"tbody",
|
|
78
|
-
{
|
|
79
|
-
ref,
|
|
80
|
-
role: preset === "stacked-record-collection" ? "rowgroup" : void 0,
|
|
81
|
-
className: cn("[&_tr:last-child]:border-0", className),
|
|
82
|
-
...props
|
|
83
|
-
}
|
|
84
|
-
);
|
|
85
|
-
});
|
|
47
|
+
const TableBody = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("tbody", { ref, className: cn("[&_tr:last-child]:border-0", className), ...props }));
|
|
86
48
|
TableBody.displayName = "TableBody";
|
|
87
|
-
const TableRow = React.forwardRef(({ className, ...props }, ref) =>
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
...props
|
|
99
|
-
}
|
|
100
|
-
);
|
|
101
|
-
});
|
|
49
|
+
const TableRow = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
50
|
+
"tr",
|
|
51
|
+
{
|
|
52
|
+
ref,
|
|
53
|
+
className: cn(
|
|
54
|
+
"ui-table-row hover:bg-accent/70 data-[state=selected]:bg-primary/[0.06] border-b transition-colors",
|
|
55
|
+
className
|
|
56
|
+
),
|
|
57
|
+
...props
|
|
58
|
+
}
|
|
59
|
+
));
|
|
102
60
|
TableRow.displayName = "TableRow";
|
|
103
|
-
const TableHead = React.forwardRef(({ className, priority, ...props }, ref) =>
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
...props
|
|
114
|
-
}
|
|
115
|
-
);
|
|
116
|
-
});
|
|
61
|
+
const TableHead = React.forwardRef(({ className, priority, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
62
|
+
"th",
|
|
63
|
+
{
|
|
64
|
+
ref,
|
|
65
|
+
"data-slot": "table-head",
|
|
66
|
+
"data-priority": priority,
|
|
67
|
+
className: cn(tableHeadHeightClass, className),
|
|
68
|
+
...props
|
|
69
|
+
}
|
|
70
|
+
));
|
|
117
71
|
TableHead.displayName = "TableHead";
|
|
118
|
-
const TableCell = React.forwardRef(({ className, priority,
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
"
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
className: cn(className),
|
|
129
|
-
...props,
|
|
130
|
-
children: [
|
|
131
|
-
stacked && label != null ? /* @__PURE__ */ jsx("span", { className: "ui-table-stacked-collection-label", children: label }) : null,
|
|
132
|
-
children
|
|
133
|
-
]
|
|
134
|
-
}
|
|
135
|
-
);
|
|
136
|
-
});
|
|
72
|
+
const TableCell = React.forwardRef(({ className, priority, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
73
|
+
"td",
|
|
74
|
+
{
|
|
75
|
+
ref,
|
|
76
|
+
"data-slot": "table-cell",
|
|
77
|
+
"data-priority": priority,
|
|
78
|
+
className: cn(className),
|
|
79
|
+
...props
|
|
80
|
+
}
|
|
81
|
+
));
|
|
137
82
|
TableCell.displayName = "TableCell";
|
|
138
83
|
export {
|
|
139
84
|
Table,
|
|
@@ -81,21 +81,8 @@ export type StickyProp = boolean;
|
|
|
81
81
|
* the desktop intrinsic column widths are replaced by token-owned column-PRIORITY measures under
|
|
82
82
|
* `table-layout: fixed` and cells wrap, so every column — including the row actions — stays inside
|
|
83
83
|
* the initial narrow frame. The real `<table>` semantics are never rewritten.
|
|
84
|
-
*
|
|
85
|
-
* `"stacked-record-collection"` (gh#356) is the canonical RECORD list — a table whose columns
|
|
86
|
-
* cannot be reflowed into a fixed-layout budget (a scopes/status/lifecycle-action record, not a
|
|
87
|
-
* dense queue): below `collapseBelow` each row renders as a card-like block with every column's
|
|
88
|
-
* label + value stacked vertically (a definition-list composition), and row-level actions stay in
|
|
89
|
-
* document flow at the bottom of the card — never scrolled off-canvas. Unlike `action-collection`
|
|
90
|
-
* this DOES change `display` (table → block), so the preset re-asserts table semantics with
|
|
91
|
-
* explicit `role` attributes on every element that keeps rendering (browsers drop the IMPLICIT
|
|
92
|
-
* table roles once `display` leaves the table family — the standard fix, see e.g. Scott O'Hara's
|
|
93
|
-
* "breaking tables"). The header row is the one element that does NOT keep rendering below the
|
|
94
|
-
* step — it is removed outright, because each `TableCell`'s own `label` becomes the field name
|
|
95
|
-
* for every modality at that tier. Mark each column's stacked-tier legend with `label` on its
|
|
96
|
-
* `TableCell`.
|
|
97
84
|
*/
|
|
98
|
-
export type TablePresetProp = "default" | "action-collection"
|
|
85
|
+
export type TablePresetProp = "default" | "action-collection";
|
|
99
86
|
/**
|
|
100
87
|
* Relative importance of a table column, used by `preset="action-collection"` to allocate the
|
|
101
88
|
* narrow-frame measure. `"primary"` is the row's subject, `"secondary"` its object/target,
|
|
@@ -1271,7 +1271,19 @@
|
|
|
1271
1271
|
align-items: center;
|
|
1272
1272
|
gap: var(--topbar-gap);
|
|
1273
1273
|
padding-inline: var(--topbar-inset);
|
|
1274
|
-
|
|
1274
|
+
/* Horizontal-only clip (gh#291). `hidden` clipped BOTH axes with no clip-margin,
|
|
1275
|
+
* cutting the focus ring of slot controls flat at top/bottom — the bar's content
|
|
1276
|
+
* box hugs --control-height exactly, and the rails' overflow-clip-margin below
|
|
1277
|
+
* cannot help when the parent already swallowed the ring. `clip` (not `hidden`)
|
|
1278
|
+
* is what lets overflow-y stay `visible` — a `hidden`/`visible` pair computes to
|
|
1279
|
+
* `auto` and still clips. Vertically the ring paints into the shell bar's box,
|
|
1280
|
+
* which has headroom; the horizontal shrink/truncation contract is unchanged. */
|
|
1281
|
+
overflow-x: clip;
|
|
1282
|
+
overflow-y: visible;
|
|
1283
|
+
/* Ring headroom on the clipped axis: the end rail sits flush against this
|
|
1284
|
+
* box, so without a margin the LAST control's ring loses its outer edge.
|
|
1285
|
+
* 2x the ring token — open/focus rings paint up to 3px (gh#291 follow-up). */
|
|
1286
|
+
overflow-clip-margin: calc(2 * var(--focus-ring-width));
|
|
1275
1287
|
}
|
|
1276
1288
|
.ui-topbar-start,
|
|
1277
1289
|
.ui-topbar-center,
|
|
@@ -1280,8 +1292,17 @@
|
|
|
1280
1292
|
min-width: 0;
|
|
1281
1293
|
align-items: center;
|
|
1282
1294
|
gap: var(--topbar-gap);
|
|
1283
|
-
|
|
1284
|
-
|
|
1295
|
+
/* Clip horizontally only (gh#291): the rails hug --control-height, so a
|
|
1296
|
+
* vertical clip eats the focus ring even WITH the clip-margin — the margin
|
|
1297
|
+
* is 2px while e.g. the toggle ring paints 3px, and Safari does not
|
|
1298
|
+
* implement overflow-clip-margin at all. The margin still buys horizontal
|
|
1299
|
+
* ring headroom where supported. */
|
|
1300
|
+
overflow-x: clip;
|
|
1301
|
+
overflow-y: visible;
|
|
1302
|
+
/* 2x the ring token, NOT 1x: focus/open rings paint up to 3px while the
|
|
1303
|
+
* token is 2px, so a flush-edge control (the locale picker is the first
|
|
1304
|
+
* child of `end`) lost 1px of ring on the clipped axis (gh#291 follow-up). */
|
|
1305
|
+
overflow-clip-margin: calc(2 * var(--focus-ring-width));
|
|
1285
1306
|
}
|
|
1286
1307
|
.ui-topbar-start {
|
|
1287
1308
|
flex: 0 1 auto;
|
|
@@ -363,32 +363,6 @@
|
|
|
363
363
|
}
|
|
364
364
|
}
|
|
365
365
|
|
|
366
|
-
@layer components {
|
|
367
|
-
/* ── Table · `preset="stacked-record-collection"` (gh#356) ──────────────────────────────────
|
|
368
|
-
* The canonical RECORD list: client ID · purpose · scopes · last use · status · lifecycle
|
|
369
|
-
* actions — independent facts about ONE record, not a dense queue `action-collection`'s
|
|
370
|
-
* column-priority budget can reflow. Below `collapseBelow` every row becomes a card-like block
|
|
371
|
-
* and every column's label + value stack vertically (a definition-list composition), so every
|
|
372
|
-
* field — the row's lifecycle actions included — stays inside the initial narrow frame instead
|
|
373
|
-
* of requiring horizontal scroll.
|
|
374
|
-
*
|
|
375
|
-
* Unlike `action-collection` this DOES change `display` (table family → block) below the step,
|
|
376
|
-
* so table.tsx re-asserts table/rowgroup/row/columnheader/cell explicitly via `role` — browsers
|
|
377
|
-
* drop the IMPLICIT roles once an element's `display` leaves the table family. The static rules
|
|
378
|
-
* here are unqueried (apply whenever the preset is on); the display-changing, card-drawing
|
|
379
|
-
* rules live in the `godxjp-ui-responsive` layer below, same split as `action-collection`. */
|
|
380
|
-
.ui-table-stacked-collection {
|
|
381
|
-
container: ui-table-stacked-collection / inline-size;
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
/* The stacked-tier field label TableCell renders ahead of its value when `label` is supplied.
|
|
385
|
-
* Hidden above the collapse step so a wide container never shows both the real `<th>` header
|
|
386
|
-
* AND the inline label for the same column — the responsive layer below turns it back on. */
|
|
387
|
-
.ui-table-stacked-collection-label {
|
|
388
|
-
display: none;
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
|
|
392
366
|
/* The compact tier lives in `godxjp-ui-responsive` — the LAST layer, declared after Tailwind in
|
|
393
367
|
* styles/base.css — not in `@layer components`. `<table>` carries `text-sm`, a Tailwind utility,
|
|
394
368
|
* and `utilities` outranks `components` by LAYER ORDER, so a `font-size:` re-point written here as
|
|
@@ -563,325 +537,3 @@
|
|
|
563
537
|
}
|
|
564
538
|
}
|
|
565
539
|
}
|
|
566
|
-
|
|
567
|
-
/* `preset="stacked-record-collection"` compact tier (gh#356) — same layer-contract reason as
|
|
568
|
-
* `action-collection` above: `<table>` carries `text-sm`/`border-b`/`border-0`, all Tailwind
|
|
569
|
-
* utilities, and `utilities` outranks `components` by LAYER ORDER, so the display-changing card
|
|
570
|
-
* transform has to live in this LAST layer to ever win the cascade. One block per canonical step
|
|
571
|
-
* (a container query cannot read a `var()`, so the scale is written out — sm 40rem · md 48rem ·
|
|
572
|
-
* lg 64rem · xl 80rem, the same steps `action-collection` and `--master-detail-collapse-below`
|
|
573
|
-
* use). See styles/base.css · THE LAYER CONTRACT. */
|
|
574
|
-
@layer godxjp-ui-responsive {
|
|
575
|
-
@container ui-table-stacked-collection (width < 40rem) {
|
|
576
|
-
[data-collapse-below="sm"] [data-slot="table"] {
|
|
577
|
-
display: block;
|
|
578
|
-
}
|
|
579
|
-
|
|
580
|
-
/* The header is fully removed below the step — see the rule's own comment for why
|
|
581
|
-
* `display: none` (not a sr-only clip) is the right call here. */
|
|
582
|
-
[data-collapse-below="sm"] .ui-table-stacked-collection-head {
|
|
583
|
-
/* `display: none` (not a visually-hidden clip) removes the header from BOTH the paint
|
|
584
|
-
* tree and the accessibility tree below the step — deliberate: TableCell's stacked-tier
|
|
585
|
-
* label (rendered as real, non-aria-hidden text) is what carries the field name to every
|
|
586
|
-
* modality at this tier, sighted and AT alike, so the raw `<th>` is fully redundant here,
|
|
587
|
-
* not just visually. */
|
|
588
|
-
display: none;
|
|
589
|
-
}
|
|
590
|
-
|
|
591
|
-
[data-collapse-below="sm"] tbody {
|
|
592
|
-
display: block;
|
|
593
|
-
}
|
|
594
|
-
|
|
595
|
-
/* Card shell. `border`/`background` here are the SHORTHAND form, which beats the individual
|
|
596
|
-
* `border-bottom-width` / `background-color` Tailwind utilities TableRow also carries — layer
|
|
597
|
-
* order decides that, not specificity (this layer is declared after `utilities`). */
|
|
598
|
-
[data-collapse-below="sm"] .ui-table-row {
|
|
599
|
-
display: block;
|
|
600
|
-
/* `.ui-table-row` carries a FIXED `height: var(--table-row-height)` from
|
|
601
|
-
* control.css (an earlier layer, but that only matters for a property BOTH
|
|
602
|
-
* layers declare — this preset never touches `height` anywhere else, so without
|
|
603
|
-
* this reset the fixed row height survives untouched and every stacked field
|
|
604
|
-
* below the first overflows the ~34px box, visually overlapping the next card).
|
|
605
|
-
* `auto` lets the card grow to fit its stacked fields. */
|
|
606
|
-
height: auto;
|
|
607
|
-
border: 1px solid
|
|
608
|
-
var(--table-stacked-record-collection-card-border-color, hsl(var(--border)));
|
|
609
|
-
border-radius: var(--table-stacked-record-collection-card-radius);
|
|
610
|
-
background: var(
|
|
611
|
-
--table-stacked-record-collection-card-background,
|
|
612
|
-
hsl(var(--card, var(--background)))
|
|
613
|
-
);
|
|
614
|
-
padding: var(--table-stacked-record-collection-card-padding);
|
|
615
|
-
}
|
|
616
|
-
|
|
617
|
-
[data-collapse-below="sm"] .ui-table-row + .ui-table-row {
|
|
618
|
-
margin-block-start: var(--table-stacked-record-collection-card-gap);
|
|
619
|
-
}
|
|
620
|
-
|
|
621
|
-
/* Each column becomes its own block inside the card. Consistent vertical rhythm (the
|
|
622
|
-
* field-gap padding below) separates fields — no rule between them, matching the
|
|
623
|
-
* canonical's plain definition-list composition. */
|
|
624
|
-
[data-collapse-below="sm"] [data-slot="table-cell"] {
|
|
625
|
-
display: block;
|
|
626
|
-
padding-block: var(--table-stacked-record-collection-field-gap);
|
|
627
|
-
white-space: normal;
|
|
628
|
-
overflow-wrap: anywhere;
|
|
629
|
-
}
|
|
630
|
-
|
|
631
|
-
[data-collapse-below="sm"] [data-slot="table-cell"]:first-child {
|
|
632
|
-
padding-block-start: 0;
|
|
633
|
-
}
|
|
634
|
-
|
|
635
|
-
[data-collapse-below="sm"] [data-slot="table-cell"]:last-child {
|
|
636
|
-
padding-block-end: 0;
|
|
637
|
-
}
|
|
638
|
-
|
|
639
|
-
/* A nowrap child (a Badge pill) would otherwise clip inside the narrow card. */
|
|
640
|
-
[data-collapse-below="sm"] [data-slot="table-cell"] * {
|
|
641
|
-
white-space: normal;
|
|
642
|
-
}
|
|
643
|
-
|
|
644
|
-
[data-collapse-below="sm"] .ui-table-stacked-collection-label {
|
|
645
|
-
display: block;
|
|
646
|
-
font-size: var(--table-stacked-record-collection-label-font-size);
|
|
647
|
-
color: var(--table-stacked-record-collection-label-color, hsl(var(--muted-foreground)));
|
|
648
|
-
margin-block-end: var(--table-stacked-record-collection-label-gap);
|
|
649
|
-
}
|
|
650
|
-
|
|
651
|
-
/* Lifecycle actions (`priority="actions"`) span the card edge-to-edge and split evenly —
|
|
652
|
-
* the canonical's full-width button pair — instead of the compact right-aligned desktop
|
|
653
|
-
* pair. Targets any actionable element inside the cell regardless of nesting, so it
|
|
654
|
-
* still applies through a `Flex` wrapper. */
|
|
655
|
-
[data-collapse-below="sm"] [data-slot="table-cell"][data-priority="actions"] :is(button, a) {
|
|
656
|
-
flex: 1 1 0%;
|
|
657
|
-
}
|
|
658
|
-
}
|
|
659
|
-
|
|
660
|
-
@container ui-table-stacked-collection (width < 48rem) {
|
|
661
|
-
[data-collapse-below="md"] [data-slot="table"] {
|
|
662
|
-
display: block;
|
|
663
|
-
}
|
|
664
|
-
|
|
665
|
-
[data-collapse-below="md"] .ui-table-stacked-collection-head {
|
|
666
|
-
/* `display: none` (not a visually-hidden clip) removes the header from BOTH the paint
|
|
667
|
-
* tree and the accessibility tree below the step — deliberate: TableCell's stacked-tier
|
|
668
|
-
* label (rendered as real, non-aria-hidden text) is what carries the field name to every
|
|
669
|
-
* modality at this tier, sighted and AT alike, so the raw `<th>` is fully redundant here,
|
|
670
|
-
* not just visually. */
|
|
671
|
-
display: none;
|
|
672
|
-
}
|
|
673
|
-
|
|
674
|
-
[data-collapse-below="md"] tbody {
|
|
675
|
-
display: block;
|
|
676
|
-
}
|
|
677
|
-
|
|
678
|
-
[data-collapse-below="md"] .ui-table-row {
|
|
679
|
-
display: block;
|
|
680
|
-
/* `.ui-table-row` carries a FIXED `height: var(--table-row-height)` from
|
|
681
|
-
* control.css (an earlier layer, but that only matters for a property BOTH
|
|
682
|
-
* layers declare — this preset never touches `height` anywhere else, so without
|
|
683
|
-
* this reset the fixed row height survives untouched and every stacked field
|
|
684
|
-
* below the first overflows the ~34px box, visually overlapping the next card).
|
|
685
|
-
* `auto` lets the card grow to fit its stacked fields. */
|
|
686
|
-
height: auto;
|
|
687
|
-
border: 1px solid
|
|
688
|
-
var(--table-stacked-record-collection-card-border-color, hsl(var(--border)));
|
|
689
|
-
border-radius: var(--table-stacked-record-collection-card-radius);
|
|
690
|
-
background: var(
|
|
691
|
-
--table-stacked-record-collection-card-background,
|
|
692
|
-
hsl(var(--card, var(--background)))
|
|
693
|
-
);
|
|
694
|
-
padding: var(--table-stacked-record-collection-card-padding);
|
|
695
|
-
}
|
|
696
|
-
|
|
697
|
-
[data-collapse-below="md"] .ui-table-row + .ui-table-row {
|
|
698
|
-
margin-block-start: var(--table-stacked-record-collection-card-gap);
|
|
699
|
-
}
|
|
700
|
-
|
|
701
|
-
[data-collapse-below="md"] [data-slot="table-cell"] {
|
|
702
|
-
display: block;
|
|
703
|
-
padding-block: var(--table-stacked-record-collection-field-gap);
|
|
704
|
-
white-space: normal;
|
|
705
|
-
overflow-wrap: anywhere;
|
|
706
|
-
}
|
|
707
|
-
|
|
708
|
-
[data-collapse-below="md"] [data-slot="table-cell"]:first-child {
|
|
709
|
-
padding-block-start: 0;
|
|
710
|
-
}
|
|
711
|
-
|
|
712
|
-
[data-collapse-below="md"] [data-slot="table-cell"]:last-child {
|
|
713
|
-
padding-block-end: 0;
|
|
714
|
-
}
|
|
715
|
-
|
|
716
|
-
[data-collapse-below="md"] [data-slot="table-cell"] * {
|
|
717
|
-
white-space: normal;
|
|
718
|
-
}
|
|
719
|
-
|
|
720
|
-
[data-collapse-below="md"] .ui-table-stacked-collection-label {
|
|
721
|
-
display: block;
|
|
722
|
-
font-size: var(--table-stacked-record-collection-label-font-size);
|
|
723
|
-
color: var(--table-stacked-record-collection-label-color, hsl(var(--muted-foreground)));
|
|
724
|
-
margin-block-end: var(--table-stacked-record-collection-label-gap);
|
|
725
|
-
}
|
|
726
|
-
|
|
727
|
-
/* Lifecycle actions (`priority="actions"`) span the card edge-to-edge and split evenly —
|
|
728
|
-
* the canonical's full-width button pair — instead of the compact right-aligned desktop
|
|
729
|
-
* pair. Targets any actionable element inside the cell regardless of nesting, so it
|
|
730
|
-
* still applies through a `Flex` wrapper. */
|
|
731
|
-
[data-collapse-below="md"] [data-slot="table-cell"][data-priority="actions"] :is(button, a) {
|
|
732
|
-
flex: 1 1 0%;
|
|
733
|
-
}
|
|
734
|
-
}
|
|
735
|
-
|
|
736
|
-
@container ui-table-stacked-collection (width < 64rem) {
|
|
737
|
-
[data-collapse-below="lg"] [data-slot="table"] {
|
|
738
|
-
display: block;
|
|
739
|
-
}
|
|
740
|
-
|
|
741
|
-
[data-collapse-below="lg"] .ui-table-stacked-collection-head {
|
|
742
|
-
/* `display: none` (not a visually-hidden clip) removes the header from BOTH the paint
|
|
743
|
-
* tree and the accessibility tree below the step — deliberate: TableCell's stacked-tier
|
|
744
|
-
* label (rendered as real, non-aria-hidden text) is what carries the field name to every
|
|
745
|
-
* modality at this tier, sighted and AT alike, so the raw `<th>` is fully redundant here,
|
|
746
|
-
* not just visually. */
|
|
747
|
-
display: none;
|
|
748
|
-
}
|
|
749
|
-
|
|
750
|
-
[data-collapse-below="lg"] tbody {
|
|
751
|
-
display: block;
|
|
752
|
-
}
|
|
753
|
-
|
|
754
|
-
[data-collapse-below="lg"] .ui-table-row {
|
|
755
|
-
display: block;
|
|
756
|
-
/* `.ui-table-row` carries a FIXED `height: var(--table-row-height)` from
|
|
757
|
-
* control.css (an earlier layer, but that only matters for a property BOTH
|
|
758
|
-
* layers declare — this preset never touches `height` anywhere else, so without
|
|
759
|
-
* this reset the fixed row height survives untouched and every stacked field
|
|
760
|
-
* below the first overflows the ~34px box, visually overlapping the next card).
|
|
761
|
-
* `auto` lets the card grow to fit its stacked fields. */
|
|
762
|
-
height: auto;
|
|
763
|
-
border: 1px solid
|
|
764
|
-
var(--table-stacked-record-collection-card-border-color, hsl(var(--border)));
|
|
765
|
-
border-radius: var(--table-stacked-record-collection-card-radius);
|
|
766
|
-
background: var(
|
|
767
|
-
--table-stacked-record-collection-card-background,
|
|
768
|
-
hsl(var(--card, var(--background)))
|
|
769
|
-
);
|
|
770
|
-
padding: var(--table-stacked-record-collection-card-padding);
|
|
771
|
-
}
|
|
772
|
-
|
|
773
|
-
[data-collapse-below="lg"] .ui-table-row + .ui-table-row {
|
|
774
|
-
margin-block-start: var(--table-stacked-record-collection-card-gap);
|
|
775
|
-
}
|
|
776
|
-
|
|
777
|
-
[data-collapse-below="lg"] [data-slot="table-cell"] {
|
|
778
|
-
display: block;
|
|
779
|
-
padding-block: var(--table-stacked-record-collection-field-gap);
|
|
780
|
-
white-space: normal;
|
|
781
|
-
overflow-wrap: anywhere;
|
|
782
|
-
}
|
|
783
|
-
|
|
784
|
-
[data-collapse-below="lg"] [data-slot="table-cell"]:first-child {
|
|
785
|
-
padding-block-start: 0;
|
|
786
|
-
}
|
|
787
|
-
|
|
788
|
-
[data-collapse-below="lg"] [data-slot="table-cell"]:last-child {
|
|
789
|
-
padding-block-end: 0;
|
|
790
|
-
}
|
|
791
|
-
|
|
792
|
-
[data-collapse-below="lg"] [data-slot="table-cell"] * {
|
|
793
|
-
white-space: normal;
|
|
794
|
-
}
|
|
795
|
-
|
|
796
|
-
[data-collapse-below="lg"] .ui-table-stacked-collection-label {
|
|
797
|
-
display: block;
|
|
798
|
-
font-size: var(--table-stacked-record-collection-label-font-size);
|
|
799
|
-
color: var(--table-stacked-record-collection-label-color, hsl(var(--muted-foreground)));
|
|
800
|
-
margin-block-end: var(--table-stacked-record-collection-label-gap);
|
|
801
|
-
}
|
|
802
|
-
|
|
803
|
-
/* Lifecycle actions (`priority="actions"`) span the card edge-to-edge and split evenly —
|
|
804
|
-
* the canonical's full-width button pair — instead of the compact right-aligned desktop
|
|
805
|
-
* pair. Targets any actionable element inside the cell regardless of nesting, so it
|
|
806
|
-
* still applies through a `Flex` wrapper. */
|
|
807
|
-
[data-collapse-below="lg"] [data-slot="table-cell"][data-priority="actions"] :is(button, a) {
|
|
808
|
-
flex: 1 1 0%;
|
|
809
|
-
}
|
|
810
|
-
}
|
|
811
|
-
|
|
812
|
-
@container ui-table-stacked-collection (width < 80rem) {
|
|
813
|
-
[data-collapse-below="xl"] [data-slot="table"] {
|
|
814
|
-
display: block;
|
|
815
|
-
}
|
|
816
|
-
|
|
817
|
-
[data-collapse-below="xl"] .ui-table-stacked-collection-head {
|
|
818
|
-
/* `display: none` (not a visually-hidden clip) removes the header from BOTH the paint
|
|
819
|
-
* tree and the accessibility tree below the step — deliberate: TableCell's stacked-tier
|
|
820
|
-
* label (rendered as real, non-aria-hidden text) is what carries the field name to every
|
|
821
|
-
* modality at this tier, sighted and AT alike, so the raw `<th>` is fully redundant here,
|
|
822
|
-
* not just visually. */
|
|
823
|
-
display: none;
|
|
824
|
-
}
|
|
825
|
-
|
|
826
|
-
[data-collapse-below="xl"] tbody {
|
|
827
|
-
display: block;
|
|
828
|
-
}
|
|
829
|
-
|
|
830
|
-
[data-collapse-below="xl"] .ui-table-row {
|
|
831
|
-
display: block;
|
|
832
|
-
/* `.ui-table-row` carries a FIXED `height: var(--table-row-height)` from
|
|
833
|
-
* control.css (an earlier layer, but that only matters for a property BOTH
|
|
834
|
-
* layers declare — this preset never touches `height` anywhere else, so without
|
|
835
|
-
* this reset the fixed row height survives untouched and every stacked field
|
|
836
|
-
* below the first overflows the ~34px box, visually overlapping the next card).
|
|
837
|
-
* `auto` lets the card grow to fit its stacked fields. */
|
|
838
|
-
height: auto;
|
|
839
|
-
border: 1px solid
|
|
840
|
-
var(--table-stacked-record-collection-card-border-color, hsl(var(--border)));
|
|
841
|
-
border-radius: var(--table-stacked-record-collection-card-radius);
|
|
842
|
-
background: var(
|
|
843
|
-
--table-stacked-record-collection-card-background,
|
|
844
|
-
hsl(var(--card, var(--background)))
|
|
845
|
-
);
|
|
846
|
-
padding: var(--table-stacked-record-collection-card-padding);
|
|
847
|
-
}
|
|
848
|
-
|
|
849
|
-
[data-collapse-below="xl"] .ui-table-row + .ui-table-row {
|
|
850
|
-
margin-block-start: var(--table-stacked-record-collection-card-gap);
|
|
851
|
-
}
|
|
852
|
-
|
|
853
|
-
[data-collapse-below="xl"] [data-slot="table-cell"] {
|
|
854
|
-
display: block;
|
|
855
|
-
padding-block: var(--table-stacked-record-collection-field-gap);
|
|
856
|
-
white-space: normal;
|
|
857
|
-
overflow-wrap: anywhere;
|
|
858
|
-
}
|
|
859
|
-
|
|
860
|
-
[data-collapse-below="xl"] [data-slot="table-cell"]:first-child {
|
|
861
|
-
padding-block-start: 0;
|
|
862
|
-
}
|
|
863
|
-
|
|
864
|
-
[data-collapse-below="xl"] [data-slot="table-cell"]:last-child {
|
|
865
|
-
padding-block-end: 0;
|
|
866
|
-
}
|
|
867
|
-
|
|
868
|
-
[data-collapse-below="xl"] [data-slot="table-cell"] * {
|
|
869
|
-
white-space: normal;
|
|
870
|
-
}
|
|
871
|
-
|
|
872
|
-
[data-collapse-below="xl"] .ui-table-stacked-collection-label {
|
|
873
|
-
display: block;
|
|
874
|
-
font-size: var(--table-stacked-record-collection-label-font-size);
|
|
875
|
-
color: var(--table-stacked-record-collection-label-color, hsl(var(--muted-foreground)));
|
|
876
|
-
margin-block-end: var(--table-stacked-record-collection-label-gap);
|
|
877
|
-
}
|
|
878
|
-
|
|
879
|
-
/* Lifecycle actions (`priority="actions"`) span the card edge-to-edge and split evenly —
|
|
880
|
-
* the canonical's full-width button pair — instead of the compact right-aligned desktop
|
|
881
|
-
* pair. Targets any actionable element inside the cell regardless of nesting, so it
|
|
882
|
-
* still applies through a `Flex` wrapper. */
|
|
883
|
-
[data-collapse-below="xl"] [data-slot="table-cell"][data-priority="actions"] :is(button, a) {
|
|
884
|
-
flex: 1 1 0%;
|
|
885
|
-
}
|
|
886
|
-
}
|
|
887
|
-
}
|
|
@@ -136,21 +136,3 @@
|
|
|
136
136
|
* Japanese at the compact type tier) and the table scrolls instead of crushing. */
|
|
137
137
|
--table-action-collection-min-inline-size-compact: 0;
|
|
138
138
|
}
|
|
139
|
-
|
|
140
|
-
/* Table · stacked-record-collection preset (gh#356) — the canonical RECORD list: below the
|
|
141
|
-
* collapse step each row becomes a card and every column's label + value stack vertically. Every
|
|
142
|
-
* measure here is themeable so a service can retint/respace the cards without forking the
|
|
143
|
-
* component (rule #45). Colour/background tokens are `initial` so the default re-resolves the
|
|
144
|
-
* LIVE role at the call site (a :root binding would freeze a scoped [data-tenant] override —
|
|
145
|
-
* docs/TOKENS.md). */
|
|
146
|
-
:root {
|
|
147
|
-
--table-stacked-record-collection-card-gap: var(--space-stack-sm);
|
|
148
|
-
--table-stacked-record-collection-card-padding: var(--space-4);
|
|
149
|
-
--table-stacked-record-collection-card-radius: var(--card-radius);
|
|
150
|
-
--table-stacked-record-collection-card-border-color: initial; /* default = hsl(var(--border)) */
|
|
151
|
-
--table-stacked-record-collection-card-background: initial; /* default = hsl(var(--card, var(--background))) */
|
|
152
|
-
--table-stacked-record-collection-field-gap: var(--space-2);
|
|
153
|
-
--table-stacked-record-collection-label-gap: var(--space-1);
|
|
154
|
-
--table-stacked-record-collection-label-font-size: var(--font-size-xs);
|
|
155
|
-
--table-stacked-record-collection-label-color: initial; /* default = hsl(var(--muted-foreground)) */
|
|
156
|
-
}
|