Sankey / Flow Diagram
ProFlow diagram with reproducible column layout, cubic-bezier flow paths, width-proportional links and hover tooltip. Cyclic graphs are ranked rather than collapsed, and any flow it cannot draw is named under the diagram. Pure SVG.
import { SvSankeyChartComponent } from '@styloviz-pro/charts';Demo & usage
Basic usage
ProUsage example — open the gallery for the full interactive demo.
An interactive demo for this component lives in the gallery.
Open live demoMore examples
Sized canvas
ProFlow & node events
ProHeaviest node first
ProValidate a graph before it reaches the chart
ProWhen to use
- Visualizing flow and proportion between stages: budgets, traffic, conversions, energy.
- You want link widths proportional to magnitude.
- The process loops — returns, refunds, recycled material. A backwards flow is drawn dashed and does not disturb the column order.
- For simple stage counts, a funnel (Other Types) is lighter.
Async states
- loading
- empty
- error
- retry
Inputs
| Name | Type | Default | Description |
|---|---|---|---|
| loading | boolean | false | True while the series is being fetched. |
| error | SvDataError | string | null | null | Load failure. Use `toSvDataError()` from `@styloviz/core` to normalize an `HttpErrorResponse`. |
| emptyMessage | string | 'No data to plot' | Copy for the no-data state. |
| filtered | boolean | false | True when the emptiness is caused by a filter rather than an empty set. |
| nodes | readonly SankeyNode[] | [] | Flow nodes: { id, label } (columns are auto-laid out). |
| links | readonly SankeyLink[] | [] | Flows between nodes: { source, target, value } (value sets link width). |
| nodeOrder | SvSankeyNodeOrder | 'input' | How nodes are stacked within a column. `'input'` follows the order of the `nodes` array, so reordering that array is how a host pins the layout. `'value'` puts the heaviest nodes at the top of each column. Both are reproducible: the same inputs always draw the same diagram. |
| variant | SankeyVariant | 'default' | Visual variant. |
| width | number | 540 | Diagram width in pixels. |
| height | number | 320 | Diagram height in pixels. |
| nodeWidth | number | 18 | Node rectangle width in pixels. |
| nodePad | number | 16 | Vertical padding between nodes in pixels. |
| title | string | '' | Chart title rendered above the diagram. |
| ariaLabel | string | '' | Accessible name override for the diagram. Falls back to a generated summary. |
| customClass | string | '' | Extra CSS classes applied to the root wrapper. |
Outputs
| Event | Payload type | Description |
|---|---|---|
| retry | void | The host should re-run the failed load. |
| linkHover | SankeyLinkEvent | Emitted when a flow ribbon is hovered or keyboard-focused. |
| linkSelect | SankeyLinkEvent | Emitted when a flow ribbon is clicked or activated via keyboard (Enter/Space). |
| nodeHover | SankeyNodeEvent | Emitted when a node is hovered or keyboard-focused. |
| nodeSelect | SankeyNodeEvent | Emitted when a node is clicked or activated via keyboard (Enter/Space). |
Wire it to your API
This component is headless about transport: it renders what you give it and reports what the user asks for. Nothing below requires @styloviz/data — drive it from whatever you already use.
Template
ProBound to the names this component actually exposes.
Host class
ProDrive the three async inputs from your own fetch.
- This component does not emit a query, so it renders what you give it. Fetch on your own trigger and bind `nodes`, `loading` and `error`.
- Set `filtered` when a search or filter is active. It is the difference between "you have no orders" and "no orders match this filter" — telling a customer with 4,000 orders the first one reads as a bug.
- Normalize failures with `toSvDataError()` from `@styloviz/core`. It derives `retryable` from the status, so a 404 does not get a "Try again" button that can only fail again.
Full walkthrough: Connecting to a backend.
Customization & theming
- Reproducible column layout: longest-path ranking, with `nodeOrder` choosing input order or heaviest-first within a column.
- Width-proportional links.
- Per-node and per-link colors.
- Backwards flows drawn dashed and excluded from ranking.
Best practices
- Do: Keep node labels short; long names crowd the columns.
- Do: Ensure inflow equals outflow per node so the diagram is honest.
- Do: Order the `nodes` array the way you want each column stacked. That array is the layout control: `nodeOrder="input"` follows it exactly, and the order of `links` no longer affects the picture at all.
- Don't: Send a negative value to mean a flow in the other direction. A ribbon has no direction but the one it is drawn in, so a negative magnitude is refused and reported rather than drawn as a thin positive flow. Reverse the source and target instead.
- Tip: Color links by source or category to make paths traceable.
- Tip: Read the note under the diagram during development. It names every flow that was refused — an unusable value, an unknown endpoint, a flow carrying nothing — which is usually a payload bug rather than a charting one.
Accessibility
- The SVG is a `role="group"` with a generated summary (override via `ariaLabel`) — `group`, not `img`, because the ribbons and nodes are tab stops.
- `sv-data-summary-table` publishes one row per flow, named "Source to Destination", with its value and its share of BOTH ends. Ribbon width is the value, and the two shares are what the picture makes obvious and a bare list of numbers does not: 60 out of a 600 source is a trickle, 60 into a 60 destination is everything that destination gets.
- A backwards flow is marked "(backwards)" in its row and in its accessible name, not only by the dash. The dash is the one part of the drawing a screen reader cannot report and a colour-blind reader can miss.
- The table lists what is actually on screen. A flow the chart refused is absent from it and named in the note instead, so the rows and the ribbons never disagree.
- Ribbons and nodes are keyboard-focusable `role="button"` elements with `aria-label`s; hover/focus shows the tooltip and Enter/Space emits `linkSelect`/`nodeSelect`. Labels carry meaning beyond color.
Feedback on Sankey / Flow Diagram
Spotted a gap in this page, or something that didn't work as described? Comments are GitHub Discussions in the public styloviz/community repo, so posting needs a GitHub account.