fix(projects): style the panel controls and use the real theme tokens

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.
This commit is contained in:
Yaojia Wang
2026-07-29 18:39:34 +02:00
parent e004da1a55
commit 3c0b2f6bae

View File

@@ -1569,8 +1569,8 @@ body {
display: flex; display: flex;
align-items: stretch; align-items: stretch;
margin: 10px 0 4px; margin: 10px 0 4px;
background: var(--bg-sunk, rgba(0, 0, 0, 0.22)); background: var(--surface-1);
border: 1px solid var(--border, rgba(255, 255, 255, 0.08)); border: 1px solid var(--border);
border-radius: 9px; border-radius: 9px;
overflow: hidden; overflow: hidden;
flex-wrap: wrap; flex-wrap: wrap;
@@ -1582,7 +1582,7 @@ body {
gap: 3px; gap: 3px;
padding: 11px 18px; padding: 11px 18px;
min-width: 0; 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 { .proj-sync-cell:last-child {
@@ -1598,14 +1598,14 @@ body {
font-size: 10.5px; font-size: 10.5px;
letter-spacing: 0.13em; letter-spacing: 0.13em;
text-transform: uppercase; text-transform: uppercase;
color: var(--fg-faint, #6f6a61); color: var(--text-faint);
} }
.proj-sync-v { .proj-sync-v {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 7px; gap: 7px;
font-family: var(--mono, ui-monospace, SFMono-Regular, Menlo, monospace); font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
font-size: 15px; font-size: 15px;
font-variant-numeric: tabular-nums; font-variant-numeric: tabular-nums;
} }
@@ -1617,9 +1617,9 @@ body {
} }
.proj-sync-sub { .proj-sync-sub {
font-family: var(--mono, ui-monospace, SFMono-Regular, Menlo, monospace); font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
font-size: 11px; font-size: 11px;
color: var(--fg-faint, #6f6a61); color: var(--text-faint);
} }
.proj-sync-sub-bad { .proj-sync-sub-bad {
@@ -1627,7 +1627,7 @@ body {
} }
.proj-sync-upstream { .proj-sync-upstream {
color: var(--fg-dim, #a8a299); color: var(--text-dim);
} }
.proj-sync-chip { .proj-sync-chip {
@@ -1645,7 +1645,7 @@ body {
} }
.proj-sync-behind { .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. */ /* The one reassuring state. Reachable only with an upstream AND a fresh fetch. */
@@ -1689,7 +1689,7 @@ body {
border-radius: 7px; border-radius: 7px;
border: 0; border: 0;
background: var(--accent); background: var(--accent);
color: var(--bg, #100f0d); color: var(--on-accent);
} }
.proj-sync-fetch:hover:not(:disabled) { .proj-sync-fetch:hover:not(:disabled) {
@@ -1702,7 +1702,7 @@ body {
} }
.proj-sync-fetch:focus-visible { .proj-sync-fetch:focus-visible {
outline: 2px solid var(--fg, #ece9e3); outline: 2px solid var(--text);
outline-offset: 2px; outline-offset: 2px;
} }
@@ -1713,7 +1713,7 @@ body {
.proj-sync-cell { .proj-sync-cell {
border-right: 0; border-right: 0;
border-bottom: 1px solid var(--border, rgba(255, 255, 255, 0.08)); border-bottom: 1px solid var(--border);
} }
.proj-sync-actions { .proj-sync-actions {
@@ -1723,7 +1723,7 @@ body {
/* ── w6: unpushed count beside the commit-list heading ───────────────────── */ /* ── w6: unpushed count beside the commit-list heading ───────────────────── */
.proj-commitlog-count { .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-size: 11.5px;
font-variant-numeric: tabular-nums; font-variant-numeric: tabular-nums;
color: var(--accent); color: var(--accent);
@@ -1768,9 +1768,9 @@ body {
cursor: pointer; cursor: pointer;
padding: 4px 12px; padding: 4px 12px;
border-radius: 6px; border-radius: 6px;
border: 1px solid var(--border-strong, rgba(255, 255, 255, 0.14)); border: 1px solid var(--border-strong);
background: transparent; background: transparent;
color: var(--fg, #ece9e3); color: var(--text);
} }
.proj-wt-open:hover { .proj-wt-open:hover {
@@ -1779,7 +1779,7 @@ body {
} }
.proj-wt-open:focus-visible { .proj-wt-open:focus-visible {
outline: 2px solid var(--fg, #ece9e3); outline: 2px solid var(--text);
outline-offset: 2px; outline-offset: 2px;
} }
@@ -1819,8 +1819,8 @@ body {
.proj-commit-boundary-label { .proj-commit-boundary-label {
font-size: 10.5px; font-size: 10.5px;
color: var(--fg-dim, #a8a299); color: var(--text-dim);
border: 1px solid var(--border, rgba(255, 255, 255, 0.1)); border: 1px solid var(--border);
border-radius: 999px; border-radius: 999px;
padding: 2px 10px; padding: 2px 10px;
white-space: nowrap; white-space: nowrap;
@@ -1830,7 +1830,7 @@ body {
.proj-commit-boundary-rule { .proj-commit-boundary-rule {
flex: 1; flex: 1;
height: 1px; 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. */ /* w6/G7: running sessions attributed to one worktree row. */
@@ -2281,6 +2281,102 @@ body {
opacity: 0.5; opacity: 0.5;
cursor: not-allowed; 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. */ /* W5 fan-out status/error banner — fixed, dismissible, textContent only. */
.fanout-banner { .fanout-banner {
position: fixed; position: fixed;