Files
miniSCP/ui/dev/harness.html
T
jgamboaandClaude 0ae2a62229 Stage 4a: context menu is pure 7.css; retire the lookalike and the false claim
The menu now renders 7.css's real contract — ul[role=menu] > li[role=menuitem]
> button for actions, input[type=checkbox] + label for the checkable column
toggles, and dividers as .has-divider on the PRECEDING item (7.css draws them
as an ::after bevel, not as a node; the service's separator entries collapse
onto their predecessor at render time). With the markup right, the framework
supplies everything the hand-written version imitated or lacked: the left
gutter stripe, bevelled separators, the gradient selection band, the checked
box, and disabled/submenu styling we previously had none of.

Deleted: the w7-menu lookalike (both the button-slab stripper in `skin` and
the whole hand-authored Aero set in `skinfix`) and its w7-menu/w7-menu-sep
hooks. The "7.css has no menu component" claims in styles.css and
architecture.md were FALSE — dist/gui/menu.css is a full component; the old
markup (div > button) simply matched none of it. Both corrected to state the
real contract and the trap.

Keyboard now follows the platform instead of a highlight class: arrows move
REAL focus between items — 7.css styles :focus-visible identically to :hover,
and keyboard-initiated programmatic focus counts — and Enter/Space activate
buttons natively; only labels need a synthetic click. This also makes the menu
honest to screen readers.

