forked from molecule-ai/molecule-core
fix(canvas): wire ReactFlow colorMode to resolvedTheme
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) <noreply@anthropic.com>
This commit is contained in:
parent
88ef70431e
commit
df7edfcd3f
@ -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() {
|
||||
</a>
|
||||
<main id="canvas-main" className="w-screen h-screen bg-surface">
|
||||
<ReactFlow
|
||||
colorMode="dark"
|
||||
colorMode={resolvedTheme}
|
||||
nodes={nodes}
|
||||
edges={allEdges}
|
||||
onNodesChange={onNodesChange}
|
||||
@ -273,7 +282,9 @@ function CanvasInner() {
|
||||
variant={BackgroundVariant.Dots}
|
||||
gap={24}
|
||||
size={1}
|
||||
color="#27272a"
|
||||
// Match the line token so dots fade with the surface.
|
||||
// Hard-coded zinc-800 was invisible on warm-paper.
|
||||
color={resolvedTheme === "dark" ? "#27272a" : "#d4d0c4"}
|
||||
/>
|
||||
<Controls
|
||||
className="!bg-surface-sunken/90 !border-line/50 !rounded-lg !shadow-xl !shadow-black/20 [&>button]:!bg-surface-card [&>button]:!border-line/50 [&>button]:!text-ink-mid [&>button:hover]:!bg-surface-card [&>button:hover]:!text-ink"
|
||||
@ -281,7 +292,9 @@ function CanvasInner() {
|
||||
/>
|
||||
<MiniMap
|
||||
className="!bg-surface-sunken/90 !border-line/50 !rounded-lg !shadow-xl !shadow-black/20"
|
||||
maskColor="rgba(0, 0, 0, 0.7)"
|
||||
// Mask dims off-viewport areas; tint matches the surface so
|
||||
// the dimming doesn't show as a black bar in light mode.
|
||||
maskColor={resolvedTheme === "dark" ? "rgba(0, 0, 0, 0.7)" : "rgba(232, 226, 211, 0.7)"}
|
||||
nodeColor={(node) => {
|
||||
// Parents show as a filled region — hierarchy visible at
|
||||
// a glance in the minimap without needing to zoom.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user