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 pnpm install @dschz/solid-flow yarn install @dschz/solid-flow bun 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, SolidFlowProvider, Controls, Background, MiniMap, addEdge, type EdgeConnection, createEdgeStore, createNodeStore, type Viewport, } from "@dschz/solid-flow"; import "@dschz/solid-flow/styles"; // Required styles import { createStore, produce } from "solid-js/store"; export default function Page() { return ( <SolidFlowProvider> <Flow /> </SolidFlowProvider> ) } function Flow() { // Can invoke useSolidFlow due to parent Page + SolidFlowProvider wrapper. Contains all helper APIs const { .. } = useSolidFlow(); // 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 [viewport, setViewport] = createStore<Viewport>({ x: 100, y: 100, zoom: 5, }); const updateViewport = () => { setViewport("x", (prev) => prev + 10); }; 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 /> <Panel position="top-left"> <button onClick={updateViewport}>Update viewport</button> </Panel> <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
maininstead 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