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-builderAlso installs: Toggle-group
Requires: @xyflow/react
Demo
Props
| Name | Type | Default | Description |
|---|---|---|---|
| defaultGraph | WorkflowGraph | - | 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. |
| height | number | 500 | Canvas height in pixels. |
| className | string | "" | 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. |
| readOnly | boolean | false | Renders 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.
| Key | Function |
|---|---|
| tab | Moves focus to the next node, toolbar control, or inspector field, following the page's normal tab order. |
| shift+tab | Moves focus to the previous stop in that same order. |
| enter | Selects the focused node and opens the inspector panel, or activates the focused button. |
| space | Selects the focused node and opens the inspector panel, or activates the focused button. |
| up arrow | Moves the selected node up (Shift moves it further per press). |
| down arrow | Moves the selected node down (Shift moves it further per press). |
| left arrow | Moves the selected node left (Shift moves it further per press). |
| right arrow | Moves the selected node right (Shift moves it further per press). |
| escape | Deselects the focused node and closes the inspector panel. |
| delete | Deletes the selected node or edge (disabled in read-only mode). |
| backspace | Deletes the selected node or edge (disabled in read-only mode). |