Workflow Canvas
Headless node-based workflow canvas. The component renders the graph and emits events; your app owns modals, drawers, and inspectors via onNodeSelect, onNodeDoubleClick, renderNodePicker, and renderControls.
Default
Controlled workflow with built-in add-node controls and a right-click node picker.
Add nodes with the + control, or right-click the canvas for the node picker.
Sign in to view this example's source code.
Sign inNode inspector
App-owned dialog wired via onNodeSelect and onNodeDoubleClick - canvas stays headless.
Select a node to open the inspector, or double-click to open it directly. Dialog UI lives in the app layer.
No selectionSign in to view this example's source code.
Sign inProps
| Name | Type | Default | Description |
|---|---|---|---|
| nodes | WorkflowNode[] | Required | Workflow nodes with id, type, position, and display/configuration data |
| edges | WorkflowEdge[] | Required | Connections between workflow nodes |
| editable | boolean | true | Enable dragging, connecting, selection, and deletion |
| onNodesChange | (nodes: WorkflowNode[]) => void | undefined | Called with normalized workflow nodes after canvas changes |
| onEdgesChange | (edges: WorkflowEdge[]) => void | undefined | Called with normalized workflow edges after canvas changes |
| onConnect | (connection: Connection) => void | undefined | Called when a new edge connection is created |
| onNodeSelect | (node: WorkflowNode | null) => void | undefined | Selection event - wire to app state; open drawers/modals in your layer, not inside the canvas |
| onNodeDoubleClick | (node: WorkflowNode) => void | undefined | Double-click event - convenience hook to open an inspector or dialog without embedding UI in the canvas |
| onAddNode | (node: WorkflowNode) => void | undefined | Called when a node is added via the canvas API |
| onPaneContextMenu | (position, event) => void | undefined | Called on pane right-click with flow coordinates |
| renderNodePicker | (args) => ReactNode | undefined | Render a node picker at flow position; receives addNode and close |
| onNodeDrop | (event, position, type) => void | undefined | Optional drag-and-drop hook for external node sources (use WORKFLOW_NODE_DRAG_TYPE) |
| renderControls | (api: WorkflowCanvasAPI) => ReactNode | undefined | Custom controls slot with imperative canvas API |
| showAddNodeInControls | boolean | false | Show add-node menu on default zoom controls |
| ref | WorkflowCanvasHandle | undefined | Imperative API: addNode, createNode, getNodes, fitView, zoomIn, zoomOut, screenToFlowPosition |
| height | string | number | undefined | Explicit canvas height; parent should size the container when omitted |
| autoFitView | boolean | false | Fit viewport to nodes on mount |
| minimap | boolean | ReactNode | undefined (built-in minimap) | Built-in minimap when omitted or true; false to hide; ReactNode for a custom minimap |
| controls | ReactNode | false | undefined (built-in zoom controls) | Built-in controls when omitted; false to hide; ReactNode for custom controls |
| background | boolean | true | Toggle the dot grid background |