Dark mode: menu.css hardcodes light literals (color:initial, white bevel
halves, the #b3d3f9 checked-box ring); restated in skinfix's dark arm like the
ListView's.

Also fixed, caught BY the harness: the Stage 3 frame sizing rule was keyed on
bare `.window`, forcing 100vh height onto every 7.css window (the harness's
demo windows blew up to full page). It is now keyed on `w7-frame`, a hook only
the three real window roots carry.

Verified zoomed in light and dark against 7.css's reference markup: gutter,
dividers, checkmark box, grey right-aligned accelerator all match; bundle
490.92 kB.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-16 03:20:55 +02:00

245 lines
11 KiB
HTML

<!doctype html>
<!--
Skin harness — a static gallery rendered headlessly by scripts/shot.ts so the
Win7 skin can be LOOKED AT during development instead of inferred from a
clean build log. Not shipped: it lives outside ui/src, so the Angular build
never sees it.
Each section pairs 7.css's own documented markup ("reference") with what the
app currently renders ("ours"). Where those two disagree visually, 7.css is
not reaching our component — that mismatch is the whole point of the page.
Layout here uses INLINE STYLES on purpose: Tailwind v4 only emits utilities it
found while scanning ui/src, so utility classes used only here would not exist
in the built stylesheet. {{STYLES}} is replaced by scripts/shot.ts with the
real hashed build output.
-->
<html class="win7" lang="en">
<head>
<meta charset="utf-8" />
<title>7.css harness</title>
<link rel="stylesheet" href="{{STYLES}}" />
<style>
body { margin: 0; padding: 20px; }
h2 { font-size: 13px; margin: 22px 0 6px; opacity: 0.75; }
.pair { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; align-items: start; }
.cell { min-width: 0; }
.cell > figcaption {
font-size: 11px; opacity: 0.6; margin-bottom: 5px; text-transform: uppercase;
letter-spacing: 0.04em;
}
.stage { padding: 14px; background: #6ba5d7; border-radius: 4px; }
</style>
</head>
<body>
<h2>1 — Window frame, glass, drop shadow, active colour</h2>
<div class="pair">
<figure class="cell" style="margin:0">
<figcaption>reference — .window.glass.active</figcaption>
<div class="stage">
<div class="window glass active" style="width: 320px">
<div class="title-bar">
<div class="title-bar-text">miniSCP</div>
<div class="title-bar-controls">
<button aria-label="Minimize"></button>
<button aria-label="Maximize"></button>
<button aria-label="Close"></button>
</div>
</div>
<div class="window-body"><p>Glass frame, 6px radius, drop shadow.</p></div>
</div>
</div>
</figure>
<figure class="cell" style="margin:0">
<figcaption>ours — app.html shell (active above, inactive below)</figcaption>
<div class="stage">
<div class="window glass active" style="width: 320px">
<div class="title-bar">
<div class="title-bar-text">miniSCP</div>
<div class="title-bar-controls">
<button aria-label="Minimize"></button>
<button aria-label="Maximize"></button>
<button aria-label="Close"></button>
</div>
</div>
<div class="window-body"><p style="margin:0">Focused window.</p></div>
</div>
<div class="window glass" style="width: 320px; margin-top: 12px">
<div class="title-bar">
<div class="title-bar-text">miniSCP</div>
<div class="title-bar-controls">
<button aria-label="Minimize"></button>
<button aria-label="Maximize"></button>
<button aria-label="Close"></button>
</div>
</div>
<div class="window-body"><p style="margin:0">Unfocused — chrome desaturates.</p></div>
</div>
</div>
</figure>
</div>
<h2>2 — ListView (file panel)</h2>
<div class="pair">
<figure class="cell" style="margin:0">
<figcaption>reference — &lt;table&gt;</figcaption>
<table class="has-shadow" style="width:100%">
<thead>
<tr>
<th>Name</th>
<th class="highlighted indicator">Size</th>
<th>Modified</th>
</tr>
</thead>
<tbody>
<tr><td>..</td><td style="text-align:right">—</td><td>—</td></tr>
<tr><td>Documents</td><td style="text-align:right">—</td><td>3/29/2007 12:00 AM</td></tr>
<tr class="highlighted"><td>report.pdf</td><td style="text-align:right">27 KB</td><td>3/23/2007 12:00 AM</td></tr>
<tr><td>notes.txt</td><td style="text-align:right">4 KB</td><td>3/13/2007 12:00 AM</td></tr>
</tbody>
</table>
</figure>
<figure class="cell" style="margin:0">
<figcaption>ours — focused pane (top) vs unfocused pane (bottom)</figcaption>
<!-- Focused pane: strong band on selected rows AND the cursor row;
the cursor row additionally gets the dotted focus rect. -->
<table class="is-active">
<colgroup>
<col />
<col style="width: 5.5rem" />
<col style="width: 8.5rem" />
</colgroup>
<thead>
<tr>
<th>Name</th>
<th class="highlighted indicator up" style="text-align:right">Size</th>
<th>Modified</th>
</tr>
</thead>
<tbody>
<tr><td>..</td><td style="text-align:right">—</td><td>—</td></tr>
<tr class="highlighted"><td>Documents</td><td style="text-align:right">—</td><td>3/29/2007 12:00 AM</td></tr>
<tr class="highlighted"><td>report.pdf</td><td style="text-align:right">27 KB</td><td>3/23/2007 12:00 AM</td></tr>
<tr class="highlighted is-cursor"><td>notes.txt</td><td style="text-align:right">4 KB</td><td>3/13/2007 12:00 AM</td></tr>
</tbody>
</table>
<!-- Unfocused pane: same rows, faint inactive wash, no dots. -->
<table style="margin-top:10px">
<colgroup>
<col />
<col style="width: 5.5rem" />
<col style="width: 8.5rem" />
</colgroup>
<thead>
<tr>
<th>Name</th>
<th style="text-align:right">Size</th>
<th>Modified</th>
</tr>
</thead>
<tbody>
<tr><td>..</td><td style="text-align:right">—</td><td>—</td></tr>
<tr class="highlighted"><td>Documents</td><td style="text-align:right">—</td><td>3/29/2007 12:00 AM</td></tr>
<tr><td>report.pdf</td><td style="text-align:right">27 KB</td><td>3/23/2007 12:00 AM</td></tr>
<tr class="highlighted"><td>notes.txt</td><td style="text-align:right">4 KB</td><td>3/13/2007 12:00 AM</td></tr>
</tbody>
</table>
</figure>
</div>
<h2>2b — Selection geometry (rows must NOT shift when selected)</h2>
<div class="pair">
<figure class="cell" style="margin:0">
<figcaption>no selection</figcaption>
<table class="is-active">
<colgroup><col /><col style="width:6rem" /></colgroup>
<thead><tr><th>Name</th><th>Size</th></tr></thead>
<tbody>
<tr><td>aaa.txt</td><td>1 KB</td></tr>
<tr><td>bbb.txt</td><td>2 KB</td></tr>
<tr><td>ccc.txt</td><td>3 KB</td></tr>
<tr><td>ddd.txt</td><td>4 KB</td></tr>
</tbody>
</table>
</figure>
<figure class="cell" style="margin:0">
<figcaption>middle row selected — baselines must still line up</figcaption>
<table class="is-active">
<colgroup><col /><col style="width:6rem" /></colgroup>
<thead><tr><th>Name</th><th>Size</th></tr></thead>
<tbody>
<tr><td>aaa.txt</td><td>1 KB</td></tr>
<tr class="highlighted"><td>bbb.txt</td><td>2 KB</td></tr>
<tr><td>ccc.txt</td><td>3 KB</td></tr>
<tr><td>ddd.txt</td><td>4 KB</td></tr>
</tbody>
</table>
</figure>
</div>
<h2>3 — Context menu</h2>
<div class="pair">
<figure class="cell" style="margin:0">
<figcaption>reference — ul[role=menu]</figcaption>
<ul role="menu" style="width:200px">
<li role="menuitem"><a href="#m">Send to Other Panel</a></li>
<li role="menuitem"><a href="#m">Open</a></li>
<li role="menuitem" class="has-divider"><a href="#m">Rename</a></li>
<li role="menuitem"><a href="#m">Copy Path</a></li>
<li role="menuitem" aria-disabled="true"><a href="#m">Permissions</a></li>
<li role="menuitem" class="has-divider"><a href="#m">Delete</a></li>
<li role="menuitem">
<input type="checkbox" id="h-col-size" checked />
<label for="h-col-size">Size</label>
</li>
<li role="menuitem">
<input type="checkbox" id="h-col-kind" />
<label for="h-col-kind">Kind</label>
</li>
</ul>
</figure>
<figure class="cell" style="margin:0">
<figcaption>ours — context-menu.ts output (buttons, divider, accelerator, checkables)</figcaption>
<ul role="menu" style="width:200px">
<li role="menuitem"><button type="button">Send to Other Panel</button></li>
<li role="menuitem"><button type="button">Open</button></li>
<li role="menuitem"><button type="button">Edit <span>F4</span></button></li>
<li role="menuitem" class="has-divider"><button type="button">Rename</button></li>
<li role="menuitem"><button type="button">Copy Path</button></li>
<li role="menuitem" class="has-divider"><button type="button">Delete</button></li>
<li role="menuitem">
<input type="checkbox" id="ours-col-size" checked tabindex="-1" />
<label for="ours-col-size">Size</label>
</li>
<li role="menuitem">
<input type="checkbox" id="ours-col-kind" tabindex="-1" />
<label for="ours-col-kind">Kind</label>
</li>
</ul>
</figure>
</div>
<h2>4 — Controls 7.css already owns (sanity check)</h2>
<div class="pair">
<figure class="cell" style="margin:0">
<figcaption>buttons / textbox / progress</figcaption>
<div style="display:flex;flex-direction:column;gap:10px">
<div style="display:flex;gap:6px"><button>OK</button><button>Cancel</button><button disabled>Disabled</button></div>
<input type="text" value="/home/supongo/code" style="width:100%" />
<div role="progressbar" style="width:100%"><div style="width:42%"></div></div>
<div role="progressbar" class="marquee" style="width:100%"></div>
</div>
</figure>
<figure class="cell" style="margin:0">
<figcaption>tabs — menu[role=tablist]</figcaption>
<menu role="tablist">
<button role="tab" aria-selected="true">local</button>
<button role="tab">server-a</button>
<button role="tab">server-b</button>
</menu>
<div role="tabpanel" style="padding:10px">Tab body</div>
</figure>
</div>
</body>
</html>