From df7edfcd3fcfa3a542c7a6953d81a5b5ab448527 Mon Sep 17 00:00:00 2001 From: Hongming Wang Date: Sun, 3 May 2026 04:11:35 -0700 Subject: [PATCH] fix(canvas): wire ReactFlow colorMode to resolvedTheme MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR #2555 (Tailwind v4 + warm-paper) migrated all canvas chrome (toolbar, side panel, modal layer) to semantic tokens, but missed the React Flow viewport's `colorMode="dark"` literal — and two paired hardcoded dark literals on the Background dot color and MiniMap mask. Net result on prod: the user picked light mode, the toolbar flipped warm-paper, but the canvas backplate, edges, dots, controls, and minimap stayed black — visibly half-themed. Three coordinated fixes inside the canvas viewport: - ReactFlow `colorMode={resolvedTheme}` so the library's own dark/light styles flip with the user's choice. - Background dot color picks the line-soft tone in light mode (zinc-800 was invisible-on-cream). - MiniMap maskColor warm-tints the off-viewport dim so the unselected region doesn't render as a hard black bar over warm-paper. Verification: - `npx tsc --noEmit` clean - `npx vitest run` 188/188 pass - (will browser-verify post-redeploy on hongming.moleculesai.app) Co-Authored-By: Claude Opus 4.7 (1M context) --- canvas/src/components/Canvas.tsx | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/canvas/src/components/Canvas.tsx b/canvas/src/components/Canvas.tsx index f677862a..ebd8a1d3 100644 --- a/canvas/src/components/Canvas.tsx +++ b/canvas/src/components/Canvas.tsx @@ -13,6 +13,7 @@ import { import "@xyflow/react/dist/style.css"; import { useCanvasStore } from "@/store/canvas"; +import { useTheme } from "@/lib/theme-provider"; import { A2ATopologyOverlay } from "./A2ATopologyOverlay"; import { WorkspaceNode } from "./WorkspaceNode"; import { SidePanel } from "./SidePanel"; @@ -69,6 +70,14 @@ export function Canvas() { } function CanvasInner() { + // ReactFlow's `colorMode` prop drives the styling of every viewport + // primitive it renders directly (background dots, edge defaults, + // selection rings, controls, minimap mask). Pre-fix this was hard-pinned + // to "dark" — so on light theme the chrome (toolbar, side panel) flipped + // to warm-paper but the canvas backplate + edges stayed black, leaving a + // half-themed page. Pull resolvedTheme so the canvas matches the user's + // selected mode (and the system preference when they pick "system"). + const { resolvedTheme } = useTheme(); const rawNodes = useCanvasStore((s) => s.nodes); const edges = useCanvasStore((s) => s.edges); const a2aEdges = useCanvasStore((s) => s.a2aEdges); @@ -250,7 +259,7 @@ function CanvasInner() {
{ // Parents show as a filled region — hierarchy visible at // a glance in the minimap without needing to zoom.