Get Started
Introduction
Components
Accordion
Badge
Button
Card
Checkbox
Command
Dialog
Dropdown Menu
Input
Select
Switch
Table
Tabs
Toast
Tooltip
Forms
Introduction
Validation
Field Arrays

The edge shape, the path-type variants the built-in renderer understands, and the animated flag.

#Edge Shape

An edge connects two nodes by their ids. The minimal shape is { id, source, target }; everything else — the curve type, animation, handle pinning — is opt-in. Flow looks up source / target in the node lookup, finds the matching handles, and draws a path between them.

1// An edge is a plain object connecting two node ids.2const edges = [3  { id: "a-b", source: "a", target: "b" },4  // Optional fields:5  // - type        : 'default' | 'bezier' | 'straight' | 'smoothstep' | 'step'6  // - animated    : true → renders a moving dashed stroke7  // - sourceHandle / targetHandle : pin to a specific handle id8  // - selected    : initial selection state9  // - data        : arbitrary payload for forward compatibility10]

#Default Routing

With no type set, an edge renders as a Bezier curve from the source node's bottom handle to the target node's top handle.

#A single edge

Hello
World
1import { Flow, Background } from "@/components/ui/xyflow"23const nodes = [4  { id: "a", position: { x: 80, y: 30 },   data: { label: "Hello" } },5  { id: "b", position: { x: 280, y: 150 }, data: { label: "World" } },6]7const edges = [8  { id: "a-b", source: "a", target: "b" },9]1011export function MyFlow() {12  return (13    <div className="w-full h-[240px] rounded-lg border bg-background overflow-hidden">14      <Flow nodes={nodes} edges={edges}>15        <Background variant="dots" gap={30} />16      </Flow>17    </div>18  )19}

#Edge Variants

The built-in <SimpleEdge> picks a path algorithm from the edge's type string — "default" / "bezier" (curve), "straight" (line), "smoothstep" / "step" (right-angle).

#Four path types side-by-side

default
bezier
smoothstep
straight
r1
r2
r3
r4
1// Each edge picks its path algorithm from `type`.2const edges = [3  { id: "e1", source: "l1", target: "r1" },                       // default (bezier)4  { id: "e2", source: "l2", target: "r2", type: "bezier"     },5  { id: "e3", source: "l3", target: "r3", type: "smoothstep" },6  { id: "e4", source: "l4", target: "r4", type: "straight"   },7]

#Animated Edges

Set animated: true on an edge and <SimpleEdge> appends the bf-flow__edge--animated class — a stroke-dasharray keyframe animation that gives a sense of direction or activity. The flag is independent of type, so it composes with any of the path variants.

#Animated stroke

Source
Process
Sink
1// Toggle the moving-dash animation per edge.2const edges = [3  { id: "a-b", source: "a", target: "b", animated: true },4  { id: "b-c", source: "b", target: "c", animated: true },5]67<Flow nodes={nodes} edges={edges}>8  <Background variant="dots" gap={30} />9</Flow>

#rAF Flow Animation

The CSS keyframe animation above happens entirely inside the browser. When you need the path direction or speed to be reactive — to track a signal — drive the stroke-dashoffset attribute from a requestAnimationFrame loop owned by a createEffect. Toggling the effect off calls cancelAnimationFrame in onCleanup, so the loop never leaks past unmount.

#rAF-driven dashoffset

stroke-dashoffset is driven by requestAnimationFrame
1"use client"23import { createSignal, createEffect, onCleanup } from "@barefootjs/client"45export function XyflowFlowAnimateDemo() {6  const [animating, setAnimating] = createSignal(false)7  const [offset, setOffset]       = createSignal(0)89  createEffect(() => {10    if (!animating()) return11    let frame = 012    let last  = performance.now()13    const tick = (now) => {14      const dt = now - last15      last = now16      setOffset((prev) => (prev - dt * 0.04) % 16)17      frame = requestAnimationFrame(tick)18    }19    frame = requestAnimationFrame(tick)20    onCleanup(() => cancelAnimationFrame(frame))21  })2223  return (24    <div>25      <button onClick={() => setAnimating(!animating())}>26        {animating() ? "Stop" : "Animate flow"}27      </button>28      <svg viewBox="0 0 520 180">29        <path30          d="M 40 60 C 140 60 160 120 280 120 S 380 60 480 60"31          fill="none"32          stroke="currentColor"33          stroke-width="3"34          stroke-dasharray="8 8"35          stroke-dashoffset={String(offset())}36        />37      </svg>38    </div>39  )40}