import { Component } from '@angular/core';
import { WrWaterfallChart } from 'ngwr/charts/waterfall-chart';
@Component({ imports: [WrWaterfallChart] })
export class MyComponent {}Waterfall Chart
How a figure gets from one value to another, one change at a time.
Installation
Import the class, and @use the entry point in your global styles: without it the component renders unstyled.
Basic
A change floats from the running total. A total is a bar from zero. Up, down and total each have their own colour, sign and direction.
<wr-waterfall-chart
ariaLabel="Profit bridge"
[steps]="[
{ label: 'Opening', value: 4200, total: true },
{ label: 'Sales', value: 1800 },
{ label: 'Refunds', value: -350 },
{ label: 'Payroll', value: -900 },
{ label: 'Closing', value: 4750, total: true }
]"
/>Totals
A total shows the running total, and its value is checked rather than drawn: in dev mode, a value the steps above do not add up to warns. A total before every change opens the chart at its value.
<wr-waterfall-chart [steps]="months" />months: WrWaterfallStep[] = [
{ label: 'Start', value: 1200, total: true }, // opens the chart
{ label: 'Jan', value: 300 },
{ label: 'Feb', value: -150 },
{ label: 'Mar', value: 420 },
{ label: 'Q1', value: 1770, total: true }, // checked: 1200 + 300 − 150 + 420
{ label: 'Apr', value: -80 },
{ label: 'May', value: 260 },
{ label: 'Jun', value: 190 },
{ label: 'H1', value: 2140, total: true },
];Below zero
The value axis always includes zero. A running total below it hangs under the zero line.
<wr-waterfall-chart [steps]="cash" />Colours
increaseColor, decreaseColor and totalColor take any CSS colour. Success, danger and primary by default.
<wr-waterfall-chart totalColor="var(--wr-color-on-surface-muted)" [steps]="bridge" />Number format
Numbers follow LOCALE_ID. valueFormat replaces it, and is told where each figure goes: 'label' past a bar, 'tick' on the axis, 'value' in the tooltip, the names and the data table. So the drawing can go compact and the rest stay exact. Every figure arrives as its magnitude, and the chart writes the sign. A figure too wide for its column is left out, never cut.
<wr-waterfall-chart [steps]="bridge" [valueFormat]="format" />const usd = new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD', maximumFractionDigits: 0 });
const compactUsd = new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD', notation: 'compact' });
// Compact past the bars ('label'), whole on the axis and in the tooltip, names and table.
// Every figure arrives as its magnitude; the chart writes + or − in front.
format = (value: number, where: WrWaterfallValueContext): string =>
(where === 'label' ? compactUsd : usd).format(value);Quieter
showValues, showGrid and showConnectors each turn one layer off. Keep the figures or the connectors: with both off, only colour tells up from down. The names, the tooltip and the data table keep every figure.
<wr-waterfall-chart [steps]="bridge" [showValues]="false" [showGrid]="false" />Data table
dataTable renders every figure as a table only screen readers reach: a row per step, with its change and the running total. Nothing changes on screen.
<wr-waterfall-chart ariaLabel="Profit bridge" dataTable [steps]="bridge" />Accessibility
| Part | Behaviour |
|---|---|
| Chart | A role="group", named by ariaLabel. No tab stop. |
| Steps | One role="img" each, named with the change and the running total. |
| Up, down, total | Told apart by direction, by a + or − sign and by a heavier total label, not only colour. Turning off both showValues and showConnectors leaves only colour. |
| Zero change | A neutral hairline, printed 0. Not an increase. |
| Tooltip | Pointer only. Escape closes it. |
| Forced colours | Bars keep their colours. Lines take system colours. |
API
| Name | Description | Type | Default |
|---|---|---|---|
steps | The steps, in order. A step without total is a change to the running total; a step with it is a bar from zero showing the running total. See {@link WrWaterfallStep} for what a total's value does. | readonly WrWaterfallStep[] | [] |
ariaLabel | Accessible name of the chart, and the data table's caption. Each step names itself, so say what the chart shows. Falls back to waterfallChart.label ("Waterfall chart"). | string | null | null |
increaseColor | The colour of a change up. Any CSS colour, var(--wr-…) included. | string | 'var(--wr-color-success)' |
decreaseColor | The colour of a change down. Any CSS colour. | string | 'var(--wr-color-danger)' |
totalColor | The colour of a total. Any CSS colour. | string | 'var(--wr-color-primary)' |
height | The plot's height in px, at least 80. | number | 240 |
showGrid | Show the gridlines and the value axis' tick labels. | boolean | true |
showValues | Print each step's figure past the end of its bar: a change with its sign, over the bar when it runs up and under it when it runs down, and a total with no +. Compact from a thousand up (+1.2K) by default; with valueFormat, whatever it writes for 'label', so a formatter can go compact here and stay exact everywhere else. A figure is printed whole or not at all: one wider than its column and a quarter of the gap on either side — which keeps it clear of its neighbours' — is left out rather than cut, since +$1,… is not a figure and −$9… reads as −$9. The tooltip, the names and the data table carry every figure in full. The sign is one of the two cues besides colour that tell a change up from a change down; the connectors are the other. Off together with showConnectors, colour is the only one left on screen. | boolean | true |
showConnectors | Draw the thin line that carries each running total across the gap to the next bar, which starts from it. None leads into a total that starts a running total of its own — one before every change, at a value the line would not meet. A change up leaves the line at its bottom and a change down at its top, so the line is one of the two cues besides colour that tell them apart; the signed figures are the other. Off together with showValues, colour is the only one left on screen. | boolean | true |
tooltip | Show a tooltip with the step's change and the running total after it on hover. Pointer only — each step's accessible name already carries both. | boolean | true |
dataTable | Render the chart's figures as a table only assistive technology reaches, beside the drawing: a row per step, headed by its label, with its change (empty on a total) and the running total after it, each written as the tooltip writes it. Each step's accessible name already carries both figures; the table is for a reader who wants to move through them cell by cell, with the column headings read out. It is clipped to nothing: it takes no room, draws nothing and holds no tab stop. | boolean | false |
valueFormat | Writes every number the chart shows: the figures on the drawing, the axis ticks, the tooltip, the accessible names and the data table. Every figure is handed over as its MAGNITUDE, never below zero, and the chart writes the sign in front: + or − (U+2212 MINUS SIGN) on a change, − on a running total, a total or a tick below zero. So one formatter writes every figure, and one minus sign appears throughout. It is told where the figure goes (see {@link WrWaterfallValueContext}): 'label' past a bar, where a compact form fits a narrow column; 'tick' on the value axis; 'value' in the tooltip, the names and the data table, which a reader goes to for the exact figure. A (value) => string written for another chart fits too, and writes all three alike. null uses Intl.NumberFormat in LOCALE_ID: compact past the bars from a thousand up, compact ticks (1.2K, 3.4M) unless the full numbers are shorter, and the exact figure everywhere else. | ((value: number, context: WrWaterfallValueContext) => string) | null | null |
Types
interface WrWaterfallStep {
label: string;
value: number;
total?: boolean;
}
type WrWaterfallValueContext = 'label' | 'tick' | 'value';| Name | Description | Type | Default |
|---|---|---|---|
WrWaterfallStep | One step: a change, or a total. | interface | — |
labelrequired | The step name: under the bar, tooltip, data table. | string | — |
valuerequired | The change. Zero, or not a number, is a neutral hairline. On a total, the expected total: checked, not drawn. A total before every change opens the chart at it. | number | — |
total | Draw a bar from zero to the running total. | boolean | false |
WrWaterfallValueContext | Where valueFormat is writing: 'label' past a bar, 'tick' on the axis, 'value' in the tooltip, the names and the data table. | 'label' | 'tick' | 'value' | — |
CSS variables
Set these on the component's selector or a wrapper, not on :root: the defaults are declared on ngwr/charts/waterfall-chart's own element.
| Variable | Default | Declared on |
|---|---|---|
--wr-waterfall-chart-active-bg | color-mix(in srgb, var(--wr-color-on-surface) 6%, transparent) | .wr-waterfall-chart |
--wr-waterfall-chart-bar-radius | calc(var(--wr-border-radius-sm) / 3) | .wr-waterfall-chart |
--wr-waterfall-chart-baseline-color | var(--wr-border-base) | .wr-waterfall-chart +1 variant override |
--wr-waterfall-chart-color | var(--wr-color-on-surface) | .wr-waterfall-chart |
--wr-waterfall-chart-connector-color | var(--wr-color-on-surface-muted) | .wr-waterfall-chart +1 variant override |
--wr-waterfall-chart-connector-width | 1px | .wr-waterfall-chart |
--wr-waterfall-chart-flat-color | var(--wr-color-on-surface-muted) | .wr-waterfall-chart +1 variant override |
--wr-waterfall-chart-font-family | var(--wr-font-family-base) | .wr-waterfall-chart |
--wr-waterfall-chart-gap | var(--wr-space-sm) | .wr-waterfall-chart |
--wr-waterfall-chart-grid-color | color-mix(in srgb, var(--wr-border-base) 70%, transparent) | .wr-waterfall-chart +1 variant override |
--wr-waterfall-chart-label-color | var(--wr-color-on-surface-muted) | .wr-waterfall-chart |
--wr-waterfall-chart-label-font-size | var(--wr-text-xs) | .wr-waterfall-chart |
--wr-waterfall-chart-labels-margin-top | var(--wr-space-sm) | .wr-waterfall-chart |
--wr-waterfall-chart-plot-inset-y | var(--wr-space-sm) | .wr-waterfall-chart |
--wr-waterfall-chart-tick-color | var(--wr-color-on-surface-muted) | .wr-waterfall-chart |
--wr-waterfall-chart-tick-font-size | var(--wr-text-xs) | .wr-waterfall-chart |
--wr-waterfall-chart-tick-gap | var(--wr-space-xs) | .wr-waterfall-chart |
--wr-waterfall-chart-tick-line-height | var(--wr-text-xs-leading) | .wr-waterfall-chart |
--wr-waterfall-chart-total-font-weight | var(--wr-font-weight-medium) | .wr-waterfall-chart |
--wr-waterfall-chart-value-color | var(--wr-color-on-surface) | .wr-waterfall-chart |
--wr-waterfall-chart-value-font-size | var(--wr-text-xs) | .wr-waterfall-chart |
--wr-waterfall-chart-value-gap | var(--wr-space-xs) | .wr-waterfall-chart |
--wr-waterfall-chart-value-line-height | var(--wr-text-xs-leading) | .wr-waterfall-chart |
Dependencies
| Built on | Popover |
|---|
See also
Component Bar ChartBars for one or several series, grouped or stacked, standing up or lying along a row, with lines over them.Component Funnel ChartHow many reached each stage of a sequence, and how many of them went on to the next.Component Line ChartOne or more series of values as lines or as an area chart, overlaid or stacked.Component PopoverShow a template, or a text tooltip, next to its trigger.