Skip to main content
A sankey diagram draws flows between nodes, each flow as wide as its amount. What runs through a system, and where it ends up, reads at a glance: energy from its sources to its uses, a budget from income to spending, visitors from a landing page to a sale.
The sankey ships as its own package, @graphysdk/geom-sankey, on a 0.x version line. While it is on 0.x, a minor release may change its aesthetics, params, style or look; pin a caret range (^0.1.0) to take only patches. Tell us what works and what doesn’t on Discord.

Install

It peer-depends on @graphysdk/react and nothing else. Register the plugin once with createGraphyKit, which adds kit.geom.sankey() and binds kit.GraphProvider to the same plugin:

A sankey diagram

Pass one row per flow. Map the node it leaves to source, the node it reaches to target and its amount to value:
The nodes are the names the flows share, each as tall as the larger of what flows into it and what flows out. The flows run from left to right, a node in the column after every node that flows into it, and each flow is as wide at both ends as its amount. The geom lays itself out across the panel, so it takes no scales and draws no axes. A missing, zero or negative amount draws no flow and adds nothing to either node. A flow from a node to itself, or one that would close a loop with the rows before it, is left out: a sankey’s flows run one way.

Color

Each node takes its own color from the palette, and each flow the color of the node it leaves, as above. Each node already carries its name, so the chart draws no legend for it unless you set config.legend.position. Color always groups by node. Map it to your source or target column to choose which node a flow takes its color from: A node keeps its own color either way. Any other column is refused with UNSUPPORTED_MAPPING: a node has no value in it, so every node would fall into one group. Set color: { value: '#…' } to paint every node and flow one color.

Alignment

params.align chooses the column a node sits in:

Styling

A sankey paints three things, each with its own builder: The outline keeps a name legible where it crosses a flow. The flows and the nodes read the color scale, and the scale beats an entry in defaults, so an entry that replaces their color is an override. Every entry takes a where, which tests the observation it paints:
A flow’s fill takes a pattern (diagonal, crosshatch or dots) or a gradient as well as a color, and so does a node’s.

Hover and highlight

Hovering a node raises it with every flow into and out of it; hovering a flow raises it with the two nodes it joins. Everything else dims. A node’s tooltip is headed by its name and gives its total; a flow’s is headed by the node it leaves, and names where it goes:
A highlight raises each matched node and flow. A node holds its own name in your source column, so matching a source raises the node with the flows leaving it:
A node’s total is written into your amount column, so highlight({ variable: 'twh', gt: 100 }) matches the nodes and the flows over 100.

Not yet supported

  • The editor’s chart-type picker and the chart agent. In editable mode the sankey renders and takes annotations on a node’s center or a flow’s middle, but it is authored in code.
  • Color by a column other than the source or target. Color groups by node.
  • A flow colored from its source to its target. A flow takes one color; a gradient between its two nodes’ colors is not drawn.
  • Node width and spacing. The nodes and the gaps between them are sized to the panel, and are not yet options.
  • Loops. A flow that would close a loop is left out rather than drawn back around.
  • Names that would overlap. A name is drawn however short its node is, so the names of two short nodes in one column can meet.