Sankey Chart

Documentation Index

Fetch the complete documentation index at: /llms.txt. Use this file to discover all available pages before exploring further.

Visualize flow data as nodes and links, powered by Apache ECharts

Basic Chart

Installation

npx shadcn@latest add @evilcharts/echarts-sankey-chart

Usage

The ECharts sankey chart is composible, sharing the Recharts twin's API shape. <EChartsSankeyChart> is the container, and every part hangs off it as a compound member — <EChartsSankeyChart.Node>, <EChartsSankeyChart.NodeLabel>, <EChartsSankeyChart.Link>, and <EChartsSankeyChart.Tooltip> — so a single import gives you the whole chart. Because nodes and links are intrinsic to the flow data, <Node> and <Link> always render and just configure the diagram; <NodeLabel> and <Tooltip> follow presence semantics — omit one and it does not render.

import { EChartsSankeyChart, type ChartConfig, type SankeyData } from "@/components/evilcharts/charts/echarts-sankey-chart";
const data: SankeyData = {
  nodes: [
    { name: "Visit" },
    { name: "Direct-Favourite" },
    { name: "Page-Click" },
    { name: "Detail-Favourite" },
    { name: "Lost" },
  ],
  links: [
    { source: 0, target: 1, value: 3728 },
    { source: 0, target: 2, value: 354170 },
    { source: 2, target: 3, value: 62429 },
    { source: 2, target: 4, value: 291741 },
  ],
};
 
const chartConfig = {
  Visit: {
    label: "Visit",
    colors: { light: ["#3b82f6"], dark: ["#60a5fa"] },
  },
  "Page-Click": {
    label: "Page Click",
    colors: { light: ["#f59e0b"], dark: ["#fbbf24"] },
  },
  // ... more node configs
} satisfies ChartConfig;
 
<EChartsSankeyChart data={data} config={chartConfig}>
  <EChartsSankeyChart.Node isClickable>
    <EChartsSankeyChart.NodeLabel position="outside" showValues />
  </EChartsSankeyChart.Node>
  <EChartsSankeyChart.Link variant="source" />
  <EChartsSankeyChart.Tooltip />
</EChartsSankeyChart>

The one real difference is under the hood: ECharts renders to a <canvas>, so these children never mount as DOM. The root reads their props and compiles them into the ECharts option — same JSX, same presence semantics, same behavior, but the children are declarative config, not live DOM nodes.

config is the same contract as every EvilCharts chart — each key maps a node name to a label and a per-theme colors array. See Chart Config for the full shape. Colors resolve from CSS variables at runtime, so dark mode just works.

Interactive Selection

Set isClickable on <Node> to make nodes selectable. The selected node and its direct neighbors stay highlighted while the rest dim. Handle selection events with the root's onSelectionChange callback:

<EChartsSankeyChart
  data={data}
  config={chartConfig}
  onSelectionChange={(selection) => {
    if (selection) {
      console.log("Selected:", selection.dataKey, "Value:", selection.value);
    } else {
      console.log("Deselected");
    }
  }}
>
  <EChartsSankeyChart.Node isClickable />
  <EChartsSankeyChart.Link variant="source" />
  <EChartsSankeyChart.Tooltip />
</EChartsSankeyChart>

Loading State

isLoading='true'

Examples

Examples of the sankey chart in different configurations. Customize the <Link> variant, the root nodeWidth, nodePadding, and more.

Gradient Colors

gradient colors

Labeled Nodes

Inside Labels

showNodeLabels='inside'
showNodeLabels='inside' - solid colors

Outside Labels

showNodeLabels='outside'
<Link variant='solid' />
<Link variant='source' />

API Reference

A root container plus a small set of composible parts. Render the root, then compose the parts you need as children. On canvas each part is declarative config the root compiles, but the API closely mirrors the Recharts twin.

EChartsSankeyChart

The root container. It owns the flow data, shared selection state, loading skeleton, and intro reveal. Everything visual is composed as children and compiled into the ECharts option.

PropTypeDefaultDescription
data*SankeyData

