Tell React Flow which theme it is drawing in

React Flow stamps `colorMode` on its wrapper as a class and defaults it to
`light`. The app's own token scopes are named `.light` / `.dark` — the classes
that let a dashboard be forced to one theme inside a shell on the other — so
every canvas was silently redeclaring the light palette on its own subtree:
white node cards and a white canvas in dark mode, with the inherited
`--foreground` text still near-white and therefore invisible. Home's neurons
had the same fault, drawn with white ring gaps and the light `--primary`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016ZeGnqVsf5VHQqvz4HdUhN
This commit is contained in:
2026-08-23 09:29:30 +02:00
co-authored by Claude Opus 5
parent e25351f515
commit 98bf8fb7b0
2 changed files with 12 additions and 0 deletions
@@ -31,6 +31,7 @@ import {
type MessageSpec,
type NodeDef_Input,
} from "@/client"
import { useTheme } from "@/components/theme-provider"
import { Button } from "@/components/ui/button"
import {
Dialog,
@@ -205,6 +206,7 @@ function FlowEditorInner({
const { showErrorToast, showSuccessToast } = useCustomToast()
const { fitView } = useReactFlow()
const updateNodeInternals = useUpdateNodeInternals()
const { resolvedTheme } = useTheme()
const { data: flows } = useSuspenseQuery(flowsQueryOptions())
const { data: detail } = useSuspenseQuery(flowQueryOptions(flowName))
@@ -1076,6 +1078,10 @@ function FlowEditorInner({
nodeTypes={nodeTypes}
edgeTypes={edgeTypes}
proOptions={{ hideAttribution: true }}
// React Flow stamps this on the wrapper as a class, and the app's own
// token scopes are named `.light` / `.dark` (index.css) — so leaving it
// unset re-themes the whole canvas to light inside a dark shell.
colorMode={resolvedTheme}
fitView
fitViewOptions={FIT_VIEW}
// Low enough that the fit can always show the whole graph. A phone is