Waterfall chart
Show how a starting value becomes an end value. Each change floats from the running total, rises and falls in their own colours, with optional total bars.
Revenue bridge
From last year's revenue to this year's, in thousands.
| Change | Running total | |
|---|---|---|
| FY24 revenue | – | £4200k |
| New customers | +£1150k | £5350k |
| Expansion | +£640k | £5990k |
| Price rise | +£310k | £6300k |
| Churn | £-820k | £5480k |
| Discounts | £-270k | £5210k |
| FY25 revenue | – | £5210k |
Net cash flow
Monthly changes with quarter and half-year totals.
| Change | Running total | |
|---|---|---|
| Jan | +120 | 120 |
| Feb | -45 | 75 |
| Mar | +80 | 155 |
| Q1 | – | 155 |
| Apr | -160 | -5 |
| May | +35 | 30 |
| Jun | +90 | 120 |
| H1 | – | 120 |
Usage
use hydroxy_leptos::chart_frame::ChartFrame;
use hydroxy_leptos::waterfall_chart::*;
use leptos::prelude::*;
pub fn demo() -> AnyView {
// An opening balance, the changes, then the closing total.
let bridge = vec![
Step::start("FY24 revenue", 4_200.0),
Step::change("New customers", 1_150.0),
Step::change("Expansion", 640.0),
Step::change("Price rise", 310.0),
Step::change("Churn", -820.0),
Step::change("Discounts", -270.0),
Step::total("FY25 revenue"),
];
let cash = vec![
Step::change("Jan", 120.0),
Step::change("Feb", -45.0),
Step::change("Mar", 80.0),
Step::total("Q1"),
Step::change("Apr", -160.0),
Step::change("May", 35.0),
Step::change("Jun", 90.0),
Step::total("H1"),
];
view! {
<div style="display: grid; gap: var(--space-10);">
<ChartFrame title="Revenue bridge" description="From last year's revenue to this year's, in thousands.">
<WaterfallChart steps=bridge label="Revenue bridge from FY24 to FY25" format=|v: f64| format!("£{v:.0}k") />
</ChartFrame>
<ChartFrame title="Net cash flow" description="Monthly changes with quarter and half-year totals.">
<WaterfallChart
steps=cash
label="Net cash flow by month"
height=200
annotations=vec![Annotation::y_line(100.0, "Reserve floor")]
/>
</ChartFrame>
</div>
}
.into_any()
}use dioxus::prelude::*;
use hydroxy_dioxus::chart_frame::ChartFrame;
use hydroxy_dioxus::waterfall_chart::{Annotation, Step, WaterfallChart};
#[component]
pub fn WaterfallChartDemo() -> Element {
let bridge = vec![
Step::start("FY24 revenue", 4_200.0),
Step::change("New customers", 1_150.0),
Step::change("Expansion", 640.0),
Step::change("Price rise", 310.0),
Step::change("Churn", -820.0),
Step::change("Discounts", -270.0),
Step::total("FY25 revenue"),
];
let cash = vec![
Step::change("Jan", 120.0),
Step::change("Feb", -45.0),
Step::change("Mar", 80.0),
Step::total("Q1"),
Step::change("Apr", -160.0),
Step::change("May", 35.0),
Step::change("Jun", 90.0),
Step::total("H1"),
];
rsx! {
div { style: "display: grid; gap: var(--space-10);",
ChartFrame { title: "Revenue bridge", description: "From last year's revenue to this year's, in thousands.",
WaterfallChart { steps: bridge, label: "Revenue bridge from FY24 to FY25", format: move |v: f64| format!("£{v:.0}k") }
}
ChartFrame { title: "Net cash flow", description: "Monthly changes with quarter and half-year totals.",
WaterfallChart {
steps: cash,
label: "Net cash flow by month",
height: 200,
annotations: vec![Annotation::y_line(100.0, "Reserve floor")],
}
}
}
}
}
Anatomy
| Component | data-part | Renders |
|---|---|---|
WaterfallChart | root | figure with a screen-reader table of every change and running total |
| bar | One per step; data-kind is increase, decrease or total |
| connector | Dashed line carrying the running total to the next bar |
| overlay | Focusable plot that drives the tooltip |
| tooltip | The step's change and the running total after it |
| annotation | Reference lines, bands and points |
| legend | Increase, decrease and (when used) total colours |
Keyboard
| Key | Does |
|---|---|
ArrowLeft / ArrowRight | Previous or next step |
Home / End | First or last step |
Escape | Hide the tooltip |
Props
| Prop | Type | Notes |
|---|---|---|
steps | Vec<Step> | Required. Step::change(label, value), Step::total(label), or Step::start(label, value) to set the running total |
label | String | Required. What the chart shows; the accessible name |
height | u16 | Plot height in px. Default 240 |
format | Fn(f64) -> String | Formats ticks, tooltip and table |
annotations | Vec<Annotation> | Reference lines, bands and points; x is a step index |
Events
| Prop | Type | Notes |
|---|---|---|
on_hover | Callback<Option<Datum>> | The mark under the pointer or keyboard focus changes, or is left. Fires only on a change |
on_select | Callback<Datum> | Click, tap or Enter on a mark |