From e1d635a099e12fac2ea648e0b31e4edf5e780ee7 Mon Sep 17 00:00:00 2001 From: Hongming Wang Date: Sun, 3 May 2026 11:26:28 -0700 Subject: [PATCH] fix(canvas): Toolbar contrast + focus rings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Top-of-canvas Toolbar had multiple low-contrast surfaces in light theme: Action buttons (Stop All, Restart Pending): - bg-red-950/50 + bg-amber-950/40 → bg-bad/10 + bg-warm/10 with bg-bad/40 + bg-warm/40 borders. Dark-tinted backgrounds with /40-/50 alpha render as nearly invisible smudges on warm-paper; semantic tokens at /10 give a clear pale-bad / pale-warm tint that scales correctly in dark mode. - Both gain focus-visible:ring-2 focus-visible:ring-{bad,warm}/40. Toggle button (A2A edges): - Active state: bg-blue-950/50 → bg-accent/15 (themes correctly). - Inactive state: bg-surface-card/50 + text-ink-soft → solid bg-surface-card + text-ink-mid; hover bumps to text-ink. Drops the redundant "hover:bg-surface-card/50" identity hover. Icon buttons (Audit, Search, Help): - Same pattern as toggle inactive: solid bg-surface-card + text-ink-mid + text-ink hover, with focus-visible:ring-2 focus-visible:ring-accent/40. Workspace count + bullet separator: - text-ink-soft (3.5:1 on warm-paper) → text-ink-mid (7:1). WS connection status: - "Live": text-ink-soft → text-ink-mid (paired with the green dot). - "Reconnecting": text-ink-soft → text-warm (semantic match for amber dot). - "Offline": text-ink-soft → text-bad (semantic match for red dot). Status text now reinforces the dot colour instead of disappearing on light surfaces. Help popover: - Close button: text-ink-soft → text-ink-mid + focus-visible:underline. - HelpRow body text: text-ink-soft → text-ink-mid (was 3.5:1 on the bg-surface-sunken/45 popover row — failed AA for body text). --- canvas/src/components/Toolbar.tsx | 32 +++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/canvas/src/components/Toolbar.tsx b/canvas/src/components/Toolbar.tsx index 230e5227..a51e9fa0 100644 --- a/canvas/src/components/Toolbar.tsx +++ b/canvas/src/components/Toolbar.tsx @@ -154,10 +154,10 @@ export function Toolbar() { {counts.failed > 0 && ( )} - - + + {counts.roots} workspace{counts.roots !== 1 ? "s" : ""} - {counts.children > 0 && + {counts.children} sub} + {counts.children > 0 && + {counts.children} sub} @@ -172,7 +172,7 @@ export function Toolbar() { type="button" onClick={stopAll} disabled={stopping} - className="flex items-center gap-1.5 px-2.5 py-1 bg-red-950/50 hover:bg-red-900/60 border border-red-800/40 rounded-lg transition-colors disabled:opacity-50" + className="flex items-center gap-1.5 px-2.5 py-1 bg-bad/10 hover:bg-bad/20 border border-bad/40 rounded-lg transition-colors disabled:opacity-50 focus:outline-none focus-visible:ring-2 focus-visible:ring-bad/40" title={`Stop all running tasks (${counts.activeTasks} active)`} aria-label={stopping ? "Stopping all running tasks" : `Stop all running tasks (${counts.activeTasks} active)`} > @@ -191,7 +191,7 @@ export function Toolbar() { type="button" onClick={() => setRestartConfirmOpen(true)} disabled={restartingAll} - className="flex items-center gap-1.5 px-2.5 py-1 bg-amber-950/40 hover:bg-amber-900/50 border border-amber-800/40 rounded-lg transition-colors disabled:opacity-50" + className="flex items-center gap-1.5 px-2.5 py-1 bg-warm/10 hover:bg-warm/20 border border-warm/40 rounded-lg transition-colors disabled:opacity-50 focus:outline-none focus-visible:ring-2 focus-visible:ring-warm/40" title={`Restart ${needsRestartNodes.length} workspace${needsRestartNodes.length === 1 ? "" : "s"} that need to pick up config or secret changes`} aria-label={restartingAll ? "Restarting workspaces" : `Restart ${needsRestartNodes.length} workspace${needsRestartNodes.length === 1 ? "" : "s"} pending config or secret changes`} > @@ -216,10 +216,10 @@ export function Toolbar() { aria-pressed={showA2AEdges} aria-label={showA2AEdges ? "Hide A2A edges" : "Show A2A edges"} title={showA2AEdges ? "Hide A2A delegation edges" : "Show A2A delegation edges (last 60 min)"} - className={`flex items-center justify-center w-7 h-7 border rounded-lg transition-colors ${ + className={`flex items-center justify-center w-7 h-7 border rounded-lg transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-accent/40 ${ showA2AEdges - ? "bg-blue-950/50 hover:bg-blue-900/50 border-blue-800/40 text-accent" - : "bg-surface-card/50 hover:bg-surface-card/50 border-line/40 text-ink-soft hover:text-ink-mid" + ? "bg-accent/15 hover:bg-accent/25 border-accent/50 text-accent" + : "bg-surface-card hover:bg-surface-card/70 border-line text-ink-mid hover:text-ink" }`} > {/* Mesh / network icon */} @@ -255,7 +255,7 @@ export function Toolbar() { }} aria-label="Open audit trail for selected workspace" title="Audit — view ledger for the selected workspace" - className="flex items-center justify-center w-7 h-7 bg-surface-card/50 hover:bg-surface-card/50 border border-line/40 rounded-lg transition-colors text-ink-soft hover:text-ink-mid" + className="flex items-center justify-center w-7 h-7 bg-surface-card hover:bg-surface-card/70 border border-line rounded-lg transition-colors text-ink-mid hover:text-ink focus:outline-none focus-visible:ring-2 focus-visible:ring-accent/40" > {/* Scroll / ledger icon */} useCanvasStore.getState().setSearchOpen(true)} aria-label="Search workspaces" title="Search (⌘K)" - className="flex items-center justify-center w-7 h-7 bg-surface-card/50 hover:bg-surface-card/50 border border-line/40 rounded-lg transition-colors text-ink-soft hover:text-ink-mid" + className="flex items-center justify-center w-7 h-7 bg-surface-card hover:bg-surface-card/70 border border-line rounded-lg transition-colors text-ink-mid hover:text-ink focus:outline-none focus-visible:ring-2 focus-visible:ring-accent/40" >
); } @@ -366,14 +366,14 @@ function WsStatusPill({ status }: { status: "connected" | "connecting" | "discon return (
); } return (
); } @@ -384,7 +384,7 @@ function HelpRow({ shortcut, text }: { shortcut: string; text: string }) { {shortcut} -

{text}

+

{text}

); }