Components
Waterfall chart
A bridge/waterfall chart: a dumb painter over pre-computed data. Totals anchor in navy, movements read as signed increases and decreases against them. Colour, ordering and labels are the renderer's decisions; the caller supplies only the resolved bars and the y-domain.
Install
npx shadcn@latest add @alix/waterfallPreview
Usage
import { WaterfallChart, type WaterfallDatum } from "@/components/ui/waterfall";
// Each bar is pre-computed: base is the invisible riser, value the visible height.
const data: WaterfallDatum[] = [
{ name: "FY24", base: 0, value: 46, label: "46", kind: "total" },
{ name: "Volume", base: 46, value: 9, label: "+9", kind: "increase" },
{ name: "Price", base: 51, value: 4, label: "−4", kind: "decrease" },
// …
{ name: "FY25", base: 0, value: 53, label: "53", kind: "total" },
];
<WaterfallChart data={data} domain={[0, 68]} />Examples
01
Inside a panel
Panel owns the dashboard frame; the chart fills a fixed-height body. The same bridge, at dashboard scale rather than slide scale.
EBITDA bridge
FY24 to FY25, £m
<Panel title="EBITDA bridge" description="FY24 to FY25, £m" flush>
<div className="h-64 w-full p-4">
<WaterfallChart data={data} domain={domain} />
</div>
</Panel>02
A cost bridge
The kinds (total, increase, decrease) are the only palette lever, so a cost-down bridge and a revenue bridge read the same way.
const data: WaterfallDatum[] = [
{ name: "Baseline", base: 0, value: 120, label: "120", kind: "total" },
{ name: "Procurement", base: 112, value: 8, label: "−8", kind: "decrease" },
{ name: "Inflation", base: 103, value: 6, label: "+6", kind: "increase" },
{ name: "Run-rate", base: 0, value: 109, label: "109", kind: "total" },
];When to use it
Use it for
- A quantified bridge where the bars are already computed (a running level between signed movements).
- Inside WaterfallSlide (the deck) or a Panel body (a dashboard). Supply a height on the wrapper.
- A y-domain with a little headroom above the tallest bar so the value labels clear the frame.
Reach for something else
- Computing the bridge in the chart: it's a painter; build base/value/kind upstream.
- Per-bar colour requests: the palette is fixed by kind (totals navy, movements the ramp).
- A continuous trend or a category comparison. Use Chart, and StatsSlide for headline figures.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| data | WaterfallDatum[] | – | Pre-computed bars: name, base (the invisible riser), value (the visible height), a signed display label, and kind (total | increase | decrease) which selects the fill. |
| domain | [number, number] | – | The y-axis domain, computed upstream from the bars, typically [min(0, base), peak × 1.12] so labels clear the top. |