15 Advanced React Flow Interactions, Recreated in an Open Workbench
Running React Flow Pro's advanced interactions: 15 hands-on examples covering layout, edges, and multi-user collaboration
This project is for learning purposes only, for studying how to recreate React Flow Pro's advanced examples. It is not for any commercial use. Feature suggestions for practical flowchart and canvas editor directions are also welcome.
React Flow Pro Examples is a standalone project built on Next.js 16, React 19, TypeScript and the official @xyflow/react, bundling 15 advanced interaction examples into one workbench. You can run it locally and try each example, or read the source to study how layout, geometry calculation, and state management are implemented.
Repository: xh20220630/react-flow-pro-example-
Live demo: Online experience
The 15 official examples
| Area | Included examples | Points worth attention |
|---|---|---|
| Nodes | Node position animation, flowchart shapes | How layout switching transitions, how shapes are edited and scaled |
| Edges | WASM obstacle-avoidance routing, editable edges | How paths avoid obstacles, how control points participate in editing |
| Editing interactions | Alignment guides and snapping, copy/cut/paste, undo/redo | How alignment is preserved, graph structure and operation history |
| Multi-user collaboration | Graph, form, cursor, and connection draft synchronization | How shared documents and temporary online state are organized |
| Grouping | Selection grouping, parent-child node relationships | How absolute coordinates and group-relative coordinates are converted |
| Layout | Expand/collapse, auto layout, force-directed layout, dynamic tree layout | How positions are computed and updated after graph structure changes |
| Whiteboard | Freehand drawing | How strokes become selectable, movable, and scalable objects |
Each example has its own file, so you can observe, operate, and read the implementation around one specific problem. When using them in business projects, the capabilities still need to be combined according to the business data model and interaction rules.
Dynamic tree layout
Click a node to append child nodes; click the dashed placeholder node at the tip to convert it into a normal node and keep extending; click the plus sign on an edge to insert a new node between two existing steps.
Behind this set of interactions are two layers of processing.
The first layer maintains graph structure. For example, inserting C between A and B requires replacing the original edge with A → C and C → B; activating the tip placeholder node requires updating both the node type and connection type, and adding a new tip placeholder node.
The second layer handles layout and transitions. The example determines the parent node through incoming edges, uses D3's stratify and tree to compute target positions, then uses a D3 timer to interpolate between current coordinates and target coordinates, completing a position transition of about 300ms. When operations happen rapidly in succession, the old animation stops during the cleanup phase, avoiding overwriting the new layout.
Auto layout
The project also integrates Dagre, D3 Hierarchy, and ELK; you can switch among four layout directions and adjust spacing, append nodes, or add a root node through the parameter panel.
Layout needs to wait until node size measurement is complete; the center coordinates returned by Dagre need to be converted to node top-left coordinates by subtracting half the node width and height; D3's tree layout organizes multiple trees through a virtual root; ELK's asynchronous computation results need to be merged back into the original data by node ID.
When switching direction, besides adjusting the coordinate axes, the entry and exit positions of edges must also be updated. Looking at these steps together makes it easier to understand why "calling a layout function once" is still a distance away from a complete auto-layout interaction.
The project also provides a force-directed layout: canvas nodes are mapped to simulated particles, with repulsion, edge, and centering forces layered on. When dragging a node, fx and fy fix the corresponding particle, and after the drag ends they are released and the simulation is reactivated.
Advanced edges
In complex canvases, edge paths directly affect readability. The project provides two examples: automatic obstacle avoidance and control point editing.
Obstacle-avoidance routing uses libavoid-js's WASM capability. In the implementation, node rectangles are synchronized as obstacles, Handles are mapped to connection pins with direction information, then connection objects are maintained, routing transactions are executed, and the computed intermediate bend points are written back to edge data.
After a node moves, obstacle positions update accordingly, and the path is recalculated. The WASM file comes from the dependency installed in the project.
There is also an easily overlooked state issue here: writing the routing result back to edge data itself triggers a state update.
The editable edge example supports adjusting control points, generating straight, curved, or orthogonal paths through different path algorithms, and inserting or deleting control points. While connecting, you can also use the spacebar to sample waypoints.
Multi-user collaboration: synchronizing graph data and handling online state
In the Collaborative example, create a Flow, copy the link with Share, then open it from another browser or another device that can access the service, and you enter the same room. Node add/delete and dragging, connections, text input, and checkbox states are synchronized; remote cursors and unfinished connection drafts can also be shown on the canvas.
The implementation uses Yjs + y-websocket and splits state into three layers:
| State | Location | Example |
|---|---|---|
| Shared graph data | Maps in Y.Doc | Nodes, edges, and form data inside nodes |
| Temporary online state | Yjs Awareness | User identity, cursors, connection drafts |
| Local view state | Local projection cache | Node selection state, measured sizes |
This organization lets graph data be shared while each user keeps their own selection state. Temporary information such as cursors is managed by Awareness, and online state is cleaned up after exit or disconnection.
The project includes a built-in collaboration backend that connects to the collaboration path under the current site. The initial node in a room is created by the server, and the canvas is displayed only after the client receives the first sync response.
It also includes Playwright collaboration regression tests covering independent browser sessions, form and graph synchronization, room isolation, first initialization, and disconnection/reconnection scenarios, making it convenient to check these behaviors during subsequent maintenance.
Other examples
Besides layout and collaboration, several smaller examples are also worth studying.
Copy and paste When copying selected nodes, edges whose both endpoints are inside the selection must also be collected; when pasting, node and edge IDs are updated, endpoints are remapped, and node positions are shifted as a whole, so that the internal relationships of the copied subgraph are preserved.
Grouping When creating a group, first compute the bounding box of the selected nodes, then convert child node positions into group-relative coordinates; when ungrouping, convert them back to canvas absolute coordinates. Dragging into a parent container, moving with the parent node, and detaching from the container all build on these conversions.
Freehand drawing The example collects pointer coordinates and pressure, converts them to the canvas coordinate system on submission, then saves the stroke as a local point set in the node, and uses perfect-freehand to generate the outline. After the stroke is made, it can still be selected, moved, and scaled.
Examples such as alignment guides and snapping, snapshot-style undo/redo, expand/collapse, and more.
Project structure
src/app/ Next.js pages and layout
src/components/ Search, category navigation, and workbench entry
src/server/ HTTP and collaboration WebSocket service
packages/react-flow-pro/
src/examples/ 15 example implementations
src/collaboration/ Collaboration connections and session cleanup
src/controls/ Layout parameter panel
src/styles/ Theme and example styles
docs/ Architecture, principles, and source reading guide
The feature package exposes a unified entry point and each example component through @react-flow-pro-example/core; the app and the feature package share the official @xyflow/react. Each example has its own Provider, graph state, and mutable cache; examples are loaded on demand, and styles are isolated by scope.
In a Next.js app that has already configured the workspace dependency, the auto-layout example can be loaded from a Client Component like this:
'use client'
import dynamic from 'next/dynamic'
import '@react-flow-pro-example/core/style.css'
const AutoLayoutExample = dynamic(
() => import('@react-flow-pro-example/core').then((module) => module.AutoLayoutExample),
{ ssr: false },
)
export default function Page() {
return (
<div style={{ width: '100%', height: '100dvh' }}>
<AutoLayoutExample />
</div>
)
}
The caller supplies the container size, and the component loads in the browser. The feature package also provides separate build and bundle commands; when integrating into another host, continue following the instructions in the package.
Running locally
The project uses Node 24.13.0 and pnpm 10.20.0:
git clone https://github.com/xh20220630/react-flow-pro-example-.git
cd react-flow-pro-example-
nvm use
corepack enable
pnpm install
pnpm dev
After startup, open http://localhost:3000.
Feel free to view the source code and try the examples in the GitHub repository.