Workflow canvas

An interactive graph with draggable nodes, connections, viewport controls, anchored panels, and node actions.

3 steps · 1 connection
100%

Drag the nodes, connect their handles, or use the form. Select a node to reveal its actions.

Review workflow

3 steps · 1 connection
100%

Drag the nodes, connect their handles, or use the form. Select a node to reveal its actions.

Use it for

  • Import this optional entry and its stylesheet only where a graph is needed. React Flow is an optional peer dependency.
  • Supply nodes, edges, and change callbacks for a controlled graph, or defaultNodes and defaultEdges for engine-owned state. The application persists and executes the graph.
  • Use type=vlak for the supplied node and edge renderers. Custom nodeTypes can compose WorkflowNode and WorkflowToolbar; custom connection lines can use WorkflowConnection.
  • WorkflowPanel anchors overlays in six viewport positions. WorkflowToolbar stays anchored to a selected node and composes Vlak's keyboard-aware Toolbar.
  • WorkflowControls binds the existing CanvasControls to pan, zoom, fit, reset, and interaction lock. React Flow props remain available, including connection validation, viewport changes, and accessibility configuration.
  • For copied source, import @xyflow/react/dist/base.css in a CSS layer named vlak.engine before vlak.components. The package's workflow.css supplies that ordering.
  • Set an explicit height through style when the default 32rem does not suit the container. Use a separate form or Patchbay when users need keyboard-only creation of connections.

Avoid

  • Using Flow, an ordered pipeline layout, as an interactive graph engine.
  • Turning off React Flow's keyboard accessibility without supplying equivalent controls.
  • Treating a connected graph as executed work. Execution, persistence, permissions, and undo history belong to the application.

React package

npm install @noorddev/vlak-react @xyflow/react

Load the stylesheet once at your app root, then import the components you use.

import "@noorddev/vlak-react/css";
import "@noorddev/vlak-react/workflow.css";
import { WorkflowCanvas, WorkflowControls, WorkflowPanel, type WorkflowGraphNode } from "@noorddev/vlak-react/components/workflow-canvas";

Per-component imports are available at @noorddev/vlak-react/components/workflow-canvas.

Copy the source

npx @noorddev/vlak-cli add workflow-canvas

Adds the component and its dependencies to components/vlak/. Follow the StyleX setup to compile the source in your application.

shadcn registry

npx shadcn add https://vlak.dev/r/workflow-canvas.json

Installs the same source through the shadcn CLI.

"use client";
import "@noorddev/vlak-react/workflow.css";
import { addEdge, useNodesState, useEdgesState, type Edge } from "@xyflow/react";
import { WorkflowCanvas, WorkflowControls, WorkflowPanel, type WorkflowGraphNode } from "@noorddev/vlak-react/components/workflow-canvas";

export function ReviewWorkflow() {
  const [nodes, , onNodesChange] = useNodesState<WorkflowGraphNode>([
    { id: "brief", type: "vlak", position: { x: 0, y: 0 }, data: { title: "Read brief", target: false } },
    { id: "review", type: "vlak", position: { x: 380, y: 0 }, data: { title: "Review", source: false } },
  ]);
  const [edges, setEdges, onEdgesChange] = useEdgesState<Edge>([]);
  return <WorkflowCanvas nodes={nodes} edges={edges} onNodesChange={onNodesChange} onEdgesChange={onEdgesChange}
    onConnect={connection => setEdges(current => addEdge({ ...connection, type: "vlak" }, current))}>
    <WorkflowControls />
    <WorkflowPanel position="top-left">Review workflow</WorkflowPanel>
  </WorkflowCanvas>;
}

See the integration example to compose these components with your application's model and data.

WorkflowCanvas

Optional React Flow adapter. Supply a bounded height and controlled changes or defaultNodes/defaultEdges.

WorkflowConnection

Pointer-following connection preview while creating an edge.

WorkflowControls

Binds Vlak's canvas controls to the graph viewport and interaction lock.

PropTypeDefaultDescription
labelstring"Workflow controls"

WorkflowEdge

Bezier edge with engine-managed hit testing and optional temporary or animated state.

WorkflowNode

A graph node surface. Render inside React Flow so its handles use the graph's geometry.

PropTypeDefaultDescription
titlerequiredReactNode
descriptionReactNode
footerReactNode
actionsReactNode
sourcebooleantrue
targetbooleantrue
sourcePositionPositionPosition.Right
targetPositionPositionPosition.Left
selectedbooleanfalse
connectablebooleantrue

Also accepts Omit<HTMLAttributes<HTMLDivElement>, "title">.

The ref reaches HTMLDivElement.

WorkflowPanel

Overlay anchored to one of React Flow's six viewport positions.

WorkflowToolbar

Node-anchored toolbar with Vlak's arrow-key action navigation.

PropTypeDefaultDescription
actionsrequiredToolbarAction[]
labelrequiredstring
KeysDoes
TabFocuses nodes, edges, viewport controls, and supplied actions
Enter, SpaceSelects a focused node or edge through React Flow
Arrow keysMoves a selected, draggable node; moves between actions inside the node toolbar
Delete, BackspaceDeletes selected graph elements through the supplied change callbacks
EscapeCancels the current graph selection or connection gesture
  • React Flow supplies keyboard movement, focusable nodes and edges, instruction text, and movement announcements. ariaLabelConfig can localize those messages.
  • Visible connection handles have 44px pointer targets. The application should provide a form-based connection action for keyboard-only creation.
  • The node action Toolbar retains its single Tab stop and arrow-key focus movement.
  • Animated edges stop moving with reduced motion. Surfaces use Vlak paper, ink, hairlines, and 4px corners.

The same styles are available as CSS. Native HTML provides the static presentation; React or application code supplies state updates and actions.

npm install @noorddev/vlak
import "@noorddev/vlak/css";
<section class="rs-workflow-canvas" aria-label="Workflow"><div class="rs-workflow-canvas-node"><header class="rs-workflow-canvas-header"><div class="rs-workflow-canvas-title">Review brief</div></header><div class="rs-workflow-canvas-content">Summarize the supplied document.</div></div></section>

Classes

.rs-workflow-canvas.rs-workflow-canvas-node.rs-workflow-canvas-selected.rs-workflow-canvas-header.rs-workflow-canvas-title.rs-workflow-canvas-description.rs-workflow-canvas-content.rs-workflow-canvas-footer.rs-workflow-canvas-handle.rs-workflow-canvas-dot.rs-workflow-canvas-edge.rs-workflow-canvas-temporary.rs-workflow-canvas-animated.rs-workflow-canvas-endpoint.rs-workflow-canvas-panel.rs-workflow-canvas-controls