Sankey
Weighted-flow diagram. Nodes arranged in horizontal columns by topological depth; link thickness encodes flow value. Use for funnels, energy/material/money flows, and any "value moving from A to B" picture.
Installation
pnpm dlx @hex-core/cli add sankeyUsage
import { Sankey } from "@/components/ui/sankey"Energy flow
Two sources flowing into a single sink.
<Sankey
nodes={[
{ id: "coal", label: "Coal" },
{ id: "gas", label: "Gas" },
{ id: "grid", label: "Grid" },
]}
links={[
{ source: "coal", target: "grid", value: 60 },
{ source: "gas", target: "grid", value: 30 },
]}
/>Funnel-style with hover
Surface link details on hover for tooltips.
<Sankey
nodes={steps}
links={transitions}
onLinkHover={(l) => setActive(l)}
/>API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
nodesrequired | object | — | Array of { id, label }. Every link's source/target MUST match an id here. |
linksrequired | object | — | Array of { source, target, value }. Values must be positive. |
width | number | 720 | SVG pixel width. |
height | number | 420 | SVG pixel height. |
nodeAlign | "left" | "right" | "center" | "justify" | justify | Column alignment strategy. |
nodeWidth | number | 12 | Pixel width of each node rectangle. |
nodePadding | number | 8 | Vertical pixel gap between nodes in the same column. |
onLinkHover | function | — | Called with the hovered SankeyLink (or null when hover ends). |
onNodeClick | function | — | Called with the clicked SankeyNode. |
className | string | — | Additional CSS classes on the SVG element. |
AI Guidance
When to use
Visualize how a quantity is distributed and re-distributed across a multi-step pipeline — energy mix, marketing-funnel transitions, traffic referral flows, budget allocation by department × line-item. The thicker the link, the more value moves along it.
When not to use
Don't use for hierarchies (use TreeMap or Sunburst). Don't use for arbitrary node-edge graphs without a clear left-to-right flow (use Canvas). Don't use when total flow doesn't conserve from column to column — d3-sankey assumes a balanced graph.
Common mistakes
- A link's source or target id not present in `nodes` — d3-sankey throws an opaque error. Validate ids upstream
- Negative or zero `value` — produces zero-width or NaN-positioned links. Filter or clamp upstream
- Cycles in the link graph — d3-sankey requires a DAG. If your data has feedback loops, collapse them or split into multiple Sankeys
- Mutating the input `nodes` / `links` between renders — the component clones internally to protect consumer arrays, but unmemoized inputs still trigger a full re-layout each render. Memoize
Accessibility
The SVG carries role="img" with a <title> and <desc> summarizing node and link counts. For agent outputs, also expose a parallel <table> of source / target / value triples so screen-reader users get the flow magnitudes.
Token budget: 360
Verified against @hex-core/components@1.12.0