Nodes and links for the flow. SankeyData is { nodes: SankeyNode[]; links: SankeyLink[] }, where SankeyNode = { name: string; icon?: ReactNode } and SankeyLink = { source: number; target: number; value: number }. source/target are indices into nodes. (icon is accepted for parity with the Recharts shape but not rendered on canvas.)

config*ChartConfig

Defines the chart's nodes. Each key matches a node name, with a label and a per-theme colors array. Same contract as every EvilCharts chart — see Chart Config.

children*ReactNode

The composed parts — <Node />, <NodeLabel />, <Link />, and <Tooltip />.

classNamestring

Additional CSS classes for the chart container.

nodeWidthnumber10

The width of each node in pixels.

nodePaddingnumber10

The vertical gap between nodes in pixels (ECharts nodeGap).

linkCurvaturenumber0.5

Curvature of links between nodes, 0 (straight) to 1 (maximum curve).

iterationsnumber32

Iterations for the sankey layout algorithm. Higher values improve the layout but take more time.

alignleft|justify"justify"

Horizontal alignment for nodes (ECharts nodeAlign). "left" aligns to the left, "justify" spreads them across the width.

sortbooleantrue

Accepted for parity with the Recharts twin. The ECharts layout always sorts nodes, so this prop has no effect.

verticalAlignjustify|top"justify"

Accepted for parity with the Recharts twin. ECharts has no vertical-alignment control for sankey, so this prop has no effect.

defaultSelectedNodestring | nullnull

The node name selected on first render.

onSelectionChange(selection: { dataKey: string; value: number } | null) => void

Called when a node is selected or deselected. Receives an object with dataKey (node name) and value (node value from links), or null on deselect. Fires on click while <Node /> has isClickable set.

isLoadingbooleanfalse

Shows the animated loading skeleton.

animationbooleantrue

Master switch for the intro draw-in. Pass false to render the chart instantly.

animationTypenone|default"default"

"default" plays ECharts' native draw-in on first render; "none" disables it. The OS reduce-motion preference falls back to "none" automatically.

chartOptionsRecord<string, unknown>

Escape hatch merged over the built ECharts option object. See the ECharts sankey option documentation.

Node

Configures how the sankey nodes render. Compose a <NodeLabel /> inside it to show labels and values.

PropTypeDefaultDescription
radiusnumber0

The corner radius of node rectangles in pixels. Set to 0 for square nodes.

isClickablebooleanfalse

Lets nodes be clicked to select/deselect them. Selected nodes and their direct neighbors stay highlighted while the rest dim.

childrenReactNode

Optional <NodeLabel /> composition.

NodeLabel

Declares labels for the <Node /> it is composed inside. With no position, no labels are shown.

PropTypeDefaultDescription
positioninside|outside

Where node labels sit. "inside" centers them on the nodes (with a translucent backing plate), "outside" hangs them to the right. Without <NodeLabel />, or with no position, no labels show.

showValuesbooleanfalse

Show the total flow value alongside each node label.

valueFormatter(value: number) => string(value) => value.toLocaleString()

Function to format node values when showValues is enabled.

Link

Configures how the sankey links render.

PropTypeDefaultDescription
variantgradient|solid|source|target"gradient"

The coloring strategy for links. "gradient" fades from source to target color, "solid" uses the foreground color, "source" uses the source node color, "target" uses the target node color.

verticalPaddingnumber0

Accepted for parity with the Recharts twin. ECharts sizes each link band to its value with no per-link inset, so this prop has no effect.

Tooltip

The hover tooltip. Its presence enables it; omit it and none shows. Hovering a node shows its label and total flow; hovering a link shows the source → target flow and its value. Hidden automatically while loading.

PropTypeDefaultDescription
variantdefault|frosted-glass"default"

Controls the visual style of the tooltip surface.

roundnesssm|md|lg|xl"lg"

Controls the border-radius of the tooltip.

positionfixed|variable"variable"

Controls how the tooltip is anchored. "variable" follows the pointer (ECharts' default); "fixed" pins the tooltip near the top and only tracks the pointer's X.

defaultIndexnumber

Accepted for parity with the Recharts twin. ECharts does not surface a default-visible tooltip for sankey, so this prop has no effect.