Skip to content
quartiledocsv0.1
GitHub

Sankey

PreviewSVGPublishes selection

Shows how a quantity flows from one set of categories to another, such as traffic channel to outcome.

Playground

Sessions by channel and outcome
Sep 7 – Oct 6, 2026

Flows from Channel to Outcome: total 80,870 across 12 paths. Largest: Paid social → Bounced (16,800), Organic search → Bounced (12,400), Paid social → Abandoned cart (10,100).

Sessions by channel and outcome
ChannelOutcomeSessions
Organic searchPurchased5,840
Organic searchAbandoned cart9,210
Organic searchBounced12,400
Paid socialPurchased5,480
Paid socialAbandoned cart10,100
Paid socialBounced16,800
EmailPurchased4,150
EmailAbandoned cart3,900
EmailBounced3,100
DirectPurchased2,790
DirectAbandoned cart2,400
DirectBounced4,700
nodeWidth
<Sankey
  data={channelFlows}
  from="channel"
  to="outcome"
  value="sessions"
  select
/>

Installation

Sankey is exported from @quartile/react, alongside every other chart and component.

git clone https://github.com/zinnoberHaus/quartile

Not on npm yet: build the package from the clone as described in Installation. The preview API may change before publication.

Usage

One row per flow; rows that share a pair are summed. A name used in both from and to links the stages.

import { Sankey } from '@quartile/react';

const flows = [
  { channel: 'Email', outcome: 'Purchased', sessions: 4150 },
  { channel: 'Email', outcome: 'Bounced', sessions: 6200 },
  { channel: 'Paid social', outcome: 'Purchased', sessions: 5480 },
];

export function ChannelOutcomes() {
  return <Sankey data={flows} from="channel" to="outcome" value="sessions" select />;
}
With select, clicking a node (or Enter on it) toggles it in the selection on the from or to field; Shift adds. See Linked selections.

Props

PropTypeDefaultDescription
datarequiredDataInput<R>—Rows of flows (aggregated per pair), or a dataset with a schema attached.
fromrequiredkeyof R & string—Field naming where a flow starts.
torequiredkeyof R & string—Field naming where a flow ends. A name used in both fields links the stages.
valuekeyof R & string—Flow size. Counts rows when omitted.
formatFormatter—Formats flow sizes. Defaults to the field's schema format.
nodeWidthnumber14Node bar width in px.
nodePaddingnumber10Vertical gap between nodes in px.
selectbooleanfalseClick (or Enter) on a node toggles it in the selection on from or to. Shift adds.
idstring—Publisher id for the selection. Defaults to a generated id.
selectionstring | false—Selection to read from and publish to. Defaults to the nearest; false opts out.
onSelect(predicate: Predicate | null) => void——
Frame and state props shared with the charts (11) · ChartBaseProps, ChartStateProps
PropTypeDefaultDescription
heightnumber220Plot height in px. Width always fills the container.
classNamestring——
styleCSSProperties——
aria-labelstring—Accessible name. A summary of the data is generated and rendered as hidden text inside the figure.
view'chart' | 'table'—table renders the same data as a table, with the same formats, at the chart's size. Large lazy tables expose a data-view control rather than mounting every hidden row.
tooltipNotestring—Plain-text context shown with tooltips and included in the accessible chart description.
loadingboolean | string—Shows the loading state at the chart's size, so the layout never jumps.
errorboolean | string | Error | null—Shows the error state. A string or Error becomes the message.
errorCodestring—Shown in the error state; copyable for support.
onRetry() => void——
empty{ title?: string; description?: string; action?: ReactNode }—Title and description for the empty state. Shown when there are no rows.

Accessibility

Keyboard
Tab into the diagram; arrow keys move through nodes and then flows. With select, Enter or Space toggles the focused node and Shift adds it.
Screen readers
A summary gives the total, the number of paths and the largest flows. The focused node or flow is announced as you move.
Table fallback
Screen readers always get a table of the plotted values with the same formats. view="table" shows it at the chart's size.
Report an issueBuilt Oct 21, 2026