---
id: "packages/active-charts/all-exports/sankey-chart"
title: "SankeyChart"
description: "SankeyChart, SankeyChartProps, SankeyLinkColor, SankeyNodeAlignment and 1 more: generated from the source of active-charts."
url: "/packages/active-charts/all-exports/sankey-chart"
locale: "en"
revision: "g0mvjxwj5c-88bdbe1c:sankey-chart"
---

# SankeyChart

Exported by `@workspace/active-charts`. Generated from the package source; part of [the index of every export](/packages/active-charts/all-exports).

## `SankeyChart`

| Prop | Type | Required | Description |
| --- | --- | --- | --- |
| `height` | `number` | yes | Container height in pixels. Width is always responsive. |
| `links` | `LinkDatum<TLinkExtra>[]` | yes | Graph links. `source` and `target` reference node ids. |
| `nodes` | `NodeDatum<TNodeExtra>[]` | yes | Graph nodes. Each `id` must be unique. |
| `accessibility` | `StandaloneAccessibilityOptions` | no | Accessible name, description, data table and keyboard navigation. No `announcements`: it switches `<Chart>`'s interaction announcements, which this family does not make. |
| `animation` | `InteractionAnimationOption` | no | How the tooltip and the context's attention move; the family has no entrance. `false` turns every interpolation off. |
| `className` | `string` | no | Optional className applied to the outer container. |
| `colors` | `string[]` | no | Categorical palette for this chart only: replaces the host palette (`--chart-1` … `--chart-10`) in the chart's colour assignment, and nothing else. It is a data encoding, not a theme: surfaces, text, grid and semantic roles keep coming from the CSS token contract, and a series, datum or annotation that sets its own colour keeps it. Any CSS colour string (a public token reference such as `var(--chart-3)`, hex, oklch). |
| `contextMenu` | `FeatureOption<ChartContextMenuOptions<SankeyElement<TNodeExtra, TLinkExtra>, "copy" \| "export">>` | no | The context menu. Opened on a node or a link, the host's builder receives a typed {@link SankeyElement} (`{kind: 'node', node}` or `{kind: 'link', link}`; a node wins over a link beneath it) as `context.target.element`. |
| `defaultSelectedItems` | `readonly ChartItemRef[]` | no | The initial selection of an uncontrolled chart. |
| `dir` | `"ltr" \| "rtl"` | no | The chart's UI direction: the reading direction of its HTML text and chrome (tooltip, legend, menus, the accessible table), and the direction the context menu carries under `<body>`.  Left out, the chart inherits the direction of the page around it (the nearest `dir` attribute, else the computed CSS direction) and follows a later change of that attribute. It is never inferred from `locale`, and it never reverses an axis or reorders data: `reversed` stays an explicit axis choice. Under `rtl` the chrome mirrors (legend flow, tooltip side, context menu and submenus, report text in exports), a title-like label starts at the inline start, and a label placed by geometry (an axis tick, a slice or bar label) keeps its physical side; plot arrow keys stay spatial while legend and menu arrows follow the reading direction. |
| `events` | `(Omit<ChartEvents, "onLegendChange" \| "onZoomChange"> & ChartSelectionEvents<never, ChartNodeItem<NodeDatum<TNodeExtra>> \| ChartLinkItem<LinkDatum<TLinkExtra>>>)` | no | The chart's events, and the selection events (T8): an item is a node (`{kind: 'node', id}`) or a link (`{kind: 'link', id?, source, target}`). Space selects the keyboard's node or link and Shift+Enter activates it; Enter keeps moving between nodes and links. |
| `labelPadding` | `number` | no | Horizontal space reserved on each side for the labels of the first and the last column, in pixels. Default: measured from those labels (VQ5), up to a quarter of the width per side. |
| `linkColor` | `SankeyLinkColor` | no | The colour of a flow (T6). Default `'source'`: its source node's; `'target'`: its target node's; `'gradient'`: from the source's colour to the target's along the flow. A link's own `color` wins in every mode. Colour carries a node's identity along its flows only: the tooltip, the table and the keyboard name both ends. |
| `locale` | `ValuePresentation` | no | Presentation input for axis labels, tooltips, labels and accessibility announcements: a locale code (notation follows the language), or a presentation-context object (`{languageLocale, dateShape?, dateFormat?, timeFormat?, numberFormat?, currencyDisplay?}`) carrying language and notation independently. `dateShape` is the normal human date shape a plain date consumer inherits; an axis that declares its own preset for readability keeps it. Forwarded untouched to the central `@workspace/active-format`; the package never resolves tenant or application settings itself. When omitted, `<ChartDefaults>` supplies it; with neither, the chart throws a configuration error (no `'en'` fallback, active-format D14). Object inputs must be referentially stable across renders. |
| `nodeAlignment` | `SankeyNodeAlignment` | no | The column of a node (T6). Default `'justify'`: every node at its distance from the sources, and every sink in the last column. `'source'`: every node at its distance from the sources (a sink can stand in a middle column). `'sink'`: every node at its distance to the sinks (a source can stand in a middle column). `'center'`: as `'source'`, with a source drawn just before its first target. Flow terms, not left and right: the sankey does not mirror in `rtl`. |
| `nodeOrder` | `SankeyNodeOrder` | no | The order of the nodes within a column (T6). Default `'auto'`: the layout's own order, which reduces crossing flows. `'input'`: the order of `nodes`, so comparable charts keep every node in its place. The data table keeps the order of `links` either way. |
| `nodePadding` | `number` | no | Vertical padding between nodes in pixels. Default: 16. |
| `nodeWidth` | `number` | no | Node width in pixels. Default: 20. |
| `onAnimationComplete` | `((event: AnimationCompleteEvent) => void)` | no | Fired when a chart animation completes. - `'load'`: initial mount animation finished (or immediately if animation disabled / prefers-reduced-motion is active). - `'update'`: data-update transition finished.  Not triggered by zoom animations (use `onZoomChange`) or tooltip fades. |
| `onExportComplete` | `((result: ChartExportResult) => void)` | no | Fired after a successful export action (PNG/SVG/CSV/PDF), including from the context menu and from imperative `ChartHandle` calls. |
| `onExportError` | `((format: ChartExportFormat, error: unknown) => void)` | no | Fired when an export could not produce its file (W11), from the handle as well as from the context menu. Without it a failed context-menu export is reported as an error diagnostic (`<ChartDefaults diagnostics>`). |
| `onItemActivate` | `((item: ChartNodeItem<NodeDatum<TNodeExtra>> \| ChartLinkItem<LinkDatum<TLinkExtra>>, source: ChartInteractionSource) => void)` | no | Fired when the reader activates an item: a click or tap on it, or `Enter` on the focused item (`Shift+Enter` on a sankey, whose `Enter` moves between nodes and links). With a handler, `Enter` activates instead of opening the context menu (`Shift+F10` and the context-menu key still open it). |
| `onReady` | `(() => void)` | no | Fired exactly once per chart instance, after the first successful mount with valid dimensions and **before** any entrance animation starts. "Ready" means: the SVG is in the DOM, layout has run with real dimensions, and the chart can be queried by integration tests.  Distinct from {@link onAnimationComplete} with `type: 'load'`, which fires *after* the load animation finishes. A chart with `animation={false}` still fires `onReady` — animation state has no effect on readiness.  A new React `key` on the host produces a new component instance and `onReady` fires again. Identity changes of the callback itself after the first fire are ignored (latch is per-instance).  **Consumer requirement — stable from first render.** The latch closes on the first effect run regardless of whether `onReady` was defined at that moment. If `onReady` is initially `undefined` and later resolves to a function, the callback will **never** fire — the latch has already closed with a no-op. Pass a stable reference (typically via `useCallback`) or pass the final function unconditionally from the first render. |
| `onSelectionChange` | `((selection: ChartItemRef[], change: ChartSelectionChange<never, ChartNodeItem<NodeDatum<TNodeExtra>> \| ChartLinkItem<LinkDatum<TLinkExtra>>>) => void)` | no | Fired when the reader changes the selection (pointer, touch or keyboard), and when an uncontrolled selection drops items the data no longer contains. `selection` is the complete selection the change makes; it keeps every reference the selection held, of whatever form. On a controlled chart it is a proposal (`change.requested: true`), computed from the current `selectedItems` and never from an earlier proposal; the host applies it, changes it or ignores it. |
| `ref` | `Ref<ChartExportHandle>` | no | Imperative handle: exports and element access. A family built on this type has no data-range zoom, so its handle has no `setZoom`. Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref). |
| `selectedItems` | `readonly ChartItemRef[]` | no | The selection, controlled by the host. The chart draws, announces and lists the items it resolves to and never changes it; the host updates it from `onSelectionChange`. A request the host applies is announced when the host passes it back; one it ignores is never announced. A reference to an item that is hidden, zoomed or drilled out of view, or not in the data stays in the host's selection and is not shown as selected. |
| `selection` | `FeatureOption<Omit<ChartSelectionOptions, "itemKey">>` | no | Item selection. `true` = single selection keyed by the default key. |
| `t` | `ChartTranslateFn` | no | The host translator for every text the chart shows or announces. When omitted, `<ChartDefaults>` supplies it; with neither, the chart throws a configuration error (no English fallback, ADR-028). |
| `tooltip` | `StandaloneTooltipOption<never>` | no | Tooltip of the node or link under the pointer: `enabled`, `renderer`, `valueFormatter` and `style` (ADR-082, LAB-AT17). |
| `valueSemantics` | `ChartValueSemantics` | no | What the flow values mean (BC1): unit and precision, declared once with the type the Cartesian charts read (`ChartValueSemantics`). The tooltip of a link and of a node (its fixed value, else the larger of its in- and outflow, as today), the data table and the announcement write the value in it; `tooltip.valueFormatter` still wins in the tooltip. The node labels keep their names. Without a declaration the chart presentation's number applies. CSV and Copy value keep the raw number. |
| `width` | `number` | no | Optional fixed width in pixels. Default: fill container. |

