The previous model made the dotted rectangle the de-facto focus signal: the
cursor row got ONLY dots (and only in the active pane), so an unfocused pane's
cursor row disappeared entirely, and selection strength was the only band
difference. Wrong way around for a commander UI.
Now (matching Win7 Explorer / the commander convention):
- tr.highlighted = "selected via Space" OR "cursor row" — the template ORs
them, so the cursor row always carries the selection band in BOTH panes.
- Pane focus is what changes the band: strong Aero band (--w7-el-grad-h) in
the focused pane, 7.css's own faint inactive wash in the unfocused pane —
that wash IS Win7's inactive-selection colour, faint by design.
- The dotted rect is demoted to what it was in Win7: a keyboard-focus marker
layered ON TOP of the band, focused pane only. It is no longer the thing
that tells you which pane is active.
Harness now renders a focused and an unfocused pane stacked, with selected
rows and a cursor row in each; verified zoomed in light and dark.
Co-Authored-By: Claude <noreply@anthropic.com>
You were right that selecting a line looked off. Three separate problems, two
of them introduced by the Stage 2 dark-mode block:
1. The selection band was ERASED in dark mode. Stage 2 restated the dark
surface on `table > tbody > tr > *`, i.e. on the CELLS — but 7.css paints
tr.highlighted on the ROW, and a cell background paints over a row
background. The selected row kept only its 1px border and no fill. The base
surface now goes on `table` alone; cells stay transparent so the row band
shows through. Same trap re-applies to the cell separators, which 7.css
deliberately drops inside a selected row and the dark rule was re-adding.
2. The cursor rectangle was drawn PER CELL. `tr.is-cursor > *` puts a dotted
outline around every cell, so the focused row rendered as a row of dotted
boxes. Win7 drew one rectangle around the row — the outline belongs on the
`tr`.
3. Selection was barely visible even in light, and that one is 7.css's own
semantics rather than a bug: listview's `.highlighted` is Win7's *inactive*
selection, a near-white wash. Win7 drew the FOCUSED pane's selection as the
stronger Aero band. The table now carries `is-active` from the panel's own
isActive(), and the focused pane's selection uses --w7-el-grad-h/-bd-h,
which the dark palette already restates, so it recolours for free.
Verified by cropping and zooming the harness screenshots in both themes rather
than eyeballing a full page: full-row band, separators dropped inside it, and a
single dotted rectangle on the cursor row.
Co-Authored-By: Claude <noreply@anthropic.com>
The file list was a CSS grid of <div>s, so 7.css's listview component never
matched a single selector and Tailwind styled the whole thing. It is now the
plain <table> 7.css documents, which is what makes the Aero treatment appear.
- The column header row moved OUT of its own div and INTO <thead>: 7.css makes
thead position:sticky, so it stays put while the body scrolls, and it has to
be inside the same table to do that.
- Column widths moved from a computed grid-template-columns to <colgroup>,
because 7.css sets table-layout: fixed. `gridTemplate()` is deleted.
- Selection is now `tr.highlighted` (7.css's gradient band + #aaddfa border)
instead of bg-primary/15.
- The sort arrow was the text glyph ↑/↓ from `sortIndicator()`, which is also
deleted; the sorted column is now `th.highlighted.indicator[.up]` and 7.css
draws the real clip-path triangle in the header.
- Row height, padding, borders and fonts now come from 7.css, so --row-h and
the per-cell text/color/font utilities are gone.
Two things 7.css does not cover, added in `skinfix`:
- Dark mode. listview.css hardcodes light literals (#fff, #c0c1cd, #eee and a
white header gradient) rather than --w7-* vars, so it does NOT follow the
hand-authored dark palette — the header labels rendered invisible, dark on
dark. The dark arms restate those rules; light keeps 7.css's own values.
- The keyboard cursor. 7.css models selection only; Win7 drew the focused row
with a dotted focus rectangle over it, which is what tells "cursor" apart
from "selected" when they differ. That is `tr.is-cursor`.
Verified visually this time, not just by build log: harness screenshots in both
light and dark show the header gradient, sort triangle, cell separators,
selection band and cursor rectangle matching 7.css's reference markup. Backend
`tsc --noEmit` clean, `bun run build:ui` clean, bundle 489.83 kB (from 490.50).
Co-Authored-By: Claude <noreply@anthropic.com>
Everything about this branch's look has so far been verified by reading build
logs, which is how a fully black window got reported as a clean boot. This adds
a way to actually LOOK at the skin.
- scripts/shot.ts — renders a page with Firefox headless (already installed; no
Chromium/puppeteer download) and writes a PNG. Firefox needs a dedicated
profile, since a running Firefox locks the default one.
- ui/dev/harness.html — static gallery pairing 7.css's own documented markup
("reference") against what the app currently renders ("ours"), for the window
frame, ListView, context menu, buttons, textbox, progress bars and tabs. Lives
outside ui/src so the Angular build never sees it.
Two traps found while building it, both documented in the files:
- The composed page MUST be written into ui/dist beside the stylesheet.
Firefox's security.fileuri.strict_origin_policy blocks a file:// document
from loading CSS in another directory, and the result renders completely
unstyled — indistinguishable from "the skin is broken".
- replaceAll, not replace, for the {{STYLES}} token: the harness documents the
token in a header comment that precedes the <link>, so a first-match replace
substitutes the comment and leaves the stylesheet unlinked. This produced one
false "everything is unstyled" result before it was spotted.
What the first screenshots already confirm, visually:
- The window has no Aero frame, radius, drop shadow or glass, and its title-bar
controls sit in their inactive colours — we render a bare .title-bar with no
.window.glass.active wrapper.
- The file list gets none of the ListView treatment (header gradient, sort
indicator, cell separators, selection band) because it is a div grid.
- The context menu gets none of the menu treatment (gutter, dividers, disabled
state, real checkmarks).
- NEW, not previously predicted: `.win7 button { min-width:0; padding:
revert-layer }` — added to stop Tailwind icon buttons ballooning — also
crushes legitimate dialog push buttons well below Win7's 75x23 metrics.
- Dark mode: ListView header labels and tab labels are invisible (dark on
dark), since listview.css hardcodes light literals the dark block never
restates.
Caveat recorded in the script: Firefox is Gecko, not the WebKitGTK engine the
app ships on. Good for skin fidelity, useless for native window transparency.
Co-Authored-By: Claude <noreply@anthropic.com>