Funnel chart
Stages that narrow to the next, with the conversion from each stage to the one after. Runs top to bottom or left to right.
Signup funnel
Last 30 days, with conversion between stages.
| Stage | Value | From previous | From first |
|---|---|---|---|
| Visited pricing | 18400 | 100% | |
| Started trial | 4120 | 22.4% | 22.4% |
| Invited a teammate | 1870 | 45.4% | 10.2% |
| Connected data | 1240 | 66.3% | 6.7% |
| Paid | 610 | 49.2% | 3.3% |
Hiring
Engineering roles this year, left to right.
| Stage | Value | From previous | From first |
|---|---|---|---|
| Applied | 640 | 100% | |
| Screened | 210 | 32.8% | 32.8% |
| Interviewed | 72 | 34.3% | 11.2% |
| Offered | 14 | 19.4% | 2.2% |
| Hired | 11 | 78.6% | 1.7% |
Usage
use hydroxy_leptos::chart_frame::ChartFrame;
use hydroxy_leptos::funnel_chart::*;
use leptos::prelude::*;
pub fn demo() -> AnyView {
let signup = vec![
Datum::new("Visited pricing", 18_400.0),
Datum::new("Started trial", 4_120.0),
Datum::new("Invited a teammate", 1_870.0),
Datum::new("Connected data", 1_240.0),
Datum::new("Paid", 610.0),
];
let hiring = vec![
Datum::new("Applied", 640.0),
Datum::new("Screened", 210.0),
Datum::new("Interviewed", 72.0),
Datum::new("Offered", 14.0),
Datum::new("Hired", 11.0),
];
view! {
<div style="display: grid; gap: var(--space-10);">
<ChartFrame title="Signup funnel" description="Last 30 days, with conversion between stages.">
<FunnelChart data=signup label="Signup funnel" />
</ChartFrame>
<ChartFrame title="Hiring" description="Engineering roles this year, left to right.">
<FunnelChart data=hiring label="Hiring funnel" orientation=Orientation::Horizontal height=200 />
</ChartFrame>
</div>
}
.into_any()
}use dioxus::prelude::*;
use hydroxy_dioxus::chart_frame::ChartFrame;
use hydroxy_dioxus::funnel_chart::{Datum, FunnelChart, Orientation};
#[component]
pub fn FunnelChartDemo() -> Element {
let signup = vec![
Datum::new("Visited pricing", 18_400.0),
Datum::new("Started trial", 4_120.0),
Datum::new("Invited a teammate", 1_870.0),
Datum::new("Connected data", 1_240.0),
Datum::new("Paid", 610.0),
];
let hiring = vec![
Datum::new("Applied", 640.0),
Datum::new("Screened", 210.0),
Datum::new("Interviewed", 72.0),
Datum::new("Offered", 14.0),
Datum::new("Hired", 11.0),
];
rsx! {
div { style: "display: grid; gap: var(--space-10);",
ChartFrame { title: "Signup funnel", description: "Last 30 days, with conversion between stages.",
FunnelChart { data: signup, label: "Signup funnel" }
}
ChartFrame { title: "Hiring", description: "Engineering roles this year, left to right.",
FunnelChart { data: hiring, label: "Hiring funnel", orientation: Orientation::Horizontal, height: 200 }
}
}
}
}
Anatomy
| Component | data-part | Renders |
|---|---|---|
FunnelChart | root | figure with a screen-reader table of every stage |
| plot | Focusable funnel; arrow keys step through stages |
| stage-label | Stage name and value in the gutter |
| stage | Trapezoid from the stage's value down to the next one's |
| conversion | Share of the previous stage, on the seam between them |
| tooltip | Value, share of the previous stage and of the first |
Keyboard
| Key | Does |
|---|---|
ArrowDown / ArrowRight | Next stage |
ArrowUp / ArrowLeft | Previous stage |
Home / End | First or last stage |
Escape | Clear the active stage |
Props
| Prop | Type | Notes |
|---|---|---|
data | Vec<Datum> | Required. Stages in order |
label | String | Required. What the chart shows; the accessible name |
orientation | Orientation | Vertical (default) or Horizontal |
height | u16 | Plot height in px. Default 280 |
format | Fn(f64) -> String | Formats values in labels, tooltip and table |
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 |