Histogram
Show how a set of values is distributed. Values are binned into equal-width bars by Sturges' rule, or into a bin count you choose. Hover a bar for its count.
| Range | Count |
|---|---|
| 60 ms to 100 ms | 68 |
| 100 ms to 139 ms | 27 |
| 139 ms to 179 ms | 13 |
| 179 ms to 218 ms | 13 |
| 218 ms to 258 ms | 11 |
| 258 ms to 297 ms | 10 |
| 297 ms to 337 ms | 5 |
| 337 ms to 376 ms | 7 |
| 376 ms to 416 ms | 6 |
| Range | Count |
|---|---|
| 60 to 96 | 61 |
| 96 to 131 | 32 |
| 131 to 167 | 10 |
| 167 to 202 | 12 |
| 202 to 238 | 12 |
| 238 to 273 | 9 |
| 273 to 309 | 8 |
| 309 to 345 | 5 |
| 345 to 380 | 6 |
| 380 to 416 | 5 |
Usage
use hydroxy_leptos::histogram::{Annotation, Histogram};
use leptos::prelude::*;
pub fn demo() -> AnyView {
// A right-skewed spread of response times: most are quick, a few are slow.
let times: Vec<f64> = (0..160)
.map(|i| {
let t = (f64::from(i) * 0.618_034).fract();
60.0 + 340.0 * t * t * t + f64::from(i % 7) * 4.0
})
.collect();
view! {
<div style="display: grid; gap: var(--space-10);">
// Sturges' rule picks the bin count. The target is on the value axis.
// Hover a bar, or focus the plot and use the arrow keys, to read each bin.
<Histogram
values=times.clone()
label="Response time"
format=|v: f64| format!("{v:.0} ms")
annotations=vec![Annotation::x_line(250.0, "Target")]
/>
// Or set it yourself.
<Histogram values=times label="Response time, 10 bins" bins=10 height=160 format=|v: f64| format!("{v:.0}") />
</div>
}
.into_any()
}use dioxus::prelude::*;
use hydroxy_dioxus::histogram::{Annotation, Histogram};
#[component]
pub fn HistogramDemo() -> Element {
// A right-skewed spread of response times: most are quick, a few are slow.
let times: Vec<f64> = (0..160)
.map(|i| {
let t = (f64::from(i) * 0.618_034).fract();
60.0 + 340.0 * t * t * t + f64::from(i % 7) * 4.0
})
.collect();
rsx! {
div { style: "display: grid; gap: var(--space-10);",
Histogram {
values: times.clone(),
label: "Response time",
format: move |v: f64| format!("{v:.0} ms"),
annotations: vec![Annotation::x_line(250.0, "Target")],
}
Histogram { values: times, label: "Response time, 10 bins", bins: 10, height: 160, format: move |v: f64| format!("{v:.0}") }
}
}
}
Anatomy
| Component | data-part | Renders |
|---|---|---|
Histogram | root | figure with a screen-reader table of every bin |
| gridline | Recessive count gridlines at nice ticks |
| columns | Focusable plot; arrow keys move between bins |
| column | One per bin |
| tooltip | Range and count of the active bin |
| annotation | Reference line, band or labelled point; x on the value axis, y a count |
| bar | Bar in the first chart colour, growing from the baseline |
| label | Bin edges along the bottom, thinned to fit |
Keyboard
| Key | Does |
|---|---|
ArrowLeft / ArrowRight | Move to the previous or next bin |
Home / End | Jump to the first or last bin |
Escape | Hide the tooltip |
Props
| Prop | Type | Notes |
|---|---|---|
values | Vec<f64> | Required. Raw observations; non-finite values are ignored |
label | String | Required. What the chart shows; the accessible name |
bins | usize | Number of bins. Default: Sturges' rule, ceil(log2 n) + 1 |
height | u16 | Plot height in px. Default 200 |
format | Fn(f64) -> String | Formats the bin edges |
annotations | Vec<Annotation> | Reference lines, bands and labelled points; x is a value, y a count |
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 |