M
MetricUI
Charts

Waterfall

Waterfall chart showing sequential positive and negative changes from a starting value.

import { Waterfall } from "metricui";

Use Waterfall for sequential change analysis — showing how an initial value is affected by a series of positive and negative changes. Perfect for P&L breakdowns, MRR bridges, and budget analysis. Supports subtotals, totals, connector lines, per-bar color overrides, and custom positive/negative/total colors. For categorical comparison, use BarChart instead.

Basic Example

Pass an array of items with label, value, and type. Use type: "total" for the final computed sum.

MRR Bridge
<Waterfall
  data={[
    { label: "Starting MRR", value: 85000, type: "value" },
    { label: "New Sales", value: 28400, type: "value" },
    { label: "Expansion", value: 12600, type: "value" },
    { label: "Churn", value: -8200, type: "value" },
    { label: "Contraction", value: -3100, type: "value" },
    { label: "Ending MRR", value: 0, type: "total" },
  ]}
  title="MRR Bridge"
  format="currency"
  connectors
  height={320}
/>

With Subtotals

Use type: "subtotal" to insert intermediate running-total markers. Great for P&L statements where you need gross income before expenses.

P&L Breakdown
<Waterfall
  data={[
    { label: "Revenue", value: 120000, type: "value" },
    { label: "Services", value: 34000, type: "value" },
    { label: "Gross Income", value: 0, type: "subtotal" },
    { label: "Salaries", value: -62000, type: "value" },
    { label: "Marketing", value: -18000, type: "value" },
    { label: "Rent", value: -9500, type: "value" },
    { label: "Operating Income", value: 0, type: "subtotal" },
    { label: "Tax", value: -13000, type: "value" },
    { label: "Net Income", value: 0, type: "total" },
  ]}
  title="P&L Breakdown"
  format="currency"
  connectors
  height={360}
/>

Custom Colors

Override colors per-bar with the color property on individual data items, or set positiveColor, negativeColor, and totalColor globally.

Q1 Revenue Bridge
<Waterfall
  data={[
    { label: "Q1 Target", value: 50000 },
    { label: "Outperformance", value: 8200, color: "#6366f1" },
    { label: "Seasonality", value: -3400 },
    { label: "New Market", value: 12800, color: "#6366f1" },
    { label: "Refunds", value: -2100 },
    { label: "Q1 Actual", value: 0, type: "total" },
  ]}
  title="Q1 Revenue Bridge"
  format="currency"
  positiveColor="#10b981"
  negativeColor="#f43f5e"
  totalColor="#8b5cf6"
  height={320}
/>

Without Connectors

Set connectors={false} to hide the dashed connector lines between bars for a cleaner look.

Budget Allocation
<Waterfall
  data={[
    { label: "Budget", value: 200000 },
    { label: "Personnel", value: -82000 },
    { label: "Equipment", value: -34000 },
    { label: "Software", value: -21000 },
    { label: "Travel", value: -8500 },
    { label: "Remaining", value: 0, type: "total" },
  ]}
  title="Budget Allocation"
  format="currency"
  connectors={false}
  height={320}
/>

Quarterly Changes

Show how periodic changes contribute to a final total. Each bar represents the delta for that period, and the total bar shows the cumulative result.

Quarterly Revenue
<Waterfall
  data={[
    { label: "Q1", value: 120000 },
    { label: "Q2", value: 45000 },
    { label: "Q3", value: -30000 },
    { label: "Q4", value: 65000 },
    { label: "FY Total", type: "total" },
  ]}
  title="Quarterly Revenue"
  format="currency"
  connectors
  height={320}
/>

Data States

Every component handles loading, empty, and error states. Pass individual props or use the grouped state prop.

Loading

Error

Failed to load data

// Loading state
<Waterfall data={[]} title="Revenue Bridge" loading />

// Error state
<Waterfall data={[]} title="Revenue Bridge" error={{ message: "Failed to load" }} />

Props

PropTypeDescription
data*
WaterfallItem[]

Array of waterfall items with label, value, optional type and color.

title
string

Chart card title.

subtitle
string

Chart card subtitle.

description
string | React.ReactNode

Description popover.

footnote
string

Footnote.

action
React.ReactNode

Action slot.

format
FormatOption

Format for axis labels, bar value labels, and tooltips.

height
number

Chart height in px.

positiveColor
string

Color for positive (increase) bars. Default: theme positive color.

negativeColor
string

Color for negative (decrease) bars. Default: theme negative color.

totalColor
string

Color for subtotal/total bars. Default: theme accent.

connectors
boolean

Show dashed connector lines between bars.

enableLabels
boolean

Show value labels on bars.

borderRadius
number

Corner radius on bars.

padding
number

Padding between bars (0-1).

enableGridY
boolean

Show Y-axis grid lines.

yAxisLabel
string

Y-axis label.

animate
boolean

Enable/disable animation.

variant
CardVariant

Card variant.

dense
boolean

Compact layout.

className
string

Additional CSS class names.

classNames
{ root?: string; header?: string; chart?: string }

Sub-element class name overrides.

id
string

HTML id attribute.

data-testid
string

Test id.

loading
boolean

Loading state.

empty
EmptyState

Empty state.

error
ErrorState

Error state.

stale
StaleState

Stale indicator.

drillDown
boolean | ((event: { label: string; value: number; runningTotal: number }) => React.ReactNode)

Enable drill-down on bar click. `true` auto-generates a summary KPI row + filtered DataTable from the chart's source data. Pass a render function for full control over the panel content. Requires DrillDown.Root wrapper.

drillDownMode
DrillDownMode

Presentation mode for the drill-down panel. "slide-over" (default) slides from the right, full height. "modal" renders centered and compact.

Data Shape

interface WaterfallItem {
  label: string;          // Display label
  value?: number;         // Positive for increase, negative for decrease. Ignored for subtotal/total.
  type?: "value" | "subtotal" | "total";  // Default: "value". subtotal/total are auto-computed.
  color?: string;         // Custom color override for this bar
}

Notes

  • Uses forwardRef.
  • Uses a stacked spacer technique — transparent spacer bars create the floating effect.
  • Positive values show in green, negative in red, subtotal/total bars use the accent color.
  • Connector lines (dashed) link adjacent bar tops. Disabled for total bars that start from zero.
  • Items with type 'subtotal' show the running total without resetting. Items with type 'total' show and reset.
  • Tooltips show item value plus running total for non-total items.
  • Custom colors per bar override the default positive/negative/total coloring.
  • drillDown={true} auto-generates a summary KPI row + filtered DataTable from the chart's source data. Pass a render function for custom panel content. Requires DrillDown.Root wrapper.