crispmeasured from Attio

FlowCanvas

A pannable, zoomable node canvas — Attio's Workflows editor.

The node-graph editor behind Attio's Workflows: a dotted-grid canvas with draggable node cards connected by edges. Drag a node to move it, drag the background to pan, and use the toolbar to zoom. You render the node bodies; the canvas owns dragging, panning, edges, and the grid.

Preview

Attribute value changed
When a Deal's stage changes…
Filter
Only continue if the new stage…
Broadcast message
Notify all workspace members
100%

Usage

import { FlowCanvas, type FlowNode } from "crisp";

const [nodes, setNodes] = useState<FlowNode[]>([
  { id: "trigger", x: 20, y: 90 },
  { id: "filter", x: 320, y: 90 },
]);

<FlowCanvas
  nodes={nodes}
  onNodesChange={setNodes}
  edges={[{ from: "trigger", to: "filter" }]}
  renderNode={(n) => <MyNodeCard node={n} />}
/>;

API

PropTypeDefaultDescription
nodesT extends { id, x, y }[]Positioned nodes (controlled).
edges{ from, to }[]Connections by node id (bezier + end dots).
onNodesChange(nodes: T[]) => voidFires after a node drag with the moved list.
renderNode(node: T) => ReactNodeRenders a node's body.
nodeWidthnumber240Width used to anchor edges on the node's right/left.
nodeHeightnumber64Height used to anchor edges at the vertical middle.

Notes

  • Controlled. The parent owns nodes; a drag calls onNodesChange — so a flow and a list can be two views over the same graph.
  • Interactions. Node drag / background pan use pointer events (scaled by zoom); the toolbar zooms 50–150% and resets.
  • Edges are SVG beziers from each source node's right-middle to the target's left-middle, with brand connection dots.

On this page