Edge Types
Edges are the connections between nodes. AlpineFlow provides seven built-in edge types, each using a different path algorithm. Set the type property on an edge to choose one:
{ id: 'e1', source: 'a', target: 'b', type: 'smoothstep' }
<div x-data="flowCanvas({
nodes: [
{ id: 'a1', position: { x: 0, y: 0 }, data: { label: 'Bezier' } },
{ id: 'a2', position: { x: 85, y: 130 }, data: { label: 'Bezier' } },
{ id: 'b1', position: { x: 220, y: 0 }, data: { label: 'Smoothstep' } },
{ id: 'b2', position: { x: 305, y: 130 }, data: { label: 'Smoothstep' } },
{ id: 'c1', position: { x: 440, y: 0 }, data: { label: 'Straight' } },
{ id: 'c2', position: { x: 525, y: 130 }, data: { label: 'Straight' } },
],
edges: [
{ id: 'e1', source: 'a1', target: 'a2', type: 'bezier' },
{ id: 'e2', source: 'b1', target: 'b2', type: 'smoothstep' },
{ id: 'e3', source: 'c1', target: 'c2', type: 'straight' },
],
background: 'dots',
fitViewOnInit: true,
controls: false,
pannable: false,
zoomable: false,
})" class="flow-container" style="height: 250px;">
<div x-flow-viewport>
<template x-for="node in nodes" :key="node.id">
<div x-flow-node="node">
<div x-flow-handle:target></div>
<span x-text="node.data.label"></span>
<div x-flow-handle:source></div>
</div>
</template>
</div>
</div>
Built-in types
| Type | Description | When to use |
|---|---|---|
bezier |
Smooth cubic bezier curve (default). | General-purpose connections where aesthetics matter. |
smoothstep |
Right-angle segments with rounded corners. | Flowcharts and structured diagrams. |
straight |
Direct line from source to target. | Simple, minimal layouts or very short connections. |
orthogonal |
Right-angle routing around obstacle nodes using visibility-graph pathfinding. Falls back to smoothstep when no obstacles exist. |
Dense diagrams where edges must not cross nodes. |
avoidant |
Smooth Catmull-Rom splines routed around obstacle nodes. Uses the same pathfinding as orthogonal but renders curves instead of right angles. Falls back to bezier when no obstacles exist. |
Same as orthogonal, but when smoother curves are preferred. |
editable |
User-controlled waypoints with multiple interpolation styles. Supports double-click to add/remove control points. | When users need to manually shape edge paths. See Editable Edges. |
floating |
Auto-computes endpoints from node borders instead of fixed handles. Uses pathType to pick the underlying path generator. |
Nodes with dynamic sizes or when handle placement is unknown. |
Floating edges
Set type: 'floating' so endpoints are computed dynamically from node borders instead of fixed handle positions:
{
id: 'e1',
source: 'a',
target: 'b',
type: 'floating',
pathType: 'smoothstep',
}
The edge finds the intersection of the center-to-center line with each node's rectangular boundary. As nodes move, connection points slide along the border automatically.
| Property | Type | Default | Description |
|---|---|---|---|
pathType |
'bezier' | 'smoothstep' | 'straight' |
'bezier' |
Which path generator to use for the floating edge. |
Floating edges work well when nodes have dynamic or unknown sizes, or when you want a cleaner look without explicit handle placement.
Drag the nodes around — the edge endpoints slide along the borders:
<div x-data="flowCanvas({
nodes: [
{ id: 'a', position: { x: 0, y: 0 }, data: { label: 'Node A' } },
{ id: 'b', position: { x: 250, y: 100 }, data: { label: 'Node B' } },
],
edges: [
{ id: 'e1', source: 'a', target: 'b', type: 'floating' },
],
background: 'dots',
fitViewOnInit: true,
controls: false,
pannable: false,
zoomable: false,
})" class="flow-container" style="height: 220px;">
<div x-flow-viewport>
<template x-for="node in nodes" :key="node.id">
<div x-flow-node="node">
<span x-text="node.data.label"></span>
</div>
</template>
</div>
</div>
Custom edge types
Register custom edge types via the edgeTypes config option. Any type string that does not match a built-in name is looked up in this registry:
flowCanvas({
edgeTypes: {
'custom': ({ sourceX, sourceY, sourcePosition, targetX, targetY, targetPosition }, edge) => ({
path: `M ${sourceX} ${sourceY} L ${targetX} ${targetY}`,
labelPosition: { x: (sourceX + targetX) / 2, y: (sourceY + targetY) / 2 },
}),
},
})
The function receives source/target coordinates and positions as its first argument, and the edge object itself as an optional second argument. It must return an object with path (an SVG path string) and labelPosition (an { x, y } point for label placement).
The edge argument lets one generator read per-edge routing data off the edge (e.g. waypoints on edge.data) rather than needing a closure per edge — and because that data lives on the edge, it survives toObject() / fromObject(). It is optional, so existing single-argument generators are unaffected.
Edge data shape
Every edge object accepts these properties:
{
id: 'edge-1', // Required. Unique string ID.
source: 'node-a', // Required. Source node ID.
target: 'node-b', // Required. Target node ID.
sourceHandle: 'output-1', // Optional. Source handle ID.
targetHandle: 'input-1', // Optional. Target handle ID.
type: 'bezier', // Optional. 'bezier', 'smoothstep', 'step', 'straight',
// 'orthogonal', 'avoidant', 'editable', or custom.
label: 'connects to', // Optional. Center label text.
labelStart: 'from', // Optional. Label near source.
labelEnd: 'to', // Optional. Label near target.
color: '#ff0000', // Optional. Stroke color string or gradient object.
strokeWidth: 2, // Optional. Stroke width.
animated: true, // Optional. true/'dash', 'pulse', or 'dot'.
markerStart: 'arrow', // Optional. Start marker: 'arrow', 'arrowclosed', or MarkerConfig.
markerEnd: 'arrowclosed', // Optional. End marker.
selected: false, // Optional. Selection state.
hidden: false, // Optional. Hide from rendering.
deletable: true, // Optional. Per-edge delete override.
class: 'my-edge', // Optional. CSS class on the SVG path.
interactionWidth: 20, // Optional. Per-edge hit area width.
}
Edge configuration options
These options are set on the flowCanvas() config object:
| Option | Type | Default | Description |
|---|---|---|---|
defaultEdgeOptions |
Partial<FlowEdge> |
-- | Properties merged into edges created at runtime (drag-connect, click-to-connect, edge-drop). Does not affect initial edges. |
defaultInteractionWidth |
number |
20 |
Invisible hit area width for edge clicks. |
edgesReconnectable |
boolean |
true |
Allow edge endpoints to be dragged to different handles. |
reconnectSnapRadius |
number |
10 |
Proximity radius for endpoint snap during reconnection. |
edgesFocusable |
boolean |
true |
Allow edges to receive keyboard focus via Tab. |
reconnectOnDelete |
boolean |
false |
Auto-bridge predecessors to successors when deleting middle nodes. |
Programmatic edge management
Add and remove edges via the $flow magic. See the Edges API reference for all available methods.
<div x-data="flowCanvas({
nodes: [
{ id: 'a', position: { x: 0, y: 0 }, data: { label: 'Node A' } },
{ id: 'b', position: { x: 200, y: 0 }, data: { label: 'Node B' } },
{ id: 'c', position: { x: 400, y: 0 }, data: { label: 'Node C' } },
],
edges: [
{ id: 'e1', source: 'a', target: 'b' },
],
background: 'dots',
fitViewOnInit: true,
controls: false,
pannable: false,
zoomable: false,
})" class="flow-container" style="height: 220px;"
x-init="
document.getElementById('demo-edges-add').addEventListener('click', () => {
if (!getEdge('e-ac')) addEdges([{ id: 'e-ac', source: 'a', target: 'c' }]);
});
document.getElementById('demo-edges-remove').addEventListener('click', () => {
removeEdges(edges.map(e => e.id));
});
">
<div x-flow-viewport>
<template x-for="node in nodes" :key="node.id">
<div x-flow-node="node">
<div x-flow-handle:target></div>
<span x-text="node.data.label"></span>
<div x-flow-handle:source></div>
</div>
</template>
</div>
</div>
See also
- Markers -- SVG arrowheads for edge endpoints
- Labels -- text labels along edges
- Gradients -- gradient colors along edge strokes
- Animation -- dash, pulse, and dot animation modes
- Editable Edges -- user-controlled waypoints
- Styling -- colors, stroke width, CSS classes
- Handles -- connection points on nodes