Skip to Content
✨ Svelte Flow 1.0 is here! Rewritten for Svelte 5 with many new features and improvements.
LearnTroubleshootingMigrate to v1

Migrate to Svelte Flow 1.0

Svelte Flow 1.0 is built from the ground up with Svelte 5 and includes many new features and improvements. This guide will help you migrate from Svelte Flow 0.x to 1.0.

If you are looking for the Svelte Flow 0.x docs, please refer to legacy.svelteflow.dev .

New features

  • Reconnect edges: You can reconnect your edges by using the new <EdgeReconnectAnchor /> component. It can be used to add custom reconnection points on custom edges.
  • Keyboard navigation & A11y: We added support for keyboard navigation and improved accessibility for screen readers. You can now tab through nodes and edges and move nodes with the arrow keys. Can be disabled via disableKeyboardA11y
  • Click connect: You can now create a new connection by clicking on a handle one by one.
  • Enhanced ViewportPortal: You can now decide if you want to render something below or above the nodes & edges in the viewport.
  • Improved fitView: We finetuned the fitView function to better work with dynamically added nodes.
  • colorModeSSR prop: You can pass a fallback color mode for server side rendering when colorMode is set to ‘system’.
  • elevateNodesOnSelect & elevateEdgesOnSelect: Control if nodes & edges should be elevated via z-index when selected.
  • noDragClass, noWheelClass, noPanClass: You can now modify the class name used to disable dragging, panning and zooming.
  • onselectionchange & useOnSelectionChange: You can now listen to selection changes via a callback

Breaking changes

nodes & edges are now using $state.raw instead of writable

Svelte 5 introduces runes which are now getting used for nodes and edges.

Old API

const nodes = writable([...]); const edges = writable([...]);

New API

let nodes = $state.raw([...]); let edges = $state.raw([...]);

Updating Nodes & Edges

Previously it was possible to update single node properties. Theoretically, this would also be possible with $state, however the performance implications  of this are unfortunately too great, so we opted to using $state.raw.

This means that nodes and edges are to be treated as immutable from now on. If you are making updates manually make sure you:

  1. create a new node/edge object, when updating a property.
  2. reassign the nodes/edges array (this was technically required before anyway)
nodes[0].position.x = 100; // won't work const newNode = { ...nodes[0] }; newNode.position.x = 100; nodes[0] = newNode; // not enough to trigger an update nodes = [...nodes]; // this will make it work nodes = nodes.map((node) => { if (node.id === '1') { return { ...node, position: { ...node.position, x: 100 } }; } return node; }); // also works updateNode('1', (node) => ({ ...node, position: { ...node.position, x: 100 }, })); // using the updateNode helper from useSvelteFlow

nodes & edges need to be bound from <SvelteFlow />

Old API

<SvelteFlow {nodes} {edges} />

New API

<SvelteFlow bind:nodes bind:edges />

If nodes and edges live in a separate module, you can use function bindings .

// store.svelte.js let nodes = $state.raw([...]); let edges = $state.raw([...]); export const getNodes = () => nodes; export const getEdges = () => edges; export const setNodes = (newNodes) => nodes = newNodes; export const setEdges = (newEdges) => edges = newEdges;
// BaseComponent.svelte <script> import { getNodes, getEdges, setNodes, setEdges } from 'store.svelte.js'; </script> <SvelteFlow bind:nodes={getNodes, setNodes} bind:edges={getEdges, setEdges} />

Custom Node & Edge Props

This is by enlarge a general change in Svelte 5, but it does have quite a big impact on typing the props of Custom Nodes & Edges.

Old API

// CustomNode.svelte type $$Props = NodeProps; export let data: $$Props['data']; export let position: $$Props['position']; export let selected: $$Props['selected'];

New API

let { data, position, selected } : NodeProps = $props();

Hooks

Hooks now return reactive values instead of writables. Because $state values cannot be returned by functions directly  we have to return an object with a .current property to keep reactivity. In this regard, we are following the official trend  set by the Svelte library authors.

Old API

const edges = useEdges(); $: console.log(edges);

New API

const edges = useEdges(); $inspect(edges.current);

Note that in case of useNodes, useEdges and useViewport reassignments to .current work!

const nodes = useNodes(); function updateNodes() { nodes.current = [...] }

Binding the viewport

Binding the viewport now works natively in Svelte 5. You can either access the internal viewport or bind your very own viewport object to be used instead.

Old API

const viewport = writable<Viewport>({ x: 100, y: 100, zoom: 1.25 }); <SvelteFlow {viewport} />

New API

let viewport = $state < Viewport > { x: 100, y: 100, zoom: 1.25 }; <SvelteFlow bind:viewport />;

Custom Connection Line

Using a custom Connection Line was possible before by passing it to a slot . In Svelte Flow 1.0 we introduced a new prop called connectionLineComponentfor this.

Old API

<SvelteFlow {nodes} {edges}> <ConnectionLine slot="connectionLine" /> <Background variant={BackgroundVariant.Lines} /> </SvelteFlow>

New API

<SvelteFlow {nodes} {edges} connectionLineComponent={ConnectionLine}> <Background variant={BackgroundVariant.Lines} /> </SvelteFlow>

onEdgeCreate becomes onbeforeconnect

onedgecreate was called before a new edge was created. This is now called onbeforeconnect to better align with events like onbeforeconnect.

Old API

<SvelteFlow {nodes} {edges} onEdgeCreate={(connection) => ({...connection, id: crypto.randomUUID()})} />

New API

<SvelteFlow bind:nodes bind:edges onbeforeconnect={(connection) => ({ ...connection, id: crypto.randomUUID() })} />

<EdgeLabelRenderer/> becomes <EdgeLabel />

The EdgeLabelRenderer component is now called EdgeLabel. As it was just a simple Portal to begin with, the naming of it being a “renderer” was a bit misleading. To add to this, the new EdgeLabel component now also handles clicks on the label automatically and is aware of what edge it belongs to.

Old API

CustomEdge.svelte
<BaseEdge id={id} path={path} /> <EdgeLabelRenderer> <div style:transform={`translate(${labelX}px, ${labelY}px)`} > My Edge Label </div> </EdgeLabelRenderer>

New API

CustomEdge.svelte
<BaseEdge path={path} /> <EdgeLabel x={labelX} y={labelY} selectEdgeOnClick> <div>My Edge Label</div> </EdgeLabel>
Last updated on