feat(maestro): fill the row for the session in the pane
ci / web (push) Successful in 34s
ci / flake (push) Successful in 2m51s
ci / rust (push) Successful in 6m54s

The web list still said "open in the focused pane" with a 1px ring, the last
edge left in it, and the TUI said it with the ● glyph alone. Both now use a
background.

Web: `--accent-fill`, the same 30% recipe `--preview-tint` uses, so the two
tiers differ by hue rather than by strength. The row rules are also rewritten
as one ordered run of equal-specificity `:where()` selectors, which is what
`docs/SIDEBAR.md` claims the ladder is — `.is-open` moves in from the bottom
of the multi-view block, where source order had been deciding its precedence
by accident.

TUI: `palette.pane_row_bg()`, blended partway from the card surface to the
selection surface, so the sidebar reads unfilled / half filled / filled. It
borrows the selection surface's foregrounds, since those are the ones picked
for a filled row, and the cursor still wins on its own row. Blended rather
than shipped as a third `Surface` — that would be eight more colours in each
of seventeen presets — with palette tests asserting it stays a visible step
from both surfaces and stays legible in every preset.
This commit is contained in:
Miguel Palhas
2026-09-03 15:31:44 +01:00
parent 46a000aa68
commit f37ff681ea
7 changed files with 310 additions and 62 deletions
+31 -40
View File
@@ -101,9 +101,11 @@
oklch(0.99 0.005 var(--preview-h)),
oklch(0.19 0.045 var(--preview-h))
);
/* Opaque, not a wash: the previewed row reads as a fill, and a fill has to
land on the same colour whatever tier the row was already painted. */
/* Opaque, not a wash: session rows read as fills, and a fill has to land on
the same colour whatever tier the row was already painted. `--accent-fill`
is the same recipe on the accent, so the two tiers differ by hue alone. */
--preview-tint: color-mix(in oklab, var(--preview) 30%, var(--surface-2));
--accent-fill: color-mix(in oklab, var(--accent) 30%, var(--surface-2));
--preview-ring: light-dark(
oklch(0.55 0.16 var(--preview-h) / 0.5),
oklch(0.78 0.14 var(--preview-h) / 0.6)
@@ -1148,38 +1150,35 @@ textarea {
transition: box-shadow var(--dur-fast) var(--ease-out);
}
/* "Alive" reads as a faint wash on the row itself — no per-row status icon. */
.tree-leaf[data-status="running"] {
/* Session-row tiers (docs/SIDEBAR.md). A row is usually several of these at
once, so every qualifier below sits in `:where()`: each rule is worth the
same specificity and the ladder is decided purely by the order they appear
in, latest wins. Add a tier where it belongs in that order, not by piling on
another class to out-weigh the rule above it. Each tier paints a background
and nothing else — the list says all of this with fill, never an edge. */
/* 1. Alive. A faint wash on the row itself — no per-row status icon. */
.tree-leaf:where([data-status="running"]) {
background: color-mix(in oklab, var(--accent) 6%, transparent);
}
/* Hovering a row is what previews it (docs/PREVIEW.md), so hover reads in the
preview hue — never the accent, which belongs to the row actually open. */
.tree-leaf:hover {
/* 2. Under the pointer, or under the keyboard walk. Both are what previews a
row (docs/PREVIEW.md), so both read in the preview hue — never the accent,
which belongs to the row actually open. */
.tree-leaf:where(:hover, .is-highlighted) {
background: color-mix(in oklab, var(--preview) 12%, var(--surface-2));
}
.tree-leaf[data-status="running"]:hover {
.tree-leaf:where([data-status="running"]):where(:hover, .is-highlighted) {
background: color-mix(in oklab, var(--preview) 18%, var(--surface-2));
}
.tree-leaf:focus-visible {
.tree-leaf:where(:focus-visible) {
outline: none;
background: color-mix(in oklab, var(--accent) 16%, var(--surface-2));
}
/* Where the keyboard walk (j/k) is standing. On a session row the cursor is
also what previews it, so it reads exactly like a hover — the preview hue,
deepening to the full fill once the preview lands. A folder row previews
nothing, so it keeps the plain cursor ring. */
.tree-leaf.is-highlighted {
background: color-mix(in oklab, var(--preview) 12%, var(--surface-2));
}
.tree-leaf.is-highlighted[data-status="running"] {
background: color-mix(in oklab, var(--preview) 18%, var(--surface-2));
}
/* A folder row previews nothing, so its cursor stays a ring. */
.tree-folder-header.is-highlighted {
box-shadow: inset 0 0 0 2px var(--accent-ring);
}
@@ -1188,25 +1187,24 @@ textarea {
outline: none;
}
/* The session currently mounted in the content pane. */
.tree-leaf.is-active,
.tree-leaf.is-active[data-status="running"] {
background: var(--accent-tint);
box-shadow: inset 0 0 0 1px var(--accent-ring);
/* 3. Open in some pane, but not the focused one (issue #33). */
.tree-leaf:where(.is-open) {
background: color-mix(in oklab, var(--accent) 6%, transparent);
}
/* 4. The session currently mounted in the content pane. */
.tree-leaf:where(.is-active) {
background: var(--accent-fill);
}
.tree-leaf.is-active .leaf-name {
color: var(--ink);
}
/* The row the content pane is previewing right now — after `.is-active` so a
preview of an already-open session still reads as provisional. */
.tree-leaf.is-previewing,
.tree-leaf.is-previewing[data-status="running"],
.tree-leaf.is-previewing.is-active,
.tree-leaf.is-previewing.is-highlighted {
/* 5. The row the content pane is previewing right now. Last, so previewing a
session that is already open still reads as provisional. */
.tree-leaf:where(.is-previewing) {
background: var(--preview-tint);
box-shadow: none;
}
/* Exited sessions recede: dimmed name + an "exited" badge carry status, so it's
@@ -3178,13 +3176,6 @@ input.leaf-rename:focus {
border-radius: var(--r-1);
}
/* sidebar two-tier highlight (issue #33).
.is-active = focused pane (loud, from existing rule); .is-open = open
elsewhere (quiet). */
.tree-leaf.is-open {
background: color-mix(in oklab, var(--accent) 6%, transparent);
}
/* =========================================================================
multi-view mobile (#35): below 860px only the focused pane is shown — no tab
bar, no pane switcher; the sidebar drawer (☰) is the navigation.