Files
Andreas Reinhold / reiniandClaude Opus 5 7d3abdd506 Keep a list row's fill under its state layer
Plan step 36 review of 9ff5a7a8. The rewrite dropped the unlayered
selected rule into material.components beside the segmented fill and the
row tint, so on equal or greater weight a selected item in a segmented
list drew surface instead of secondary-container, and hovering, pressing
or focusing any selected row (or a table's selected row) swapped its
fill for a translucent tint. Each fill now names itself
--md-list-row-fill, and the row's layer is its ink mixed over that fill
at the state tokens, which is also C-08's second suggested fix.

A disabled item inks the whole row at the disabled-content token, as the
old root colour did, so the check, the leading slot and the end slot dim
with the text; the three-line padding is a literal 12px like alert.css;
list-rows.js named list.css.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
2026-09-14 22:00:03 +02:00

94 lines
3.9 KiB
CSS

/*
* Data tables: `<x-table>` (resources/views/components/table.blade.php), whose callers write plain
* `<thead>`, `<tr>`, `<th>` and `<td>` inside it.
*
* So the styling is descendant selectors on the one attribute the component sets, `data-md-table`,
* with every cell and row selector inside `:where()`: a caller's alignment or wrapping on a cell
* always wins, whatever layer it comes from. Header cells in title-small on-surface-variant over an
* outline-variant rule, body cells in body-medium between outline-variant rules — the role itself,
* never a fraction of it, since M3 reserves opacity for state layers and disabled. A selected row
* (`aria-selected="true"`) is secondary-container. A row that opens something is `data-md-list-row`
* and answers a pointer as a list row does (components/list-item.css, shared with `<x-card>` and
* `<x-list-item>`); a selected one names its fill `--md-list-row-fill`, so that state layer is laid
* over the secondary-container rather than in place of it.
*
* A row is 52px: 16px above and below a body-medium line, 12px beside each cell. Density is never
* applied by itself — "don't apply density by default; offer an explicit density opt-in instead,
* keeping opt-out targets at >= 48x48 CSS px" (docs/reference/m3/foundations-supplement.md
* § Accessibility) — so `dense` (`data-md-dense`) is the caller's decision, and it is the caller's
* to justify: a dense row is 36px (8px above and below). `data-md-size="xs"`, for a table inside a
* panel inside a panel, is body-small with label-medium headers, 8px around each cell (32px rows),
* and 4px above and below when dense (24px).
*/
@layer material.reset, material.tokens, material.base, material.layout, material.components, material.text, material.visibility;
@import './list-item.css';
@layer material.components {
/* `position: relative` makes the table the containing block for anything absolute inside it —
a visually hidden header label, a tooltip. Without it they escape the scroll box and widen a
phone's layout viewport. */
[data-md-table] {
--cell-x: 12px;
--cell-y: var(--md-sys-measurement-space200);
position: relative;
width: 100%;
border-collapse: collapse;
color: var(--md-sys-color-on-surface);
font: var(--md-sys-typescale-body-md);
letter-spacing: var(--md-sys-typescale-body-md-tracking);
}
[data-md-table][data-md-size='xs'] {
--cell-x: var(--md-sys-measurement-space100);
--cell-y: var(--md-sys-measurement-space100);
font: var(--md-sys-typescale-body-sm);
letter-spacing: var(--md-sys-typescale-body-sm-tracking);
}
[data-md-table][data-md-dense] {
--cell-y: var(--md-sys-measurement-space100);
}
[data-md-table][data-md-size='xs'][data-md-dense] {
--cell-y: var(--md-sys-measurement-space50);
}
[data-md-table] :where(th, td) {
padding: var(--cell-y) var(--cell-x);
text-align: start;
vertical-align: middle;
}
[data-md-table] :where(thead th) {
color: var(--md-sys-color-on-surface-variant);
font: var(--md-sys-typescale-title-sm);
letter-spacing: var(--md-sys-typescale-title-sm-tracking);
white-space: nowrap;
border-bottom: 1px solid var(--md-sys-color-outline-variant);
}
[data-md-table][data-md-size='xs'] :where(thead th) {
font: var(--md-sys-typescale-label-md);
letter-spacing: var(--md-sys-typescale-label-md-tracking);
}
[data-md-table] :where(tbody tr) {
border-bottom: 1px solid var(--md-sys-color-outline-variant);
}
[data-md-table] :where(tbody tr:last-child) {
border-bottom: 0;
}
[data-md-table] :where(tbody tr[aria-selected='true']) {
--md-list-row-fill: var(--md-sys-color-secondary-container);
background-color: var(--md-list-row-fill);
color: var(--md-sys-color-on-secondary-container);
}
}