Donut chart
Parts of a whole. Up to six parts in the chart colour order; more fold into a grey "Other". Hover, touch or focus a segment or legend row to pick it out and read its value and share.
Tickets
By channel, this quarter.
| Part | Value | Share |
|---|---|---|
| 182 | 44% | |
| Chat | 124 | 30% |
| Phone | 61 | 15% |
| Forms | 43 | 10% |
Sources
More than six fold into a grey Other.
| Part | Value | Share |
|---|---|---|
| Interviews | 12 | 29% |
| Support tickets | 9 | 22% |
| Surveys | 7 | 17% |
| Sales notes | 5 | 12% |
| NPS | 4 | 10% |
| Other | 4 | 10% |
Usage
use hydroxy_leptos::chart_frame::ChartFrame;
use hydroxy_leptos::donut_chart::*;
use leptos::prelude::*;
#[component]
pub fn Demo() -> impl IntoView {
let channels = vec![
Datum::new("Email", 182.0),
Datum::new("Chat", 124.0),
Datum::new("Phone", 61.0),
Datum::new("Forms", 43.0),
];
// Eight sources: the smallest fold into "Other", which stays grey.
let sources = vec![
Datum::new("Interviews", 12.0),
Datum::new("Support tickets", 9.0),
Datum::new("Surveys", 7.0),
Datum::new("Sales notes", 5.0),
Datum::new("NPS", 4.0),
Datum::new("App reviews", 2.0),
Datum::new("Forums", 1.0),
Datum::new("Social", 1.0),
];
view! {
<div style="display: grid; gap: var(--space-10);">
<ChartFrame title="Tickets" description="By channel, this quarter.">
<DonutChart data=channels label="Tickets by channel" center_label="Tickets" />
</ChartFrame>
<ChartFrame title="Sources" description="More than six fold into a grey Other.">
<DonutChart data=sources label="Sources by type" center_label="Sources" size=150 thickness=18 />
</ChartFrame>
</div>
}
}use dioxus::prelude::*;
use hydroxy_dioxus::chart_frame::ChartFrame;
use hydroxy_dioxus::donut_chart::{Datum, DonutChart};
#[component]
pub fn DonutChartDemo() -> Element {
let channels = vec![
Datum::new("Email", 182.0),
Datum::new("Chat", 124.0),
Datum::new("Phone", 61.0),
Datum::new("Forms", 43.0),
];
let sources = vec![
Datum::new("Interviews", 12.0),
Datum::new("Support tickets", 9.0),
Datum::new("Surveys", 7.0),
Datum::new("Sales notes", 5.0),
Datum::new("NPS", 4.0),
Datum::new("App reviews", 2.0),
Datum::new("Forums", 1.0),
Datum::new("Social", 1.0),
];
rsx! {
div { style: "display: grid; gap: var(--space-10);",
ChartFrame { title: "Tickets", description: "By channel, this quarter.",
DonutChart { data: channels, label: "Tickets by channel", center_label: "Tickets" }
}
ChartFrame { title: "Sources", description: "More than six fold into a grey Other.",
DonutChart { data: sources, label: "Sources by type", center_label: "Sources", size: 150, thickness: 18 }
}
}
}
}
Anatomy
| Component | data-part | Renders |
|---|---|---|
DonutChart | root | figure labelled by `label`; `data-active` while a segment is picked |
| ring | Focusable group holding the segments, centre and tooltip |
| segment | Ring slice with a 2px gap to its neighbours; `data-active` when picked |
| center | Total, or `center_value`, with an optional caption |
| tooltip | Name, value and share of the picked segment, at its arc |
| legend | Swatch, label, value and share for every part |
| sr-live | Announces the picked segment |
| sr-table | Every part with its value and share, for screen readers and CSV export |
Keyboard
| Key | Does |
|---|---|
ArrowRight / ArrowLeft | Step to the next or previous segment |
Home / End | Jump to the first or last segment |
Escape | Clear the picked segment |
Props
| Prop | Type | Notes |
|---|---|---|
data | Vec<Datum> | Required. Parts in display order |
label | String | Required. What the chart shows; the accessible name |
size | u16 | Ring diameter in px. Default 180 |
thickness | u16 | Ring width in px. Default 22 |
center_label | String | Caption under the centre figure |
center_value | String | Centre figure. Default: the total |
format | Fn(f64) -> String | Formats the centre and legend values |
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 |