Stage 4: restore the modern tree into app/skins/shadlike/

Both UIs now live side by side. The 18 modern component files come straight
from `git show main:<path>` — recovered, not rewritten, which is possible
because main's tip IS the merge base of this branch. There is no title-bar
among them: that component is win7-only, since the modern skin defers to the
native window frame.

Their imports were rewritten to @core the same way stage 1 did, leaving only
skin-internal relative imports behind. Added skins/shadlike/index.ts exporting
SHAD_ROOTS with the same shape as SEVEN_ROOTS, so main.ts can select a tree
without knowing either skin's internals.

Restored the skin axis in core/platform.ts, deleted in fe028a9 and needed
again by the modern tree: __APP_SKIN on the Window global, APP_SKIN,
IS_WIN7_CHROME, and IS_MAC_CHROME = IS_MAC && !IS_WIN7_CHROME. That last one
is what reserves pl-24 for the macOS traffic lights in the fused hiddenInset
header — and correctly stops reserving it under win7, where titleBarStyle
'hidden' removes the traffic lights entirely.

The tree is not reachable yet; the build is the gate. I checked that the gate
is real rather than assuming it: injecting a type error into an unreferenced
shadlike file does fail `bun run build:ui`, so ngtsc type-checks the whole
program including components nothing imports. Without that check, "the build
passes" would have proven nothing about 18 files no one references.

win7 remains pixel-identical to the pre-refactor baseline.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-08-16 04:56:20 +02:00
co-authored by Claude
parent b35c30d5ab
commit bb97e5418f
20 changed files with 3626 additions and 0 deletions
+23
View File
@@ -8,6 +8,9 @@ declare global {
__APP_PLATFORM?: string;
/** Which root component this window boots. */
__APP_MODE?: 'main' | 'editor' | 'manager';
/** Which skin tree this window boots. Baked into the preload because
* settings resolve too late to decide layout without a flash. */
__APP_SKIN?: 'modern' | 'win7';
/** Window-kind specific context (EditorOpenContext for editor windows). */
__APP_CTX?: unknown;
}
@@ -32,6 +35,26 @@ export const APP_MODE: 'main' | 'editor' | 'manager' =
export const EDITOR_CONTEXT =
typeof window !== 'undefined' ? (window.__APP_CTX as EditorOpenContext | undefined) : undefined;
/**
* Which skin tree this window booted. Read from the preload rather than from
* SettingsService because both are needed before first paint — main.ts picks a
* root component from it, and it must not change under a running window (the
* native frame is fixed at BrowserWindow construction).
*/
export const APP_SKIN: 'modern' | 'win7' =
typeof window !== 'undefined' ? (window.__APP_SKIN ?? 'modern') : 'modern';
export const IS_WIN7_CHROME = APP_SKIN === 'win7';
/**
* True when macOS traffic lights overlay the app's own header row — the fused
* `hiddenInset` layout, which reserves `pl-24` for them. False under the win7
* skin even on macOS: `titleBarStyle: 'hidden'` removes the traffic lights
* altogether, so reserving space would leave a gap. Only the shadlike tree
* reads this; 7like draws its own title bar and never defers to native chrome.
*/
export const IS_MAC_CHROME = IS_MAC && !IS_WIN7_CHROME;
/**
* Kill the webview's default right-click menu (Reload, Inspect Element…)
* everywhere the app doesn't show its own native menu. Text fields keep the