Skip to content

FlowCanvas theming ​

The values listed below are exposed as --rozie-flow-* custom properties, each with a built-in fallback, so FlowCanvas works with zero configuration and re-skins by remapping tokens. The structural rules compile per-leaf and are not consumer-overridable.

css
:root {
  --rozie-flow-accent: #3b82f6;
  --rozie-flow-bg: #f7f8fa;
  --rozie-flow-node-bg: #ffffff;
  --rozie-flow-node-body-padding: 0.5rem 0.75rem;
}

Tokens ​

accent — the shared selected/active color. ​

TokenDefault
--rozie-flow-accent#3b82f6

canvas surface ​

TokenDefault
--rozie-flow-bg#f7f8fa
--rozie-flow-grid-dot-colorrgba(0, 0, 0, 0.08)
--rozie-flow-grid-size20px
--rozie-flow-border-colorrgba(0, 0, 0, 0.1)
--rozie-flow-radius8px

node chrome ​

TokenDefault
--rozie-flow-node-bg#ffffff
--rozie-flow-node-borderrgba(0, 0, 0, 0.16)
--rozie-flow-node-radius8px
--rozie-flow-node-shadow0 2px 6px rgba(0, 0, 0, 0.12)
--rozie-flow-node-title-fg#1f2937
--rozie-flow-node-selected-ringrgba(59, 130, 246, 0.5)
--rozie-flow-node-selected-shadow0 2px 8px rgba(0, 0, 0, 0.15)

D-09: a node editor has real full-bleed body cases — an image, a sparkline, a nested chart — where the consumer needs 0 padding; a hardcoded value leaves them fighting it with a negative margin. Default matches .rozie-flow-node__title's padding so body and title line up.

TokenDefault
--rozie-flow-node-body-padding0.5rem 0.75rem

ports + sockets ​

D-15: under box-sizing: border-box this token now means the socket's RENDERED diameter (the 2px border sits inside it, not added on top). The default render is unchanged from the previous 12px content-box value — only the ~2px centring error is corrected. A consumer who previously hand-set 12px now gets a genuinely 12px socket; see the phase changeset.

TokenDefault
--rozie-flow-port-fg#6b7280
--rozie-flow-socket-size16px
--rozie-flow-socket-bg#94a3b8
--rozie-flow-socket-border-color#ffffff
--rozie-flow-socket-border-width2px
--rozie-flow-socket-ringrgba(0, 0, 0, 0.2)

D-11 (ISSUE-6): opacity-only, deliberately carrying no colour — a colour-based hint would need an entry in all three hand-maintained dark palette copies, the very triplicate that produced both ISSUE-3 and A4. Opacity is immune to that drift, reads as "unavailable" rather than "error", and works against any consumer accent. Light-only by design; adds ZERO dark-block entries.

TokenDefault
--rozie-flow-socket-incompatible-opacity0.3

connections ​

TokenDefault
--rozie-flow-connection-stroke#64748b
--rozie-flow-connection-width3px
--rozie-flow-connection-selected-width4px
--rozie-flow-connection-label-fg#334155
--rozie-flow-connection-label-halo#ffffff

built-in Controls overlay ​

TokenDefault
--rozie-flow-control-bg#ffffff
--rozie-flow-control-fg#334155
--rozie-flow-control-borderrgba(0, 0, 0, 0.16)
--rozie-flow-control-radius6px
--rozie-flow-control-shadow0 1px 3px rgba(0, 0, 0, 0.14)
--rozie-flow-control-hover-bg#f1f5f9
--rozie-flow-control-active-bg#e2e8f0
--rozie-flow-control-selected-bg#dbeafe
--rozie-flow-control-selected-fg#1d4ed8
--rozie-flow-control-inset10px
--rozie-flow-control-btn-size28px

marquee (mode:'select') ​

D-25: --rozie-flow-marquee-bg derives off --rozie-flow-accent in BOTH light and dark, so overriding accent alone recolors the marquee too — zero dark-block entries needed. The derivation lives at the component's read site (color-mix(in srgb, var(--rozie-flow-accent) 12%, transparent)), not here, so it is resolved against the accent the canvas actually inherits. color-mix() needs an evergreen browser; where it does not parse, the marquee background is transparent.

