Waterfall
A cumulative bridge: each yField value is a change, and bars grow from the running total. totals marks the indices of total rows (a bar from zero to the running total).
ts
import { getData } from './data';
import type { ChartOptions } from 'grafit-charts';
export function createOptions(): ChartOptions {
return {
data: getData(),
title: { text: 'P&L bridge' },
subtitle: { text: '₽M' },
series: [
{
type: 'waterfall',
xField: 'step',
yField: 'value',
name: 'Change',
// indices 3 and 6 are the subtotal and the final total
totals: [3, 6],
},
],
legend: { enabled: false },
};
}ts
export function getData() {
return [
{ step: 'Revenue', value: 420 },
{ step: 'COGS', value: -180 },
{ step: 'Marketing', value: -65 },
{ step: 'Gross', value: 0 },
{ step: 'Other income', value: 38 },
{ step: 'Taxes', value: -52 },
{ step: 'Net', value: 0 },
];
}Subtotals and styles
totals — indices of total rows (a bar from zero), colors by sign via item; labels — label.formatter({ value, isTotal, datum }) (placements are the same as for bar):
ts
import { getData } from './data';
import type { ChartOptions } from 'grafit-charts';
export function createOptions(): ChartOptions {
return {
data: getData(),
title: { text: 'P&L with subtotals' },
series: [
{
type: 'waterfall',
xField: 'step',
yField: 'value',
totals: [2, 6],
cornerRadius: 4,
item: {
positive: { fill: '#21a06c' },
negative: { fill: '#e5484d' },
total: { fill: '#33404f' },
},
line: { enabled: true },
label: {
enabled: true,
formatter: ({ value, isTotal }) => (isTotal ? String(value) : `${value > 0 ? '+' : ''}${value}`),
},
},
],
legend: { enabled: false },
};
}ts
export function getData() {
return [
{ step: 'Revenue', value: 420 },
{ step: 'COGS', value: -180 },
{ step: 'Gross profit', value: 0 },
{ step: 'Marketing', value: -60 },
{ step: 'R&D', value: -75 },
{ step: 'Other', value: 18 },
{ step: 'Operating profit', value: 0 },
];
}| Option | Type | Default | Description |
|---|---|---|---|
xField | string | — | category and change |
yField | string | — | category and change |
totals | number[] | — | indices of total rows |
cornerRadius | Pixels | 2 | bar corner rounding |
label.enabled | boolean | false | show value labels |
label.placement | outer/center/inner-* (17 placements) | 'top' | label placement |
label.formatter | ({ value, isTotal, datum }) => string | value | label content |
label.fontSize | Pixels | 11 | label font size |
label.fontWeight | string | number | normal | font weight |
label.fontFamily | string | theme font | font family |
label.color | ColorValue | foreground; inside — auto contrast | text color |
item.positive.fill | ColorValue | series color | fill of positive steps |
item.negative.fill | ColorValue | theme red | fill of negative steps |
item.total.fill | ColorValue | theme muted | fill of total bars |
line.enabled | boolean | true | connector lines |
line.stroke | ColorValue | theme muted | connector line color |
Options
Options common to all series (name, showInLegend, tooltip.renderer, …) are covered in Common series options.