Flitter
Diagram

Node and edge editors with React Flow's interactions, drawn by Flitter on SVG or Canvas.

Layouts
5
Edge paths
5
Renderers
2
Deploy pipeline
  • Drag a node
  • Wheel or pinch to zoom
  • Shift+drag to select
  • Drag from a handle to connect
  • Drag an edge end to reconnect
  • Backspace deletes

Nodes in, editor out

Describe nodes and edges as plain objects, the same shape React Flow uses. FlowDiagram returns a widget with panning, zooming, selection, connecting, controls and a minimap already wired.

The editor keeps its own state. Change callbacks tell you what happened, and a FlowController lets you change it from outside.

Walk through the quick start
import Widget from "@flitterjs/react";
import type { FlowEdge, FlowNode } from "flitter-ui/diagram";
import { FlowDiagram } from "@/components/diagram/flow-diagram";

const nodes: FlowNode[] = [
  { id: "1", type: "input", position: { x: 0, y: 0 }, data: { label: "Input" } },
  { id: "2", position: { x: 0, y: 120 }, data: { label: "Default" } },
  { id: "3", type: "output", position: { x: 0, y: 240 }, data: { label: "Output" } },
];

const edges: FlowEdge[] = [
  { id: "e1-2", source: "1", target: "2", animated: true },
  { id: "e2-3", source: "2", target: "3", markerEnd: "arrowclosed" },
];

// Create the widget once. A new instance remounts the editor.
const diagram = FlowDiagram({ nodes, edges, fitView: true });

export default function App() {
  return <Widget widget={diagram} width="100%" height="480px" renderer="canvas" />;
}

React Flow's interactions

Drag to pan, wheel to zoom, Shift+drag to box-select, drag between handles to connect, drag an edge end to reconnect it. Defaults match React Flow.

Mouse and touch

On touch screens a tap selects, one finger drags nodes or pans, and two fingers pinch to zoom around their midpoint.

Resizer and toolbar

Selected nodes can show resize controls and a toolbar that stays at screen size, like React Flow's NodeResizer and NodeToolbar.

Rebuilds only what changed

Each node and edge widget listens to its own signal. Dragging a node rebuilds that node and its edges; panning and zooming rebuild none.

SVG or Canvas

The editor is a Flitter widget tree, so either renderer draws it. Nodes, edges, the background and the minimap all follow.

Pluggable layouts

Layered, tree, force, grid and circular ship built in, and children are laid out inside their group. dagre or ELK plug in as one async function.

One graph, five layouts

Every node below starts at the origin. The layout runs once the nodes are measured, then fits the view. Switch the algorithm to see the same graph placed differently.

Bring your own nodes

A node type is a builder that returns any Flitter widget, plus the handles it exposes. Handles are declared, not measured, so edges know where to attach before anything is painted.

FlowDiagram({
  nodes,
  edges,
  nodeTypes: {
    // Any Flitter widget, plus the handles it exposes
    task: {
      build: ({ node, selected }) =>
        Container({
          width: 180,
          padding: EdgeInsets.all(12),
          decoration: new BoxDecoration({
            color: selected ? "#fff7e6" : "#ffffff",
            border: Border.all({ color: "#f59e0b" }),
            borderRadius: BorderRadius.circular(8),
          }),
          child: Text(String(node.data.label)),
        }),
      handles: [
        { type: "target", position: "left" },
        { type: "source", position: "right" },
      ],
    },
  },
  layout: { algorithm: layeredLayout, options: { direction: "LR" } },
});