## Types

**SankeyChartProps**

```ts
interface SankeyChartProps<
  TNodeExtra extends Record<string, unknown> = Record<string, unknown>,
  TLinkExtra extends Record<string, unknown> = Record<string, unknown>,
>
  extends
    Omit<GraphChartProps<TNodeExtra, TLinkExtra>, 'events'>,
    ChartSelectionProps<
      never,
      | ChartNodeItem<NodeDatum<TNodeExtra>>
      | ChartLinkItem<LinkDatum<TLinkExtra>>,
      Omit<ChartSelectionOptions, 'itemKey'>
    > {
  events?: NonNullable<GraphChartProps<TNodeExtra, TLinkExtra>['events']> &
    ChartSelectionEvents<
      never,
      | ChartNodeItem<NodeDatum<TNodeExtra>>
      | ChartLinkItem<LinkDatum<TLinkExtra>>
    >;
  nodeWidth?: number;
  nodePadding?: number;
  labelPadding?: number;
  valueSemantics?: ChartValueSemantics;
  nodeAlignment?: SankeyNodeAlignment;
  linkColor?: SankeyLinkColor;
  nodeOrder?: SankeyNodeOrder;
}
```

**SankeyLinkColor**

```ts
type SankeyLinkColor = 'source' | 'target' | 'gradient';
```

Whose colour a flow takes (T6).

**SankeyNodeAlignment**

```ts
type SankeyNodeAlignment = 'justify' | 'source' | 'sink' | 'center';
```

The column rule of a sankey's nodes (T6).

**SankeyNodeOrder**

```ts
type SankeyNodeOrder = 'auto' | 'input';
```

The order of a sankey's nodes within a column (T6).
