Solid Flow is a port of React Flow and Svelte Flow for SolidJS.
☣️ Solid Flow is alpha and currently under development. The API intends to follow React/Svelte Flow closely but some things might change for the sake of SolidJS. ☣️
- onlyRenderVisibleElements: render only visible elements.
- Custom MiniMap Nodes: define custom minimap jsx node elements.
- Edge Reconnect Anchors: the ability to re-connect already connected edges.
- Easy to use: Seamless zooming and panning, single- and multi selection of graph elements and keyboard shortcuts are supported out of the box
- Customizable: Different node types (Input, Output, Default, Group) and edge types (Bezier, Straight, Step, SmoothStep) with full support for custom nodes and edges
- Fast rendering: Only nodes that have changed are re-rendered using SolidJS's fine-grained reactivity
- Rich Plugin Ecosystem: Background patterns, Interactive MiniMap, Zoom Controls, Node Toolbar, and Node Resizer components
- Powerful Hooks: Comprehensive set of reactive hooks for nodes, edges, viewport, connections, and data management
- Full Accessibility: Complete keyboard navigation, screen reader support, ARIA labels, and focus management
- Drag & Drop: Built-in dragging for nodes, external drag-and-drop support, and customizable drag handles
- Advanced Features: Node grouping, intersection detection, connection validation, and subflow support
- TypeScript First: Fully typed API with generic type support and IntelliSense integration
The easiest way to get the latest version of Solid Flow is to install it via npm, yarn or pnpm:
npm install @dschz/solid-flow
This is a basic example to get you started. For more advanced examples and full API documentation, explore the playground examples included in this repository.
import {
SolidFlow,
Controls,
Background,
MiniMap,
addEdge,
type EdgeConnection,
createEdgeStore,
createNodeStore,
} from "@dschz/solid-flow";
import "@dschz/solid-flow/styles"; // Required styles
export default function Flow() {
// Use createNodeStore and createEdgeStore for reactive state management
const [nodes, setNodes] = createNodeStore([
{
id: "1",
type: "input",
data: { label: "Input Node" },
position: { x: 250, y: 0 },
},
{
id: "2",
type: "default",
data: { label: "Default Node" },
position: { x: 100, y: 100 },
},
{
id: "3",
type: "output",
data: { label: "Output Node" },
position: { x: 250, y: 200 },
},
]);
const [edges, setEdges] = createEdgeStore([
{ id: "e1-2", source: "1", target: "2" },
{ id: "e2-3", source: "2", target: "3" },
]);
const onConnect = (connection: EdgeConnection) => {
/**
* Solid Flow updates the node/edge stores internally. The user-land edge store will have the connection inserted by the time onConnect fires so we can just go ahead and update the state of it
*/
setEdges(
(edge) => edge.id === connection.id,
produce((edge) => {
edge.animated = true;
}),
);
};
return (
<SolidFlow nodes={nodes} edges={edges} onConnect={onConnect} fitView>
<Controls />
<MiniMap />
<Background variant="dots" />
</SolidFlow>
);
}
- InputNode - Nodes with source handles only (starting points)
- OutputNode - Nodes with target handles only (ending points)
- DefaultNode - Standard nodes with both source and target handles
- GroupNode - Container nodes for organizing other nodes
- BezierEdge - Smooth curved connections (default)
- StraightEdge - Direct straight line connections
- StepEdge - Right-angle step connections
- SmoothStepEdge - Rounded step connections
- Background - Customizable canvas backgrounds (dots, lines, cross patterns)
- Controls - Zoom in/out, fit view, lock/unlock interactions
- MiniMap - Interactive overview with viewport indicator
- NodeToolbar - Context-sensitive toolbars for nodes
- NodeResizer - Real-time node resizing with handles
// Main flow instance with full API
const solidFlow = useSolidFlow();
// Reactive access to nodes and edges
const nodes = useNodes();
const edges = useEdges();
// Viewport control and monitoring
const viewport = useViewport();
// Connection state during drag operations
const connection = useConnection();
// Reactive access to node data
const nodeData = useNodesData(["node-1", "node-2"]);
// Node connection information
const connections = useNodeConnections("node-1");
// Create reactive stores (replaces signals)
const [nodes, setNodes] = createNodeStore(initialNodes);
const [edges, setEdges] = createEdgeStore(initialEdges);
// Update stores with SolidJS patterns
import { produce } from "solid-js/store";
setNodes(
(node) => node.id === "1",
produce((node) => {
node.position.x += 20;
}),
);
// Add new connections
setEdges(addEdge(connection, edges));
// Coordinate transformations (via useSolidFlow)
const { screenToFlowPosition, flowToScreenPosition } = useSolidFlow();
// Node/edge utilities
getNodesBounds(nodes);
getIntersectingNodes(node, nodes);
Create fully customized components with multiple handles:
import { Handle, type NodeProps } from "@dschz/solid-flow";
// Type-safe custom node component
function CustomNode(props: NodeProps<{ label: string }, "custom">) {
return (
<div class="custom-node" style={{ padding: "10px", background: "white" }}>
<Handle type="target" position="top />
<div>{props.data.label}</div>
<Handle type="source" position="bottom" id="output-a" />
<Handle type="source" position="bottom id="output-b" style={{ left: "80%" }} />
</div>
);
}
// Create type-safe node types
const nodeTypes = {
custom: CustomNode,
} satisfies NodeTypes;
// Use with typed store
const [nodes] = createNodeStore<typeof nodeTypes>([...]);
<SolidFlow nodeTypes={nodeTypes} nodes={nodes} ... />
import { type Connection } from "@dschz/solid-flow";
const isValidConnection = (connection: Connection) => {
// Custom validation logic
return connection.source !== connection.target;
};
const onConnect = (connection: Connection) => {
console.log("New connection:", connection);
setEdges(addEdge(connection, edges));
};
<SolidFlow
isValidConnection={isValidConnection}
onConnect={onConnect}
...
/>
<SolidFlow
onNodeClick={(event, node) => console.log("Node clicked:", node)}
onNodeDrag={(event, node) => console.log("Node dragged:", node)}
onEdgeClick={(event, edge) => console.log("Edge clicked:", edge)}
onPaneClick={(event) => console.log("Pane clicked")}
onSelectionChange={(params) => console.log("Selection changed:", params)}
/>
Solid Flow includes comprehensive accessibility features:
- Full keyboard navigation support
- Screen reader compatibility with ARIA labels
- Focus management and visual indicators
- High contrast and color mode support
- Customizable keyboard shortcuts
- Reactive Updates: Only re-renders components when their specific data changes
- Viewport Optimization: Option to render only visible elements (coming soon)
- Memory Efficient: Optimized data structures for large graphs
- Stress Tested: Handles hundreds of nodes smoothly
The repository includes a comprehensive playground with 25+ examples:
- Basic Usage - Simple flows and interactions
- Custom Nodes - Creating specialized node types
- Edge Types - Different connection styles
- Drag & Drop - External elements and node creation
- Validation - Connection rules and constraints
- Subflows - Hierarchical node organization
- Performance - Large dataset handling
- Accessibility - Keyboard navigation and screen readers
Run the examples locally:
bun start
Some pre-requisites before install dependencies:
- Install Node Version Manager (NVM)
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
- Install Bun
curl -fsSL https://bun.sh/install | bash
nvm use
bun install
bun start
bun run lint # checks source for lint violations
bun run format # checks source for format violations
bun run lint:fix # fixes lint violations
bun run format:fix # fixes format violations
The only requirements when contributing are:
- You keep a clean git history in your branch
- rebasing
main
instead of making merge commits.
- rebasing
- Using proper commit message formats that adhere to conventional commits
- Additionally, squashing (via rebase) commits that are not conventional commits
- CI checks pass before merging into
main