Waterfall Chart
import { WaterfallChart } from '@absoluteui/components/waterfall-chart';import '@absoluteui/components/waterfall-chart/style.css';Using Angular? See Waterfall Chart for Angular.
What it does
Section titled “What it does”An accessible SVG waterfall chart that shows how a starting value changes through a sequence of increases and decreases. It provides:
- delta steps that float from the running total, total steps that drop to the baseline (an opening balance, a subtotal, or the closing total);
- dashed connectors between consecutive steps and signed value labels;
- keyboard-reachable steps (one tab stop), including steps without a value, with a tooltip on focus and hover;
- a legend of the step kinds present (Increase, Decrease, Total);
- a generated accessible summary (start, end, largest increase and decrease) and a data table fallback (change, running total, type);
- kinds that differ by color, texture, signed labels, and accessible names, never by color alone (WCAG 1.4.1).
When to use
Section titled “When to use”- Bridges from an opening to a closing value (profit and loss, cash flow, headcount changes).
- Explaining which steps contributed most to a change.
When not to use
Section titled “When not to use”- Independent values per category: use Bar Chart.
- Trends over time: use Line Chart.
- Part-to-whole without an order: use Pie Chart.
Examples
Section titled “Examples”Profit bridge with an opening total, deltas, and a closing total
Section titled “Profit bridge with an opening total, deltas, and a closing total”import { WaterfallChart, type WaterfallStep } from '@absoluteui/components/waterfall-chart';
const steps: WaterfallStep[] = [ { id: 'open', label: 'Opening', kind: 'total', value: 100 }, { id: 'sales', label: 'Sales', value: 40 }, { id: 'refunds', label: 'Refunds', value: -15 }, { id: 'other', label: 'Other', value: null }, { id: 'close', label: 'Closing', kind: 'total' },];const host = document.createElement('div');document.body.append(host);WaterfallChart.create(host, { label: 'Profit bridge', steps, valueFormat: { style: 'currency', currency: 'EUR', maximumFractionDigits: 0 }, valueAxis: { label: 'EUR' },});Custom kind colors and no connectors
Section titled “Custom kind colors and no connectors”import { WaterfallChart } from '@absoluteui/components/waterfall-chart';
const host = document.querySelector<HTMLElement>('#headcount');if (host) { const chart = WaterfallChart.create(host, { label: 'Headcount', steps: [ { id: 'start', label: 'Start', kind: 'total', value: 250 }, { id: 'hires', label: 'Hires', value: 30 }, { id: 'leavers', label: 'Leavers', value: -12 }, { id: 'end', label: 'End', kind: 'total' }, ], colors: { increase: 5, decrease: 6, total: 1 }, connectors: false, }); host.dataset.summary = chart.summary;}import { WaterfallChart } from '@absoluteui/components/waterfall-chart';import '@absoluteui/components/waterfall-chart/style.css';
const host = document.querySelector<HTMLElement>('#cash');if (host) { WaterfallChart.create(host, { label: 'Cash flow', steps: [ { id: 'start', label: 'Start', kind: 'total', value: 500 }, { id: 'in', label: 'Receipts', value: 320 }, { id: 'out', label: 'Payments', value: -410 }, { id: 'end', label: 'End', kind: 'total' }, ], valueFormat: { style: 'currency', currency: 'USD', maximumFractionDigits: 0 }, });}More usage
Section titled “More usage”import { WaterfallChart, type WaterfallStep } from '@absoluteui/components/waterfall-chart';
const steps: WaterfallStep[] = [ { id: 'open', label: 'Opening', kind: 'total', value: 100 }, { id: 'sales', label: 'Sales', value: 40 }, { id: 'refunds', label: 'Refunds', value: -15 }, { id: 'close', label: 'Closing', kind: 'total' },];const host = document.createElement('div');document.body.append(host);WaterfallChart.create(host, { label: 'Profit bridge', steps });Export: @absoluteui/components/chart-export (chartToSvg, chartToPng, downloadChart) exports any chart instance to SVG or PNG.
Anatomy
Section titled “Anatomy”<div class="aui-chart aui-waterfall-chart [aui-chart--patterns]"> <div class="aui-chart__header"> <div class="aui-chart__title" id="T">title</div> <p class="aui-chart__description" id="D">description</p> <div class="aui-chart__toolbar" hidden/> </div> <ul class="aui-chart__legend" aria-label="Legend"> <li class="aui-chart__legend-entry"><span class="aui-chart__legend-item"><svg class="aui-chart__swatch" aria-hidden="true"/>Increase</span></li> </ul> <div class="aui-chart__body"> (height: --aui-chart-height) <svg class="aui-chart__svg" role="group" aria-roledescription="waterfall chart" aria-labelledby="T" aria-describedby="D S"> <g class="aui-chart__grid" aria-hidden="true"/> <g class="aui-chart__axis …" aria-hidden="true"/> <g class="aui-waterfall-chart__connectors" aria-hidden="true"><line class="aui-chart__connector"/>...</g> <g class="aui-waterfall-chart__bars"> <g class="aui-waterfall-chart__step aui-waterfall-chart__step--increase aui-chart__series--c3"><rect class="aui-chart__mark aui-chart__bar" role="img" aria-label="Sales: +40 (Increase), running total 140" tabindex="0"/><rect class="aui-chart__pattern" aria-hidden="true"/></g> <rect class="aui-chart__mark aui-waterfall-chart__gap" role="img" aria-label="Other: no value, running total 140"/> </g> <g class="aui-waterfall-chart__labels" aria-hidden="true"><text class="aui-chart__value-label">+40</text>...</g> </svg> <div class="aui-chart__empty" hidden/> <div class="aui-chart__tooltip" aria-hidden="true" hidden/> </div> <p class="aui-chart__summary" id="S" hidden>generated summary</p> <div class="aui-chart__data">...Show data table...</div></div>API reference
Section titled “API reference”Factory
Section titled “Factory”WaterfallChart.create(host: HTMLElement, options: WaterfallChartOptions): WaterfallChartGlobal configuration key: waterfallChart (see Configuration).
Options
Section titled “Options”| Option | Type | Default | Description |
|---|---|---|---|
label |
string |
Chart title: visible text and the accessible name of the plot (aria-labelledby). Required. | |
hideLabel |
boolean |
false |
Visually hide the title; it stays the accessible name. |
description |
string |
Visible description below the title, also referenced by aria-describedby (text only). | |
summary |
string |
Replaces the generated accessible summary (aria-describedby). | |
valueFormat |
Intl.NumberFormatOptions |
Number format for values in tooltips, labels, the data table, the summary, and axis ticks (ticks use fixed fraction digits). | |
formatValue |
(value: number) => string |
Custom value text; overrides valueFormat everywhere except axis ticks. | |
hiddenSeries |
readonly string[] |
Accepted and validated (string[]) for the shared chart contract; a waterfall has no series, so it has no effect. | |
steps |
readonly WaterfallStep[] |
Steps in order: { id, label, value?: number | null, kind?: ‘delta’ | ‘total’ }. Ids are unique and non-empty. delta (default): the change (null: a gap, the running total carries over). total: with a value, the running total becomes it (an opening balance); without, the bar shows the current running total. Required. | |
colors |
{ increase?: ChartColor; decrease?: ChartColor; total?: ChartColor } |
Palette slots (1-8) per step kind. Default increase 3, decrease 2, total 1. | |
categoryAxis |
{ label?: string } |
Category axis title (also the first table column header; default “Category”). | |
valueAxis |
{ label?: string; min?: number; max?: number; tickCount?: number; includeZero?: boolean } |
Value axis title, fixed domain, and tick count (2-20). The domain always includes zero. | |
legend |
'auto' | 'show' | 'hide' |
"auto" |
Legend of the step kinds present (Increase, Decrease, Total); not toggleable. auto and show display it, hide removes it. Globally configurable. |
dataTable |
'toggle' | 'visible' | 'hidden' | 'none' |
"toggle" |
Data table fallback with the exact data: behind a Show data table button (built on first open), always visible, visually hidden (screen readers only), or none. Globally configurable. |
tooltip |
boolean |
true |
Tooltip on pointer hover and keyboard focus. Globally configurable. |
patterns |
boolean |
false |
Texture fills (and dash patterns for lines) so marks never differ by color alone (always on in forced colors). Globally configurable. |
height |
number |
300 |
Plot height in CSS px (integer 120-2000); the width follows the container. Globally configurable. |
valueLabels |
boolean |
true |
Signed change (deltas) or total printed above the bar (below for decreases and negative totals); a label wider than the step is omitted. Globally configurable. |
connectors |
boolean |
true |
Dashed connectors (aria-hidden) from each step to the next at the running total; none into a total step. Globally configurable. |
locale |
string |
"en-US" |
Number and message locale. Globally configurable. Inherited from common configuration. |
direction |
'ltr' | 'rtl' |
"ltr" |
rtl mirrors the category axis (first step at the right), puts the value axis on the right, and swaps ArrowLeft/ArrowRight. Globally configurable. Inherited from common configuration. |
Properties
Section titled “Properties”| Property | Type | Description |
|---|---|---|
host |
HTMLElement |
The host element. |
element |
SVGSVGElement |
The plot (svg role=“group”), named by the title and described by the summary. |
summary |
string |
The generated (or custom) accessible summary. |
hiddenSeries |
string[] |
Always empty (a waterfall has no series). |
Methods
Section titled “Methods”| Method | Description |
|---|---|
update(options: Partial<WaterfallChartOptions>): void |
Merge, validate, and re-render. Invalid options throw and keep the previous state. Keyboard focus stays on the same mark when it still exists. |
setSeriesVisible(id: string, visible: boolean): void |
Inherited from the shared chart controller; no visible effect (a waterfall has no series). |
destroy(): void |
Remove rendering, host classes, listeners, the resize observer, and the configuration subscription. |
CSS classes
Section titled “CSS classes”All rules live in the aui.components cascade layer, so application styles override them without specificity battles.
| Class | Purpose |
|---|---|
aui-chart |
Host (shared chart chrome). |
aui-waterfall-chart |
Host modifier for this chart type. |
aui-chart--patterns |
patterns option on: textures (and dash patterns) shown. |
aui-chart__header / __title / __title--hidden / __description |
Title and description. |
aui-chart__legend / __legend-entry / __legend-item / __legend-item--hidden / __legend-label |
Legend list and its entries. |
aui-chart__swatch |
aria-hidden legend and tooltip key (marker, dash, texture). |
aui-chart__body / __svg / __layer |
Plot container (height from –aui-chart-height), SVG, and drawing layer. |
aui-chart__grid / __gridline / __zero-line / __axis / __axis-line / __tick-label / __axis-title |
Axes (aria-hidden). |
aui-chart__series--c1 ... --c8 |
Palette slot classes; set –aui-chart-color from color-chart-<n>. |
aui-chart__mark / __mark--active / __mark--hover |
Focusable data mark and its states. |
aui-chart__tooltip / __tooltip-title / __tooltip-rows / __tooltip-row / __tooltip-label / __tooltip-value |
Tooltip (aria-hidden; the focused mark carries the same text). |
aui-chart__empty |
Empty state text (No data, All series are hidden). |
aui-chart__summary |
Hidden summary referenced by aria-describedby. |
aui-chart__data / __data--hidden / __table-toggle / __table-scroll / __table / __cell--numeric |
Data table fallback. |
aui-chart__pattern / aui-chart__pattern-tile |
Texture overlays (aria-hidden). |
aui-chart__bar / __line / __area / __point / __connector / __value-label |
Shared mark styles (chart-marks): bars, lines, areas, point markers, dashed connectors, printed values. |
aui-waterfall-chart__bars / __step / __step--increase / __step--decrease / __step--total |
Bars layer and per-step groups by kind. |
aui-waterfall-chart__gap |
Invisible focus target of a step without a value, on the running-total level. |
aui-waterfall-chart__connectors / __labels |
Connector and value label layers (aria-hidden). |
Design tokens
Section titled “Design tokens”Tokens this stylesheet reads (verified in CI). Override them in a theme or with the Theme Designer.
--aui-border-width | --aui-color-border | --aui-color-border-strong | --aui-color-chart-1 | --aui-color-chart-2 | --aui-color-chart-3 | --aui-color-chart-4 | --aui-color-chart-5 | --aui-color-chart-6 | --aui-color-chart-7 | --aui-color-chart-8 | --aui-color-chart-axis | --aui-color-chart-grid | --aui-color-focus-ring | --aui-color-hover | --aui-color-link | --aui-color-surface | --aui-color-surface-sunken | --aui-color-text | --aui-color-text-muted | --aui-duration-fast | --aui-easing-standard | --aui-focus-ring-offset | --aui-focus-ring-width | --aui-font-family-sans | --aui-font-size-md | --aui-font-size-sm | --aui-font-size-xs | --aui-font-weight-medium | --aui-font-weight-regular | --aui-font-weight-semibold | --aui-line-height-normal | --aui-line-height-tight | --aui-radius-md | --aui-radius-sm | --aui-shadow-md | --aui-space-1 | --aui-space-2 | --aui-space-3 | --aui-tooltip-max-width | --aui-touch-target-min
TypeScript definitions
Section titled “TypeScript definitions”type WaterfallStepKind = 'delta' | 'total';interface WaterfallStep { id: string; label: string; value?: number | null; kind?: WaterfallStepKind }interface WaterfallChartColors { increase?: ChartColor; decrease?: ChartColor; total?: ChartColor }interface WaterfallChartConfig { legend: ChartLegendMode; dataTable: ChartTableMode; tooltip: boolean; patterns: boolean; height: number; valueLabels: boolean; connectors: boolean }interface WaterfallChartOptions extends ChartCommonOptions, Partial<WaterfallChartConfig> { steps: readonly WaterfallStep[]; colors?: WaterfallChartColors; categoryAxis?: { label?: string }; valueAxis?: WaterfallChartValueAxis; // { label?; min?; max?; tickCount?; includeZero? }}Accessibility
Section titled “Accessibility”Pattern: SVG chart as a named, described group (role=“group” with aria-roledescription) of role=“img” data marks with roving focus; data table fallback (native table). Follows the WAI Complex Images tutorial (short name plus long description) and the roving tabindex technique of WAI-ARIA APG.
Keyboard
Section titled “Keyboard”| Key | Context | Action |
|---|---|---|
| ArrowLeft / ArrowRight (also ArrowUp / ArrowDown) | Step focused | Previous / next step; Left/Right are mirrored in RTL. Steps without a value are reachable too. |
| Home / End | Step focused | First / last step. |
| PageUp / PageDown | Step focused | Ten steps back / forward. |
| Escape | Tooltip visible | Hides the tooltip without moving focus (WCAG 1.4.13); it returns on the next move. |
| Tab / Shift+Tab | Any | One tab stop for the plot (the active step), then the Show data table button and table region. |
| Element | Role |
|---|---|
| svg.aui-chart__svg | group with aria-roledescription (localized chart type), named by the title |
| data marks | img with an aria-label: step, signed change, kind, and running total (totals: the total) |
| legend | list (ul) named “Legend” of the step kinds; entries are text (not toggleable) |
| axes, connectors, value labels, textures, tooltip | aria-hidden (decorative duplicates of the accessible data) |
| data table | table (native) with caption, column headers, and row headers; wide tables scroll in a focusable region |
ARIA attributes
Section titled “ARIA attributes”| Attribute | Element | Value |
|---|---|---|
aria-labelledby |
svg | id of the visible (or visually hidden) title |
aria-describedby |
svg | description id (when provided) and the generated summary id |
aria-roledescription |
svg | Localized “waterfall chart” |
aria-label |
each mark | Localized “{label}: {change} ({kind}), running total {total}”; totals “{label}: total {total}”; gaps “{label}: no value, running total {total}”. Example: “Closing: total 125” |
tabindex |
active mark | 0 on exactly one mark (roving); other marks have none |
aria-expanded / aria-controls |
Show data table button | Table open state and the table region id |
Roving focus: one step is in the tab sequence and remembers the last visited step across re-renders (resize, update). Toggling the table keeps focus on the table button.
WCAG 2.2 success criteria addressed
Section titled “WCAG 2.2 success criteria addressed”Automated test results: Accessibility and compliance.
Notes and known caveats
Section titled “Notes and known caveats”- The generated summary names the chart type, step count, start and end values, and the largest increase and decrease with their steps.
- Increases, decreases, and totals differ by color, by texture (patterns), by signed value labels, and by their accessible names and table Type column, never by color alone.
- Forced colors: marks use CanvasText (bubbles and outlines Canvas/CanvasText) and keep shapes and textures; focus uses Highlight.
- No animation: nothing moves on render; hover and focus emphasis transitions are removed under prefers-reduced-motion and animation: none.
- Manual screen-reader verification (NVDA, JAWS, VoiceOver, TalkBack) is pending.
- aria-roledescription support varies; screen readers without it announce “group”.
Behavior
Section titled “Behavior”States
Section titled “States”default, empty (“No data”), step focused (tooltip), hovered, table open.
State transitions
Section titled “State transitions”| From | Trigger | To |
|---|---|---|
| plot not focused | Tab | active step focused, tooltip shown |
| step focused | arrow keys, Home, End, PageUp, PageDown | another step focused |
| tooltip visible | Escape | tooltip hidden, focus unchanged |
| table closed | Show data table | table built and shown |
| any | container resize | re-render at the new width; focus kept on the same step |
Accessibility notes
Section titled “Accessibility notes”- The summary names the type, step count, start and end values, and the largest increase and decrease, for example “waterfall chart, 5 steps. Starts at 100, ends at 125. Largest increase: Sales (+40). Largest decrease: Refunds (-15).”
- Increases, decreases, and totals differ by color, texture, signed labels, accessible names, and the table’s Type column.
- Forced colors use
CanvasTextand keep textures; focus usesHighlight. Nothing animates. - Manual screen-reader verification is pending.
Responsive behavior
Section titled “Responsive behavior”The width follows the container (ResizeObserver); the height is height. Category labels thin and truncate with the band width; value labels wider than about one step are omitted. Reflows at 320 CSS px.
Right-to-left
Section titled “Right-to-left”direction: 'rtl' mirrors the category axis (first step at the right), puts the value axis on the right, mirrors connectors, and swaps ArrowLeft/ArrowRight.
Theming
Section titled “Theming”Kind colors come from color-chart-<n> via colors (increase 3, decrease 2, total 1 by default). Connectors use color-chart-axis; value labels color-text with a surface halo.
Global configuration
Section titled “Global configuration”configureAbsoluteUI({ components: { waterfallChart: { connectors: false, valueLabels: true, height: 280 } } });Changes apply to existing instances immediately.
Component configuration
Section titled “Component configuration”Instance options override global and theme defaults. All options are dynamic.
Timezones
Section titled “Timezones”Not applicable: steps are text categories; no dates are formatted.
None. Legend keys are drawn shapes; no toolbar is shown.
Security
Section titled “Security”All text uses textContent; SVG is built with createElementNS. Colors are classes; sizes and the tooltip position are written through the CSSOM. No innerHTML, style attributes, or inline handlers.
Data handling
Section titled “Data handling”Renders the given data only; no persistence, network access, or telemetry. Validation errors name the option, never its value.
Performance
Section titled “Performance”Budget: WaterfallChart.create with 200 steps under 40 ms in headless Chromium, including the first render (e2e performance test, tests/e2e/perf-r3.spec.ts). One DOM node per step; the data table is built only when opened in toggle mode.
Supported data scale
Section titled “Supported data scale”Tested with 200 steps; labels thin out on narrow plots.
Edge cases
Section titled “Edge cases”- No steps, or only steps without a value: “No data”.
- A delta of
nullis a gap: no bar, an invisible focus target at the running total, the total carries over. - A zero change is drawn as a 1 px bar and labelled “Increase”.
- Negative running totals: the domain crosses zero; decreases and negative totals put their labels below the bar.
- The first delta starts from zero; a leading total with a value sets the opening balance.
Errors
Section titled “Errors”| Code | Category | Cause |
|---|---|---|
WATERFALL_CHART_OPTIONS |
configuration | Missing label; steps not an array; step ids not unique or empty; non-string labels; non-numeric values; invalid kind; colors outside 1-8; invalid axis options. |
CFG_INVALID_VALUE / CFG_UNKNOWN_OPTION |
configuration | Invalid or unknown configuration. |
A failed construction leaves the host untouched; a failed update() keeps the previous state.
Known limitations
Section titled “Known limitations”- One sequence per chart; no series or legend toggling.
- Totals always start at zero.
- Value labels are omitted when wider than the step.
- Manual screen-reader verification is pending.
Unsupported scenarios
Section titled “Unsupported scenarios”- Horizontal orientation; grouped or stacked waterfalls.
- Zoom, pan, and crosshair.
- HTML in labels or tooltips.