From 563a35d2ec701a51d4cbabd264c12303fc6783db Mon Sep 17 00:00:00 2001 From: Miguel Palhas Date: Thu, 10 Sep 2026 21:51:53 +0100 Subject: [PATCH] fix(maestro): restore sidebar fill, pane title, and focus dimming after React port The React port replaced CSS class names with Tailwind utilities, breaking three visual contracts: - SessionCard used inline bg-* classes instead of .is-active/.is-open/ .is-previewing that the styles.css cascade targets. - PaneTitle used className "at-title" instead of "attach-title", so font, overflow, and child layout rules never applied. - MultiView's Pane never applied .is-focused or .is-preview, so every pane matched :not(.is-focused) and was dimmed to 0.45 opacity. Closes #256 Co-Authored-By: Claude Opus 4.6 --- web/src/components/layout/MultiView.test.tsx | 2 +- web/src/components/layout/MultiView.tsx | 10 ++++------ web/src/components/layout/PaneTitle.tsx | 4 ++-- web/src/components/sidebar/SessionCard.tsx | 21 +++++++++++--------- 4 files changed, 19 insertions(+), 18 deletions(-) diff --git a/web/src/components/layout/MultiView.test.tsx b/web/src/components/layout/MultiView.test.tsx index 239fdd6..ae4b707 100644 --- a/web/src/components/layout/MultiView.test.tsx +++ b/web/src/components/layout/MultiView.test.tsx @@ -105,7 +105,7 @@ describe("MultiView", () => { expect(screen.getByText("Tab 1 · 1")).toBeTruthy(); const pane = document.querySelector('[data-session-id="s9"]'); expect(pane).toBeTruthy(); - expect(pane!.querySelector(".bg-preview-tint")).toBeTruthy(); + expect(pane!.classList.contains("is-preview")).toBe(true); expect(screen.getByText("preview")).toBeTruthy(); }); diff --git a/web/src/components/layout/MultiView.tsx b/web/src/components/layout/MultiView.tsx index 167a47f..54f5635 100644 --- a/web/src/components/layout/MultiView.tsx +++ b/web/src/components/layout/MultiView.tsx @@ -188,8 +188,9 @@ function Pane({ return (
{leaf.sessionId ? ( diff --git a/web/src/components/layout/PaneTitle.tsx b/web/src/components/layout/PaneTitle.tsx index ba7fcb9..9366019 100644 --- a/web/src/components/layout/PaneTitle.tsx +++ b/web/src/components/layout/PaneTitle.tsx @@ -15,7 +15,7 @@ export interface PaneTitleProps { export function PaneTitle({ sessionId, session, className }: PaneTitleProps) { if (!session) { return ( - + session {sessionId.slice(0, 8)} ); @@ -27,7 +27,7 @@ export function PaneTitle({ sessionId, session, className }: PaneTitleProps) { const icon = tool ? toolIconSvg(tool) : null; return ( - + {name} {showCommand && ( diff --git a/web/src/components/sidebar/SessionCard.tsx b/web/src/components/sidebar/SessionCard.tsx index 0411c18..cecb6b3 100644 --- a/web/src/components/sidebar/SessionCard.tsx +++ b/web/src/components/sidebar/SessionCard.tsx @@ -44,14 +44,17 @@ export interface SessionCardProps { onRenameCancel(): void; } -/** The fill ladder from docs/SIDEBAR.md "Which row is filled", furthest down - * wins. Written as one ordered run so the precedence is the order it reads in. */ -function rowFill(p: SessionCardProps): string { - if (p.active) return "bg-accent-fill"; - if (p.previewing) return "bg-preview-tint"; - if (p.open) return "bg-accent/[0.06]"; - if (p.highlighted) return "bg-preview-tint"; - return ""; +/** The fill ladder from docs/SIDEBAR.md "Which row is filled" — the CSS + * cascade in styles.css carries the actual fills via `.is-active`, `.is-open`, + * `.is-previewing` (all inside `:where()` so source order is the precedence). + * We just apply the right class names here. */ +function rowClasses(p: SessionCardProps): string { + const cls: string[] = []; + if (p.active) cls.push("is-active"); + if (p.open) cls.push("is-open"); + if (p.previewing) cls.push("is-previewing"); + if (p.highlighted) cls.push("is-highlighted"); + return cls.join(" "); } export function SessionCard(props: SessionCardProps) { @@ -62,7 +65,7 @@ export function SessionCard(props: SessionCardProps) { return (