TokenDefault
--rozie-flow-marquee-radius2px

MiniMap overlay ​

TokenDefault
--rozie-flow-minimap-bgrgba(255, 255, 255, 0.82)
--rozie-flow-minimap-borderrgba(0, 0, 0, 0.16)
--rozie-flow-minimap-shadow0 1px 3px rgba(0, 0, 0, 0.14)

The two tokens below are read from JS via a getComputedStyle-backed flowToken() lookup at render time (canvas paint code, not a CSS var()) — declared here (and correctly base-only per the probe) so the public surface stays discoverable in one place.

TokenDefault
--rozie-flow-minimap-node-fill#94a3b8
--rozie-flow-minimap-maskrgba(15, 23, 42, 0.18)

resize handle (the four corner drag affordances on the canvas) ​

TokenDefault
--rozie-flow-resize-handle-bg#ffffff
--rozie-flow-resize-handle-size8px
--rozie-flow-resize-handle-radius2px

NodeToolbar overlay ​

TokenDefault
--rozie-flow-toolbar-bg#ffffff
--rozie-flow-toolbar-borderrgba(0, 0, 0, 0.16)
--rozie-flow-toolbar-shadow0 2px 8px rgba(0, 0, 0, 0.18)
--rozie-flow-toolbar-btn-bg#f8fafc
--rozie-flow-toolbar-btn-fg#334155
--rozie-flow-toolbar-btn-borderrgba(0, 0, 0, 0.14)
--rozie-flow-toolbar-btn-hover-bg#eef2f7
--rozie-flow-toolbar-delete-fg#b91c1c

typography ​

Splitting the family out from the four per-role sizes means rebranding is ONE override, while each role's size stays independently tunable — the two knobs solve different problems and shouldn't be conflated.

TokenDefault
--rozie-flow-font-familysystem-ui, sans-serif
--rozie-flow-node-font-size13px
--rozie-flow-control-font-size16px
--rozie-flow-toolbar-font-size12px
--rozie-flow-connection-label-font-size11px

focus ring ​

The ring's colour, --rozie-flow-focus-ring, defaults to --rozie-flow-accent at the read site, so the ring follows dark and any accent override with ZERO entries in the three hand-maintained dark palettes. Do not "helpfully" hardcode a colour for it — that would reintroduce exactly the drift D-20's predicate exists to catch.

TokenDefault
--rozie-flow-focus-ring-width2px

Defaulted where FlowCanvas reads them ​

Public, but declared nowhere by base.css: the fallback below applies only while no scope sets the token, and it is resolved at the component itself — so it follows a value set on any ancestor (a token it defaults to included).

TokenDefault
--rozie-flow-connection-selected-strokevar(--rozie-flow-accent, #3b82f6)
--rozie-flow-control-selected-bordervar(--rozie-flow-accent, #3b82f6)
--rozie-flow-focus-ringvar(--rozie-flow-accent, #3b82f6)
--rozie-flow-marquee-bgcolor-mix(in srgb, var(--rozie-flow-accent, #3b82f6) 12%, transparent)
--rozie-flow-marquee-bordervar(--rozie-flow-accent, #3b82f6)
--rozie-flow-node-selected-bordervar(--rozie-flow-accent, #3b82f6)
--rozie-flow-resize-handle-bordervar(--rozie-flow-accent, #3b82f6)
--rozie-flow-socket-hover-bgvar(--rozie-flow-accent, #3b82f6)

Design-system bridges ​

Each package ships token presets that map FlowCanvas's tokens onto a known design system's published CSS variables — import base.css first, then a bridge:

ts
import '@rozie-ui/rete-react/themes/base.css';
import '@rozie-ui/rete-react/themes/bootstrap.css';
import '@rozie-ui/rete-react/themes/material.css';
import '@rozie-ui/rete-react/themes/shadcn.css';

See also ​

Pre-1.0 — APIs may change between minor versions.