WorkflowBuilder

Drag-and-drop graph editor for generic input/output nodes. Select a node to edit its title, description, and ports in the side panel. Outputs a serializable WorkflowGraph via onChange.

Installation

npx dafink-ui add workflow-builder

Also installs: Toggle-group

Requires: @xyflow/react

Demo

Props

NameTypeDefaultDescription
defaultGraphWorkflowGraph-Pre-populated graph loaded on first render. Not reactive after mount; state is managed internally.
onChange(graph: WorkflowGraph) => void-Fired after every change: node move, edge connection, inspector panel edit (title/description/ports), or node add/delete.
heightnumber500Canvas height in pixels.
classNamestring""Additional classes on the root container.
defaultDirection'horizontal' | 'vertical''horizontal'Initial flow orientation. Not reactive after mount; the user can switch it live via the Layout toggle in the toolbar, unless readOnly is set.
readOnlybooleanfalseRenders a static diagram: hides the toolbar and node inspector, and disables dragging, connecting, and deleting.

Examples

WorkflowBuilder

Drag nodes to reposition. Drag from an output handle to an input handle to connect them. Click a node to select it and open its inspector panel on the right — edit its title, description, and add/remove/rename its input and output ports there. Hover a node and click × (or press Delete/Backspace) to remove it. Click ▶ Run in the toolbar to animate execution: a pulse travels each edge, nodes ring when active and dim with ✓ when complete, starting from every node with no inputs. Nodes with multiple outputs fire all of them simultaneously. Click ◼ Stop to cancel mid-run.

Pre-built graph via defaultGraph

Pass a WorkflowGraph to defaultGraph to pre-populate the canvas.

Accessibility

WorkflowBuilder relies on React Flow's built-in keyboard support rather than a custom roving-tabindex implementation: every node renders with role="group", tabIndex=0, and aria-roledescription="node", so nodes sit in normal document tab order alongside the toolbar buttons, the Layout ToggleGroup, and — once a node is selected — the inspector panel's form fields. Creating a connection between two nodes is pointer/touch-only: each connection Handle is a plain, non-focusable div with only mouse/touch/click handlers, so there is no keyboard path to wire two ports together. Everything else — selecting, moving, and deleting nodes and edges — is fully keyboard-operable, and none of it fires in readOnly mode.

KeyFunction
tabMoves focus to the next node, toolbar control, or inspector field, following the page's normal tab order.
shift+tabMoves focus to the previous stop in that same order.
enterSelects the focused node and opens the inspector panel, or activates the focused button.
spaceSelects the focused node and opens the inspector panel, or activates the focused button.
up arrowMoves the selected node up (Shift moves it further per press).
down arrowMoves the selected node down (Shift moves it further per press).
left arrowMoves the selected node left (Shift moves it further per press).
right arrowMoves the selected node right (Shift moves it further per press).
escapeDeselects the focused node and closes the inspector panel.
deleteDeletes the selected node or edge (disabled in read-only mode).
backspaceDeletes the selected node or edge (disabled in read-only mode).