Edges
Every edge type, including floating edges that attach to the nearest border.
Overview
Set an edge's type to choose its path: straight, step, smoothstep, simplebezier, button, data, animated, or floating. Floating edges connect to the nearest point on each node's border instead of a fixed handle.
Live demo
Drag the nodes, pan, and zoom — the canvas below is a real, running DashFlows component (no callbacks, just the rendered graph):
# File: docs/edges/demo.py
"""Live, callback-free demo for the docs page. Rendered via `.. exec::docs.edges.demo`."""
import dash_flows
nodes = [{'id': '0', 'type': 'default', 'data': {'label': 'straight'}, 'position': {'x': 60, 'y': 40}},
{'id': '1', 'type': 'default', 'data': {'label': 'step'}, 'position': {'x': 320, 'y': 40}},
{'id': '2', 'type': 'default', 'data': {'label': 'smoothstep'}, 'position': {'x': 60, 'y': 160}},
{'id': '3',
'type': 'default',
'data': {'label': 'simplebezier'},
'position': {'x': 320, 'y': 160}},
{'id': '4', 'type': 'default', 'data': {'label': 'button'}, 'position': {'x': 60, 'y': 280}},
{'id': '5', 'type': 'default', 'data': {'label': 'animated'}, 'position': {'x': 320, 'y': 280}}]
edges = [{'id': 's', 'source': '0', 'target': '1', 'type': 'straight'},
{'id': 'st', 'source': '1', 'target': '2', 'type': 'step'},
{'id': 'sm', 'source': '2', 'target': '3', 'type': 'smoothstep'},
{'id': 'sb', 'source': '3', 'target': '4', 'type': 'simplebezier'},
{'id': 'bt', 'source': '4', 'target': '5', 'type': 'button'},
{'id': 'an', 'source': '5', 'target': '0', 'type': 'animated'}]
component = dash_flows.DashFlows(
id="edges-demo",
nodes=nodes,
edges=edges,
style={'border': '1px solid var(--mantine-color-default-border)',
'borderRadius': '8px',
'height': '440px'},
showControls=True,
fitView=True,
colorMode='system',
)
:defaultExpanded: false :withExpandedButton: true
Examples
Each example below is a complete, runnable Dash app from the examples/ folder. Run any of them with python examples/<file>.
All Edge Types
A gallery of every edge type — default, straight, step, smoothstep, simplebezier, and button — laid out as a row of sources connecting to a row of targets, plus a callback that tracks edge deletions.
# File: examples/03_all_edge_types.py
"""
Example 03: All Edge Types
==========================
This example showcases all available edge types in DashFlows:
- default: Standard bezier curve edge (React Flow built-in)
- straight: Direct line between nodes
- step: Right-angled connections with sharp corners
- smoothstep: Right-angled with rounded corners
- simplebezier: Simple bezier curve
- button: Edge with interactive button (for deletion)
- animated: Edge with Dash component animation
"""
import dash
from dash import html, callback, Input, Output, State
import dash_flows
app = dash.Dash(__name__)
# Create a row of source nodes and a row of target nodes
nodes = [
# Source nodes (top row)
{"id": "s1", "type": "input", "data": {"label": "Default"}, "position": {"x": 50, "y": 50}},
{"id": "s2", "type": "input", "data": {"label": "Straight"}, "position": {"x": 200, "y": 50}},
{"id": "s3", "type": "input", "data": {"label": "Step"}, "position": {"x": 350, "y": 50}},
{"id": "s4", "type": "input", "data": {"label": "SmoothStep"}, "position": {"x": 500, "y": 50}},
{"id": "s5", "type": "input", "data": {"label": "SimpleBezier"}, "position": {"x": 650, "y": 50}},
{"id": "s6", "type": "input", "data": {"label": "Button Edge"}, "position": {"x": 800, "y": 50}},
# Target nodes (bottom row)
{"id": "t1", "type": "output", "data": {"label": "Target 1"}, "position": {"x": 50, "y": 300}},
{"id": "t2", "type": "output", "data": {"label": "Target 2"}, "position": {"x": 200, "y": 300}},
{"id": "t3", "type": "output", "data": {"label": "Target 3"}, "position": {"x": 350, "y": 300}},
{"id": "t4", "type": "output", "data": {"label": "Target 4"}, "position": {"x": 500, "y": 300}},
{"id": "t5", "type": "output", "data": {"label": "Target 5"}, "position": {"x": 650, "y": 300}},
{"id": "t6", "type": "output", "data": {"label": "Target 6"}, "position": {"x": 800, "y": 300}},
]
edges = [
# Default edge (bezier curve) - React Flow's built-in
{
"id": "e1",
"source": "s1",
"target": "t1",
"type": "default",
"label": "Default",
"animated": True,
},
# Straight edge - direct line
{
"id": "e2",
"source": "s2",
"target": "t2",
"type": "straight",
"label": "Straight",
},
# Step edge - sharp right angles
{
"id": "e3",
"source": "s3",
"target": "t3",
"type": "step",
"label": "Step",
},
# SmoothStep edge - rounded right angles
{
"id": "e4",
"source": "s4",
"target": "t4",
"type": "smoothstep",
"label": "SmoothStep",
"data": {"borderRadius": 15}, # Custom corner radius
},
# SimpleBezier edge - simple curve
{
"id": "e5",
"source": "s5",
"target": "t5",
"type": "simplebezier",
"label": "SimpleBezier",
},
# Button edge - with delete button
{
"id": "e6",
"source": "s6",
"target": "t6",
"type": "button",
"data": {
"label": "Click X to delete",
"showButton": True,
"buttonLabel": "x",
},
},
]
app.layout = html.Div([
html.H1("All Edge Types Example"),
html.P("Demonstrates every available edge type in DashFlows."),
html.Ul([
html.Li("Default: Standard bezier curve (animated in this example)"),
html.Li("Straight: Direct line connection"),
html.Li("Step: Right-angled path with sharp corners"),
html.Li("SmoothStep: Right-angled with configurable rounded corners"),
html.Li("SimpleBezier: Simple curved line"),
html.Li("Button: Edge with interactive delete button"),
]),
dash_flows.DashFlows(
id="edge-types-flow",
nodes=nodes,
edges=edges,
style={"height": "500px", "border": "1px solid #ddd"},
fitView=True,
showControls=True,
),
html.Div(id="edge-deleted-info", style={"marginTop": "20px"}),
])
# Track edge deletions
@callback(
Output("edge-deleted-info", "children"),
Input("edge-types-flow", "edges"),
prevent_initial_call=True,
)
def track_edge_changes(current_edges):
if current_edges is None:
return ""
edge_count = len(current_edges)
return f"Current edge count: {edge_count}"
if __name__ == "__main__":
app.run(debug=True, port=8052)
:defaultExpanded: false :withExpandedButton: true
How it works
typeon each edge — picks the renderer ("default","straight","step","smoothstep","simplebezier","button"); omit it to fall back to React Flow's default bezier curve.animated=True— draws a moving dashed line on the default edge.data={"borderRadius": 15}— the smoothstep edge reads this to control corner rounding.data={"showButton": True, "buttonLabel": "x"}— the button edge renders a small button (here used for deletion) on top of the path.Input("ex03-edge-types-flow", "edges")— fires whenever the edge list changes (e.g. after clicking a button edge's delete control), letting you track the current edge count.
Floating Edges
Edges that dynamically attach to the closest border point of each node, instead of a fixed handle position — useful when nodes sit at irregular angles relative to each other.
# File: examples/26_floating_edges.py
"""
Example 26: Floating Edges
===========================
Demonstrates the 'floating' edge type which connects to the nearest point
on each node's border instead of fixed handle positions. This creates more
natural-looking connections, especially when nodes are positioned at angles.
"""
import dash
from dash import html, callback, Input, Output
import dash_flows
app = dash.Dash(__name__)
nodes = [
{
"id": "1",
"type": "input",
"data": {"label": "Data Source", "sublabel": "REST API"},
"position": {"x": 0, "y": 0},
},
{
"id": "2",
"type": "default",
"data": {"label": "Validate"},
"position": {"x": 300, "y": -50},
},
{
"id": "3",
"type": "default",
"data": {"label": "Transform"},
"position": {"x": 150, "y": 200},
},
{
"id": "4",
"type": "default",
"data": {"label": "Enrich"},
"position": {"x": 450, "y": 150},
},
{
"id": "5",
"type": "output",
"data": {"label": "Database", "sublabel": "PostgreSQL"},
"position": {"x": 350, "y": 350},
},
{
"id": "6",
"type": "output",
"data": {"label": "Dashboard", "sublabel": "Visualization"},
"position": {"x": 50, "y": 400},
},
]
# All edges use the 'floating' type - they connect to the nearest border point
edges = [
{"id": "e1-2", "source": "1", "target": "2", "type": "floating", "label": "raw"},
{"id": "e1-3", "source": "1", "target": "3", "type": "floating"},
{"id": "e2-4", "source": "2", "target": "4", "type": "floating", "label": "valid"},
{"id": "e3-4", "source": "3", "target": "4", "type": "floating"},
{"id": "e3-6", "source": "3", "target": "6", "type": "floating"},
{"id": "e4-5", "source": "4", "target": "5", "type": "floating", "label": "enriched"},
]
app.layout = html.Div([
html.H1("Floating Edges"),
html.P(
"Floating edges connect to the nearest point on each node's border. "
"Drag nodes around and watch the edges dynamically reattach to the closest point."
),
dash_flows.DashFlows(
id="floating-flow",
nodes=nodes,
edges=edges,
style={"height": "600px", "border": "1px solid #ddd"},
fitView=True,
fitViewOptions={"padding": 0.2},
showControls=True,
showMiniMap=True,
showBackground=True,
colorScheme="ocean",
),
html.Div(id="floating-info", style={"marginTop": "12px", "fontSize": "14px", "color": "#666"}),
])
@callback(
Output("floating-info", "children"),
Input("floating-flow", "clickedNode"),
)
def show_clicked(node):
if not node:
return "Click a node to see its info. Drag nodes to see floating edges update."
return f"Clicked: {node['id']} - {node['data'].get('label', '')}"
if __name__ == "__main__":
app.run(debug=True, port=8026)
:defaultExpanded: false :withExpandedButton: true
How it works
type: "floating"on every edge — connects to whichever point on the node's border is closest to the other node, and re-computes it live as nodes move.fitViewOptions={"padding": 0.2}— adds breathing room around the graph whenfitViewruns.colorScheme="ocean"— swaps the default glass theme palette for the built-in ocean color scheme.showMiniMap/showBackground— enables the minimap overlay and canvas background grid alongside the controls.Input("ex26-floating-flow", "clickedNode")— reports the clicked node'sidanddata.label; try dragging nodes to see the floating edges re-attach in real time.
Source: /edges
Note for AI agents: This is the static, prerendered view of an interactive Dash application served because we detected a non-JS user agent. Full prose docs:
- /edges/llms.txt — LLM-friendly documentation
- /sitemap.xml
- /robots.txt