Skip to content

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 },
  ];
}
OptionTypeDefaultDescription
xFieldstringcategory and change
yFieldstringcategory and change
totalsnumber[]indices of total rows
cornerRadiusPixels2bar corner rounding
label.enabledbooleanfalseshow value labels
label.placementouter/center/inner-* (17 placements)'top'label placement
label.formatter({ value, isTotal, datum }) => stringvaluelabel content
label.fontSizePixels11label font size
label.fontWeightstring | numbernormalfont weight
label.fontFamilystringtheme fontfont family
label.colorColorValueforeground; inside — auto contrasttext color
item.positive.fillColorValueseries colorfill of positive steps
item.negative.fillColorValuetheme redfill of negative steps
item.total.fillColorValuetheme mutedfill of total bars
line.enabledbooleantrueconnector lines
line.strokeColorValuetheme mutedconnector line color

Options

Options common to all series (name, showInLegend, tooltip.renderer, …) are covered in Common series options.