The tab strip was a hand-rolled lookalike: bg-accent for the active tab and an absolutely-positioned bg-primary underline, competing with a tab component 7.css already ships. Replaced with its actual contract — menu[role=tablist] plus one button[role=tab][aria-selected] per workspace — so 7.css draws the joined inactive tabs and the raised white active one. Per the agreed design the per-tab X is gone: real Win7 tab controls had none, and a button nested in a button is invalid HTML. Closing keeps Ctrl/Cmd+W and gains middle-click (auxclick, guarded on button 1 so the right button never closes a tab). Drag-reorder moved onto the tab button itself and still works. Three things 7.css does that had to be accommodated, each found by looking rather than by reasoning: - Its selector is the DESCENDANT `menu[role=tablist] button`, so the +, update pill and right-hand tools deliberately stay outside the menu. - The strip is a .w7-toolbar, whose neutralizer strips background, border and both pseudo-elements to make toolbar buttons flat. That flattened the tabs to nothing, so the rule now exempts :not([role=tab]) — tabs want the full Aero slab, their neighbours want flat. - overflow-x:auto on the scroller forces computed overflow-y from visible to auto, so the strip clips vertically. 7.css raises the active tab with margin-top:-2px, which put its top border outside the scroll box and silently deleted it. The strip now reserves 2px of padding-top, mirroring the padding-left:3px 7.css already reserves for the same tab's -3px left margin. Caught by pixel-scanning the tab's top edge against 7.css's own reference markup in the harness: reference had #8e8f8f, ours jumped straight from toolbar grey to tab fill. Also: tabs.css hardcodes color:#222 on every tablist button, outside 7.css's var system, leaving labels near-invisible in dark. Routed through a new --w7-tab-c token declared light in :root.win7 and overridden in BOTH dark blocks (attribute and prefers-color-scheme), matching the ListView and menu literals. And its `display: block` outranks Tailwind's .flex, which jammed the icon against the label — flex/gap restored in skinfix. role="tabpanel" on the panel area was considered and skipped: 7.css gives it padding:14px, margin-bottom:9px and its own border, which would fight the split-pane layout for a join that cannot read anyway with the panel toolbar row in between. The harness grew a section 5 mirroring this markup, because the live app starts with exactly one workspace and there is no way to click "+" from a headless capture — multi-tab state is only checkable there. Verified in both themes headless and on a live window capture. Co-Authored-By: Claude <noreply@anthropic.com>
290 lines
13 KiB
HTML
290 lines
13 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 — <table></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>reference — 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>
|
|
|
|
<h2>5 — Workspace tab strip (ours, as tab-bar.ts renders it)</h2>
|
|
<!--
|
|
The live app only ever has ONE workspace at startup and there is no way to
|
|
click "+" from a headless capture, so multi-tab state can only be checked
|
|
here. This mirrors tab-bar.ts exactly: the tabs sit in a menu[role=tablist]
|
|
inside a .w7-toolbar row, and the "+" / right-hand tools sit OUTSIDE the
|
|
menu so 7.css's descendant selector does not style them as tabs.
|
|
-->
|
|
<div class="pair">
|
|
<figure class="cell" style="margin:0">
|
|
<figcaption>ours — 3 workspaces, 2nd active</figcaption>
|
|
<div class="w7-toolbar relative flex h-9 items-center gap-0.5 border-b border-border bg-chrome pt-1 pr-1.5 pl-1.5">
|
|
<menu role="tablist" class="flex min-w-0 items-center overflow-x-auto">
|
|
<button role="tab" class="flex max-w-52 min-w-0 shrink-0 items-center gap-1.5">
|
|
<span class="truncate">Local</span>
|
|
</button>
|
|
<button role="tab" aria-selected="true" class="flex max-w-52 min-w-0 shrink-0 items-center gap-1.5">
|
|
<span class="truncate">build-server</span>
|
|
</button>
|
|
<button role="tab" class="flex max-w-52 min-w-0 shrink-0 items-center gap-1.5">
|
|
<span class="truncate">a-very-long-workspace-name-that-truncates</span>
|
|
</button>
|
|
</menu>
|
|
<button class="ml-0.5 grid size-6 place-items-center rounded-md">+</button>
|
|
<div class="flex-1"></div>
|
|
<button class="grid h-6 px-2 py-1 place-items-center rounded-md text-[11px]">Connections</button>
|
|
</div>
|
|
<div style="height:60px;background:var(--w7-tab-bg,#fff);border:1px solid #8e8f8f;border-top:0"></div>
|
|
</figure>
|
|
<figure class="cell" style="margin:0">
|
|
<figcaption>ours — single workspace (the live startup state)</figcaption>
|
|
<div class="w7-toolbar relative flex h-9 items-center gap-0.5 border-b border-border bg-chrome pt-1 pr-1.5 pl-1.5">
|
|
<menu role="tablist" class="flex min-w-0 items-center overflow-x-auto">
|
|
<button role="tab" aria-selected="true" class="flex max-w-52 min-w-0 shrink-0 items-center gap-1.5">
|
|
<span class="truncate">Local</span>
|
|
</button>
|
|
</menu>
|
|
<button class="ml-0.5 grid size-6 place-items-center rounded-md">+</button>
|
|
<div class="flex-1"></div>
|
|
<button class="grid h-6 px-2 py-1 place-items-center rounded-md text-[11px]">Connections</button>
|
|
</div>
|
|
<div style="height:60px;background:var(--w7-tab-bg,#fff);border:1px solid #8e8f8f;border-top:0"></div>
|
|
</figure>
|
|
</div>
|
|
</body>
|
|
</html>
|