One journey, multiple paths. Follow branches from a shared entry to a common destination, with ribbons sized to the volume moving between steps.
npx mario-charts@latest add sankey-chart620 choose email. 380 choose single sign-on. Both reach the same destination.
Waiting for chart space
Select a node or connection to inspect its original observation.
Hover or focus to trace connected branches. Use arrow keys to inspect nodes, then connections; Enter selects. On narrow screens, scroll horizontally to follow the journey.
import { SankeyChart } from "@/components/charts/sankey-chart";
const nodes = [
{ id: "start", label: "Sign up" },
{ id: "email", label: "Email" },
{ id: "sso", label: "Single sign-on" },
{ id: "done", label: "Account created" },
];
const links = [
{ source: "start", target: "email", value: 620 },
{ source: "start", target: "sso", value: 380 },
{ source: "email", target: "done", value: 620 },
{ source: "sso", target: "done", value: 380 },
];
export function SignupPaths() {
return <SankeyChart nodes={nodes} links={links}
height={400} ariaLabel="Signup paths" />;
}Each ribbon represents one supplied transition. The email branch carries 620 of the 1,000 outgoing transitions, so its share is 62%. The destination receives 620 + 380 = 1,000. The chart does not deduplicate people or infer transitions from stage totals.
A node uses the larger of its incoming and outgoing totals for its height. An imbalance stays visible in inspection. To show abandonment, supply an explicit destination and its measured connections. A zero volume has no painted area, but remains inspectable.
Connections must form an acyclic graph. For a return visit, give the repeated event a new ID at a later step. Highlighting shows reachable connections; aggregated volumes cannot recover an individual user's complete route through a merge.
For conversion through one ordered sequence, use the Funnel Chart.
| Prop | Type | Default | Description |
|---|---|---|---|
nodesRequired | readonly N[] | — | Each node has a unique string id, label and optional CSS color. Extra fields retain their inferred types in callbacks. Input order orders nodes within a column. |
linksRequired | readonly L[] | — | Each connection has source/target node IDs and a finite nonnegative numeric value. Supply aggregated transition volumes in consistent units. Duplicate connections remain separate observations. |
align | 'justify' | 'start' | 'justify' | Place terminal nodes in the final column, or at their earliest depth. Connections spanning columns route below intermediate nodes. |
linkColor | 'gradient' | 'source' | 'target' | 'gradient' | A gradient follows source and destination colors. Solid options color each ribbon by one endpoint. |
curvature | number | 0.5 | 0–1 curve tension; 0 produces straight connections between adjacent columns. Connections skipping columns keep a curved route around intervening nodes. |
colors | readonly string[] | — | Palette for nodes without a color. CSS variables work; empty arrays fall back to the defaults. |
nodeWidth / nodeGap | number | 18 / 24 | Node width (1–80px) and vertical gap (0–200px). Label space and internal scrolling prevent overlaps without inflating small values. |
showValues | boolean | true | Show each node's flow volume: max(incoming total, outgoing total). Incoming and outgoing totals stay available on inspection. |
height / className | number / string | 400 | Stable frame height and root styling. Dense or narrow views scroll within the frame. |
animation | boolean | true | Reveal connections from left to right. Reduced motion and keyboard focus complete the reveal immediately. |
loading / error | boolean / string | null | — | Loading retains available geometry; initial loading uses a branched skeleton. Errors and empty states keep the same frame. |
valueFormatter | (value: number) => string | — | Format labels, inspection values, the accessible table in your unit. |
ariaLabel / description | string | — | Accessible chart name and optional explanation of the supplied data. |
onNodeClick / onLinkClick | (item, index) => void | — | Original node or connection and input index, including zero-valued observations. Works with pointer, touch, Enter and Space. |
tooltipRenderer | (inspection: SankeyInspection<N, L>) => ReactNode | — | A discriminated node/link payload with original data. Node inspection includes incoming/outgoing totals. Link inspection includes endpoints and its shares of source outgoing/target incoming; a zero denominator returns null. |