89af52e1c020e1daf24b974f05ddd4a572c36de3
4
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
89af52e1c0 |
Clip the close button's hover glow at the frame edge; add a hover probe
Hovering the win7 X painted a red mark on the window border's far edge. Diagnosed programmatically, per request, with a new scripts/hover-probe.ts: Firefox headless has no pointer, so the probe copies the built stylesheet with every `:hover` rewritten to a `.simhover` class, renders the app's exact frame markup (w7-frame + direct-child title-bar + aria-label'd controls) with the X force-hovered, and pixel-scans four regions for red-dominant pixels, printing a verdict table and exiting non-zero on artifacts. Verdict from the first run: the right border and the region beside it were CLEAN — the reported mark is the glow escaping over the TOP edge. 7.css's hover ::before carries box-shadow 0 0 7px 3px #e68e75, a child's box-shadow is not clipped by the parent's border or radius, and the caption buttons sit flush against the window's top edge (border-top: 0) — so 100 red pixels landed above the frame: a tint across the top border and a halo floating on the desktop past it. Fix: clip-path inset(0 0 -1rem 0) on `.w7-frame > .title-bar` in skinfix. The glow now dies at the frame border — where the real Win7 DWM stopped it — and the bottom stays open so the authentic bleed toward the caption survives. clip-path clips hit-testing too, but only outside the region; the drag area is the title-bar's own box, entirely inside. Scoped to w7-frame so harness and demo windows keep stock 7.css behaviour. Verified: probe verdict now clean (escape regions 0, the intended in-frame glow still measures 30 px — the effect survived, only the escape is gone); the resting-state harness diffs exactly zero, so nothing but hover pixels changed; tsc + build clean. The probe stays in scripts/ as the regression test; gotchas.md records both the clipping rule and the :hover -> class technique. Co-Authored-By: Claude <noreply@anthropic.com> |
||
|
|
9f2a076e08 |
Scale stage 1: everything the UI sizes with is now rem
Groundwork for the continuous interface scale (a root font-size lever): every size the UI derives from must be root-relative, or it freezes while the rest grows. Gate for this commit: at the default 16px root the app renders pixel-identical to before — every conversion is exact (11px = 0.6875rem …). - The 8 panel-chrome tokens in styles.css: px -> rem, and the data-text compact/large tiers are DELETED — a continuous scale replaces discrete tiers. Same for --w7-fs (12px -> 0.75rem) and the win7 --radius (5px -> 0.3125rem, still landing rounded-md exactly on --w7-el-bdr's 3px). --radius-sm/md subtrahends: px -> rem, or corners would sharpen as the UI grew. - All 93 text-[11px]/text-[10px] arbitraries -> rem equivalents, plus the two inline padding:24px empty-state cells in the 7like file panel. - 7like.css gains a scale bridge in skinfix: 7.css is 370 px values with zero rem, and --w7-font reaches only 15 rules' TYPOGRAPHY — under a root lever win7 text would grow inside boxes frozen at 23px/14px/15px. The bridge re-expresses 7.css's size vars and its hardcoded box metrics (buttons via .w7-btn only, inputs, table rows/headers, title-bar controls, menu items, tabs, the 10pt check glyph) in rem at identical scale-1 pixels. 1px hairlines and focus rects stay px deliberately — crisp at any scale, and the tr border exists precisely to stop selection shifting rows. - Two skinfix traps found while writing it, one by reasoning and one by pixels: (a) NO blanket `.win7 button` restatement — skinfix outranks the skin-layer neutralizer that strips 7.css's 75x23 metrics off the ~84 icon buttons, so a blanket rule would re-inflate them all; (b) restating a base rule in skinfix also outranks 7.css's own VARIANTS of it by layer — the title-bar rule silently shrank the close button from 48px to 29px until the harness pixel diff caught it, and the active tab's padding-bottom needed the same treatment. Both variants are restated alongside their base rules. - TS px constants that mirror rem CSS are the latent-bug half of this work: both context menus' flip/clamp math converts through a new @core/metrics remPx() helper reading the LIVE root font-size (the shadlike menu's MENU_W=224 diverged from its w-56 box the moment scale != 1; the 7like menu's [style.width.px] pinned the box at 200px while text grew — it now binds width in rem, so math and box cannot disagree). The editors' cachedCharWidth is now keyed on the computed font string, self-invalidating under any font change, and both || px fallbacks derive from the element's font size instead of assuming a 16px root. Verified: tsc + build clean; modern and win7 live captures and the harness all diff to zero against pre-change baselines in their opaque regions (the harness to exactly zero end to end; modern's only delta is the native GTK titlebar focus state; win7's is the translucent Aero corner over the desktop). Co-Authored-By: Claude <noreply@anthropic.com> |
||
|
|
c8ccc6b918 |
Skin is a launch-time choice; stop applying it to a live window
Switching Modern -> Win7 at runtime broke the UI. SettingsService.applySkin toggled the `.win7` class the moment the setting changed — harmless when there was one component tree, and a broken window as soon as there were two. The tree is bootstrapped once from the preload-baked __APP_SKIN, so the live flip painted 7.css onto shadlike markup that has no .window.glass, no .title-bar, no menu[role=tablist] and no <table> ListView. The CSS landed on a tree that cannot receive it. A reload would not have helped, and neither would anything short of a restart: - The preload is a persistent WebKitUserScript injected at DOCUMENT_START, so its string is frozen at webview construction — loadURL() re-runs it with the OLD __APP_SKIN. updatePreloadScriptToWebView exists in the FFI but is reachable only from electrobun's internal <electrobun-webview> handler. - titleBarStyle/transparent have no setters; a live window cannot be re-framed. win7 -> modern is the dangerous direction — the modern tree draws no title bar, so it would land in a frameless transparent window with no way to move, minimize or close it. - Recreating the main window is also out: exitOnLastWindowClosed is true, the main rpc is captured by six push closures, the tray captures `win`, and listeners cannot be removed. So: applySkin is deleted outright, from setSkin AND from applyAll — the latter matters independently, since applyAll runs on the settingsChanged push and was therefore breaking every open editor and manager window too. Clicking a skin now only persists it. Also fixed a second leak found while tracing this: manager-window and editor-windows build from `currentSettings()`, the LIVE snapshot, so a window opened after a pending change would boot the new tree and frame while main still ran the old one. `initSessionSkin` now freezes the skin at startup before any window exists, and buildPreload/chromeOptions read that pinned value — chromeOptions loses its parameter so no call site can get it wrong. The options row shows the saved value as pending (skinPending() compares settings.skin() against APP_SKIN) with the hint retexted in all 7 locales; it said "Reopen the window to change its frame", which described the deleted design. Verified: tsc + build:ui clean; both skins boot correctly from a persisted setting (win7 frameless, modern with the native frame). The live flip is now impossible by construction, which is the check that matters here — the UI bundle contains no classList write for win7 at all, the only writer is buildPreload, and sessionSkin has exactly one assignment site. Not verified: the click itself and the pending hint appearing, which need an interaction pass — no window automation is available here. Both are present in the built bundle. Co-Authored-By: Claude <noreply@anthropic.com> |
||
|
|
b35c30d5ab |
Stage 3: split styles.css into a shared base plus per-skin sheets
The 919-line stylesheet had a clean seam: `main`'s version is 278 lines and this branch only ever APPENDED to it. Verified that directly — a diff of main's styles.css against our first 298 lines differs only by the @layer statement and the 7.css import. - ui/src/styles.css (296) keeps the shared half: the @layer statement, the Tailwind import, the OKLCH tokens, @theme inline, the data-text interface sizes, the animations and the accent axis. The @layer statement must stay first here — it is one of only two rule types allowed above @import, and it is what sorts `skin` above `utilities`. - app/skins/7like/7like.css (636) takes the whole win7 section plus the scoped-7.css import that feeds layer(skin). - app/skins/shadlike/shadlike.css is near-empty by nature, not by omission: that skin IS the shared token system plus inline Tailwind, so there is no framework to bridge and no cascade to invert. The file documents why, and what does/does not belong in it. Both are @imported from styles.css, so one bundle still ships both, scoped by `.win7` exactly as before. One real trap caught here: the @font-face url() is resolved relative to the stylesheet, so moving the win7 section three directories deeper would have silently 404'd Noto Sans — the build stays green and the app just falls back to a different font. Fixed by moving the fonts INTO the skin (they exist only for the Win7 look, where Noto Sans substitutes for Segoe UI), which keeps `./fonts/...` correct wherever the folder goes. Confirmed in the built output: both woff2 emitted as hashed assets with the url rewritten to ./media/. Verified: build clean, built CSS keeps `@layer theme,base,components, utilities,skin,skinfix` and all 7.css selectors, the live window's opaque interior is pixel-identical to the pre-refactor baseline, and both harness renders (light and dark) diff to exactly zero. A layer-assignment mistake here would not be subtle — 7.css would lose to ~1900 Tailwind utilities and the app would look nothing like this. Co-Authored-By: Claude <noreply@anthropic.com> |