From 3c0b2f6bae91c32fe2e7ef6e09b91d033c98af66 Mon Sep 17 00:00:00 2001 From: Yaojia Wang Date: Wed, 29 Jul 2026 18:39:34 +0200 Subject: [PATCH] fix(projects): style the panel controls and use the real theme tokens MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two things, both invisible in code review and obvious on screen. 1. Eight controls in the project detail had class names but no CSS rule at all, so they rendered as raw user-agent widgets — white input boxes and grey buttons sitting inside a dark panel: View Diff, the new-branch input, Create Worktree, and the five fan-out fields. Gave them the skin the panel already established, with two button roles: filled accent for the control that commits a form (matching Fetch), outline for one that only reveals or toggles (matching Open). Layout stays in each element's existing rule; this block sets only the shared skin, so no property is declared twice. 2. The w6 CSS referenced --fg, --fg-dim, --fg-faint, --bg-sunk and --mono, none of which exist in :root. Every one of those 19 references was silently falling through to its hardcoded fallback, which happened to match the default amber theme — so it looked correct while being wired to nothing. Under any other theme the sync band would have kept the default colours while the rest of the app changed. Rewired to the real tokens: --text, --text-dim, --text-faint, --surface-1, --on-accent, and the mono stack the file already uses. The fallback values are what hid this: a var() fallback turns a typo into a silent success. Worth remembering when reaching for one. Verified: tsc clean, npm test green (78 files / 2161, e2e 27), bundle rebuilt. --- public/style.css | 134 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 115 insertions(+), 19 deletions(-) diff --git a/public/style.css b/public/style.css index 0deed6e..0122893 100644 --- a/public/style.css +++ b/public/style.css @@ -1569,8 +1569,8 @@ body { display: flex; align-items: stretch; margin: 10px 0 4px; - background: var(--bg-sunk, rgba(0, 0, 0, 0.22)); - border: 1px solid var(--border, rgba(255, 255, 255, 0.08)); + background: var(--surface-1); + border: 1px solid var(--border); border-radius: 9px; overflow: hidden; flex-wrap: wrap; @@ -1582,7 +1582,7 @@ body { gap: 3px; padding: 11px 18px; min-width: 0; - border-right: 1px solid var(--border, rgba(255, 255, 255, 0.08)); + border-right: 1px solid var(--border); } .proj-sync-cell:last-child { @@ -1598,14 +1598,14 @@ body { font-size: 10.5px; letter-spacing: 0.13em; text-transform: uppercase; - color: var(--fg-faint, #6f6a61); + color: var(--text-faint); } .proj-sync-v { display: flex; align-items: center; gap: 7px; - font-family: var(--mono, ui-monospace, SFMono-Regular, Menlo, monospace); + font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 15px; font-variant-numeric: tabular-nums; } @@ -1617,9 +1617,9 @@ body { } .proj-sync-sub { - font-family: var(--mono, ui-monospace, SFMono-Regular, Menlo, monospace); + font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11px; - color: var(--fg-faint, #6f6a61); + color: var(--text-faint); } .proj-sync-sub-bad { @@ -1627,7 +1627,7 @@ body { } .proj-sync-upstream { - color: var(--fg-dim, #a8a299); + color: var(--text-dim); } .proj-sync-chip { @@ -1645,7 +1645,7 @@ body { } .proj-sync-behind { - color: var(--fg-faint, #6f6a61); + color: var(--text-faint); } /* The one reassuring state. Reachable only with an upstream AND a fresh fetch. */ @@ -1689,7 +1689,7 @@ body { border-radius: 7px; border: 0; background: var(--accent); - color: var(--bg, #100f0d); + color: var(--on-accent); } .proj-sync-fetch:hover:not(:disabled) { @@ -1702,7 +1702,7 @@ body { } .proj-sync-fetch:focus-visible { - outline: 2px solid var(--fg, #ece9e3); + outline: 2px solid var(--text); outline-offset: 2px; } @@ -1713,7 +1713,7 @@ body { .proj-sync-cell { border-right: 0; - border-bottom: 1px solid var(--border, rgba(255, 255, 255, 0.08)); + border-bottom: 1px solid var(--border); } .proj-sync-actions { @@ -1723,7 +1723,7 @@ body { /* ── w6: unpushed count beside the commit-list heading ───────────────────── */ .proj-commitlog-count { - font-family: var(--mono, ui-monospace, SFMono-Regular, Menlo, monospace); + font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11.5px; font-variant-numeric: tabular-nums; color: var(--accent); @@ -1768,9 +1768,9 @@ body { cursor: pointer; padding: 4px 12px; border-radius: 6px; - border: 1px solid var(--border-strong, rgba(255, 255, 255, 0.14)); + border: 1px solid var(--border-strong); background: transparent; - color: var(--fg, #ece9e3); + color: var(--text); } .proj-wt-open:hover { @@ -1779,7 +1779,7 @@ body { } .proj-wt-open:focus-visible { - outline: 2px solid var(--fg, #ece9e3); + outline: 2px solid var(--text); outline-offset: 2px; } @@ -1819,8 +1819,8 @@ body { .proj-commit-boundary-label { font-size: 10.5px; - color: var(--fg-dim, #a8a299); - border: 1px solid var(--border, rgba(255, 255, 255, 0.1)); + color: var(--text-dim); + border: 1px solid var(--border); border-radius: 999px; padding: 2px 10px; white-space: nowrap; @@ -1830,7 +1830,7 @@ body { .proj-commit-boundary-rule { flex: 1; height: 1px; - background: var(--border-strong, rgba(255, 255, 255, 0.14)); + background: var(--border-strong); } /* w6/G7: running sessions attributed to one worktree row. */ @@ -2281,6 +2281,102 @@ body { opacity: 0.5; cursor: not-allowed; } +/* ── Projects panel controls ────────────────────────────────────────────────── + These eight controls shipped with class names but no visual rules, so they + rendered as raw user-agent widgets: white boxes and grey buttons in a dark + panel. Layout stays with each element's own rule above; this block only sets + the shared skin, so there is no duplicate declaration of the same property. + + Two button roles, matching what the panel already established: filled accent + for the action that commits the form (like Fetch), outline for anything that + only reveals or toggles (like Open). */ +.proj-wt-branch-input, +.proj-fanout-prompt, +.proj-fanout-lanes, +.proj-fanout-branch, +.proj-fanout-mode { + font: inherit; + font-size: 13px; + color: var(--text); + background: var(--surface-2); + border: 1px solid var(--border-strong); + border-radius: 8px; + padding: 8px 11px; + outline: none; + box-sizing: border-box; +} + +.proj-wt-branch-input::placeholder, +.proj-fanout-prompt::placeholder, +.proj-fanout-branch::placeholder { + color: var(--text-faint); +} + +.proj-wt-branch-input:focus, +.proj-fanout-prompt:focus, +.proj-fanout-lanes:focus, +.proj-fanout-branch:focus, +.proj-fanout-mode:focus { + border-color: var(--accent); +} + +/* A branch name is an identifier, so it reads as one. */ +.proj-wt-branch-input, +.proj-fanout-branch { + font-family: ui-monospace, SFMono-Regular, Menlo, monospace; + font-size: 12.5px; +} + +.proj-fanout-lanes { + text-align: center; + font-variant-numeric: tabular-nums; +} + +.proj-fanout-mode { + cursor: pointer; +} + +.proj-wt-submit, +.proj-fanout-submit { + font: inherit; + font-size: 12.5px; + font-weight: 560; + cursor: pointer; + padding: 8px 15px; + border: 0; + border-radius: 8px; + background: var(--accent); + color: var(--on-accent); +} + +.proj-wt-submit:hover:not(:disabled), +.proj-fanout-submit:hover:not(:disabled) { + filter: brightness(1.08); +} + +.proj-diff-toggle { + font: inherit; + font-size: 12.5px; + cursor: pointer; + padding: 7px 14px; + border-radius: 8px; + border: 1px solid var(--border-strong); + background: transparent; + color: var(--text); +} + +.proj-diff-toggle:hover { + border-color: var(--accent); + color: var(--accent); +} + +.proj-wt-submit:focus-visible, +.proj-fanout-submit:focus-visible, +.proj-diff-toggle:focus-visible { + outline: 2px solid var(--text); + outline-offset: 2px; +} + /* W5 fan-out status/error banner — fixed, dismissible, textContent only. */ .fanout-banner { position: fixed;