# Edges

> Every edge type, including floating edges that attach to the nearest border.

**Site index:** [https://flows.2plot.dev/llms.txt](https://flows.2plot.dev/llms.txt) — every page on this site, as Markdown.  
**Network index:** [https://2plot.dev/llms.txt](https://2plot.dev/llms.txt) — The 2plot network; start here to discover sibling sites.  
**Sibling sites:** 13 more in The 2plot network — listed in the site index above.  
**Sitemap:** https://flows.2plot.dev/sitemap.xml  


---



### 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):



```python
# 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/`](https://github.com/pip-install-python/dash-flows/tree/main/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.



```python
# 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**

- `type` on 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.



```python
# 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 when `fitView` runs.
- `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's `id` and `data.label`; try dragging nodes to see the floating edges re-attach in real time.


---

*Source: /edges*
