Sankey Chart

A composable sankey diagram for visualizing flow between nodes with animated links and interactive tooltips

Preview

Installation

pnpm dlx shadcn@latest add https://ui.bklit.com/r/sankey-chart.json

Usage

The Sankey Chart uses a composable API similar to other charts. Build diagrams by combining components:

import { SankeyChart, SankeyNode, SankeyLink, SankeyTooltip } from "@bklitui/ui/charts";

const data = {
  nodes: [
    { name: "Organic Search", category: "source" },
    { name: "Homepage", category: "landing" },
    { name: "Converted", category: "outcome" },
  ],
  links: [
    { source: 0, target: 1, value: 100 },
    { source: 1, target: 2, value: 80 },
  ],
};

export default function FlowDiagram() {
  return (
    <SankeyChart data={data}>
      <SankeyLink />
      <SankeyNode lineCap={4} />
      <SankeyTooltip />
    </SankeyChart>
  );
}

Components

SankeyChart

The root component that computes the layout and provides context to children.

PropTypeDefaultDescription
dataSankeyDatarequiredObject with nodes and links arrays
marginPartial<Margin>{ top: 40, right: 180, bottom: 40, left: 180 }Chart margins
animationDurationnumber1100Animation duration in ms
aspectRatiostring"2 / 1"CSS aspect ratio
nodeWidthnumber16Width of nodes in pixels
nodePaddingnumber24Vertical padding between nodes
classNamestring""Additional CSS class

SankeyNode

Renders the nodes (bars) in the diagram with animated initialization and internal labels.

PropTypeDefaultDescription
fillstring-Fill color for all nodes
lineCapnumber4Corner radius for nodes
fadedOpacitynumber0.4Opacity when another element is hovered
showLabelsbooleantrueShow node name and value labels
getNodeColor(node, index) => string-Custom color function

Renders the links (flows) between nodes with animated path reveal and gradient colors.

PropTypeDefaultDescription
strokestring-Solid stroke color (overrides gradient)
strokeOpacitynumber0.7Link opacity
fadedOpacitynumber0.1Opacity when another element is hovered
useGradientbooleantrueUse gradient from source to target node color
getNodeColor(node, index) => string-Custom node color function for gradients
getLinkColor(link, index) => string-Custom link color (overrides gradient)
patternsReactNode-Pattern definitions using @visx/pattern components
getLinkPattern(link, index) => string | null-Return pattern ID for a link, or null for gradient

SankeyTooltip

Displays tooltips for nodes and links on hover.

PropTypeDefaultDescription
nodeContent(props) => ReactNode-Custom node tooltip renderer
linkContent(props) => ReactNode-Custom link tooltip renderer
formatValue(value) => stringtoLocaleStringValue formatter
classNamestring""Additional CSS class

Data Format

The sankey data follows the d3-sankey format:

interface SankeyData {
  nodes: Array<{ 
    name: string; 
    category: "source" | "landing" | "outcome";
    [key: string]: unknown; 
  }>;
  links: Array<{
    source: number;  // Index into nodes array
    target: number;  // Index into nodes array
    value: number;   // Flow value
  }>;
}

Animation

The sankey chart uses the same animation system as other charts:

  • Nodes: ScaleY and opacity fade in, staggered by index
  • Links: Grow from source to target node using stroke-dashoffset animation
  • Gradients: Links use gradient colors flowing from source node color to target node color
  • Easing: cubic-bezier(0.85, 0, 0.15, 1) for smooth, organic motion

Animation Timeline

  • 0-600ms: Nodes fade/scale in (staggered)
  • 200-1100ms: Links grow from source to target (staggered, starts after nodes begin appearing)

Hover Behavior

When hovering over a node or link:

  • Hovered link and its source/target nodes stay at full opacity
  • Connected nodes and links remain visible
  • All other links and nodes fade
  • Tooltip appears showing relevant data

Examples

Without Labels

For a cleaner look, hide the node labels:

<SankeyChart data={analyticsData} aspectRatio="16 / 9" nodeWidth={16} nodePadding={24} margin={{ top: 20, right: 20, bottom: 20, left: 20 }}><SankeyLink /><SankeyNode lineCap={4} showLabels={false} /><SankeyTooltip /></SankeyChart>

With Patterns

Use @visx/pattern to style specific links with patterns instead of gradients:

<SankeyChart data={analyticsData} aspectRatio="16 / 9" nodeWidth={16} nodePadding={24}><SankeyLink  getLinkPattern={getOutcomePattern}  patterns={    <>      <PatternLines id="converted" stroke="#22c55e" ... />      <PatternLines id="engaged" stroke="#eab308" ... />      <PatternLines id="bounced" stroke="#ef4444" ... />    </>  }/><SankeyNode lineCap={4} /><SankeyTooltip /></SankeyChart>

Dependencies

This component requires:

pnpm add @visx/sankey @visx/responsive @visx/pattern motion react-use-measure