Histogram & Density
ProDistribution of a sample: five bin-width rules, count / density / cumulative measures, an optional kernel density curve, a rug, and mean / median / quantile markers. The rule that shaped the picture is always stated. Pure SVG.
import { SvHistogramChartComponent } from '@styloviz-pro/charts';Demo & usage
Basic usage
ProUsage example — open the gallery for the full interactive demo.
An interactive demo for this component lives in the gallery.
Open live demoMore examples
Pin the bin count
ProDensity curve and rug
ProCumulative distribution
ProWeighted samples
ProMean, median and P90 markers
ProWhen to use
- Seeing the SHAPE of one numeric variable — where the mass sits, whether it is skewed, whether it has two modes.
- Answering "what share came in under X" with the cumulative measure.
- For comparing distributions across several groups, a Box Plot puts them side by side; for individual points, a Scatter Plot.
Async states
- loading
- empty
- error
- retry
Inputs
| Name | Type | Default | Description |
|---|---|---|---|
| loading | boolean | false | True while the samples are being fetched. |
| error | SvDataError | string | null | null | Load failure. Use `toSvDataError()` from `@styloviz/core` to normalize an `HttpErrorResponse`. |
| emptyMessage | string | 'No samples to plot' | Copy for the no-data state. |
| filtered | boolean | false | True when the emptiness is caused by a filter rather than an empty set. |
| samples | readonly SvHistogramSample[] | [] | The readings to bin. Each may carry a `weight`. |
| binRule | SvBinRule | 'freedman-diaconis' | How the bin width is chosen. Freedman–Diaconis is the default because it is the most robust to outliers: it scales with the interquartile range rather than the full spread, so one extreme reading does not widen every bin. The rule is always named under the plot — a histogram's shape is a function of its bin width as much as of its data, so an unstated rule leaves the picture unfalsifiable. |
| binCount | number | 10 | Bin count, used when `binRule` is `'fixed'`. |
| binEdges | readonly number[] | [] | Explicit bin edges, bypassing `binRule`. Widths may differ. Repeated edges are merged; fewer than two distinct numbers fall back to `binRule`, and the note under the plot says so. |
| measure | SvHistogramMeasure | 'count' | What the bars encode. `count` is the plain frequency. `density` is `count ÷ bin width`, which is the only honest height when the bins differ in width. `cumulative` draws the running total, turning the chart into a distribution function. |
| showDensity | boolean | false | Overlay a Gaussian kernel density estimate. Off by default: the curve is a MODEL rather than the data, and its bandwidth smooths a real bimodal distribution into one mound as easily as it reveals one. When on, the bandwidth is named under the plot. |
| bandwidth | number | 0 | Kernel bandwidth. Falls back to Silverman's rule of thumb. |
| showRug | boolean | false | Draw a tick per sample along the baseline. |
| showMean | boolean | false | Mark the mean with a labelled reference line. Weighted when the samples carry weights, like the bars. |
| showMedian | boolean | false | Mark the median with a labelled reference line. Same type-7 quantile rule as the box plot, weighted when the samples carry weights. |
| quantiles | readonly number[] | [] | Quantiles to mark, as probabilities in `[0, 1]` — `[0.9, 0.99]` draws P90 and P99. Values outside the range and duplicates are ignored. |
| width | number | 640 | Plot width in pixels. |
| height | number | 320 | Plot height in pixels. |
| color | string | '' | Bar fill. Falls back to the shared chart palette. |
| valueLabel | string | '' | Label for the value axis, e.g. a unit. |
| title | string | '' | Chart title, rendered above the plot. |
| ariaLabel | string | '' | Accessible name override. Falls back to a generated summary. |
| customClass | string | '' | Extra CSS classes applied to the root wrapper. |
Outputs
| Event | Payload type | Description |
|---|---|---|
| retry | void | The host should re-run the failed load. |
| binHover | SvHistogramBinEvent | Emitted when a bin is hovered or keyboard-focused. |
| binSelect | SvHistogramBinEvent | Emitted when a bin is clicked or activated with Enter/Space. |
Wire it to your API
This component is headless about transport: it renders what you give it and reports what the user asks for. Nothing below requires @styloviz/data — drive it from whatever you already use.
Template
ProBound to the names this component actually exposes.
Host class
ProDrive the three async inputs from your own fetch.
- This component does not emit a query, so it renders what you give it. Fetch on your own trigger and bind `samples`, `loading` and `error`.
- Set `filtered` when a search or filter is active. It is the difference between "you have no orders" and "no orders match this filter" — telling a customer with 4,000 orders the first one reads as a bug.
- Normalize failures with `toSvDataError()` from `@styloviz/core`. It derives `retryable` from the status, so a 404 does not get a "Try again" button that can only fail again.
Full walkthrough: Connecting to a backend.
Customization & theming
- Five bin-width rules, or explicit edges of your own — an edge is widened rather than lose a sample outside it, because a count that does not add up is the one thing a histogram must never do. Repeated edges are merged; an edge list with fewer than two distinct numbers falls back to the bin rule, and the note under the plot says so rather than showing an empty chart.
- Count, density or cumulative measures.
- Optional kernel density overlay with a bandwidth override — weighted the same way as the bars when the samples carry weights — and an optional rug of individual readings.
- Statistical annotation: `showMean`, `showMedian` and `quantiles` (probabilities, e.g. `[0.9, 0.99]`) draw labelled reference lines, weighted like the bars. Off by default.
- Bar colour, plot size, and a unit label carried into the axis and the table.
Best practices
- Do: Treat the bin rule as part of the finding, not a display setting. The same samples at 8 bins and at 60 are a smooth mound and a spiky comb, and neither is wrong — which is why the rule is named under every plot and cannot be hidden. Quote it when you quote the shape.
- Do: Use the density measure whenever the bins are not all the same width. Bar AREA is what a reader takes off a histogram, so drawing counts on unequal bins makes a wider bin look fuller for the same number of samples. The chart says so when you do it; density is the fix it names.
- Don't: Do not read the density curve as data. It is a kernel density estimate — a model — and its bandwidth smooths a genuinely bimodal distribution into one mound as easily as it reveals one. It is drawn dashed for that reason, and its bandwidth is stated.
- Tip: Freedman–Diaconis is the default because it scales with the interquartile range rather than the full spread, so a single extreme reading does not widen every bin. It falls back to the square-root rule when the interquartile range is zero, which a heavily-moded sample produces — and the note under the plot then names the rule that actually ran and why, not the one you asked for.
Accessibility
- Every bar is a focusable `role="button"` named with its range, count and share. Bar height is the only place a count exists in the drawing and no axis is precise enough to read one off, so those figures are in the name rather than left to be estimated.
- The plot is ONE tab stop: Tab lands on a bar, the arrow keys walk the others (Home / End jump to the ends, no wrap), Enter or Space selects. A tab stop per bar was up to 200 Tab presses to get past one chart.
- Mean, median and quantile markers are told apart by dash pattern and label, never by colour alone, and every marked figure is stated in the chart's accessible name.
- `sv-data-summary-table` publishes every bin's range, count, share and running total — the last of which the plain measure never draws at all.
- The rug is deliberately not focusable: every reading it marks is already counted in a bar that is, so making each tick a tab stop would add hundreds of stops that say nothing new.
- What shaped the picture is stated in the rendered output: the bin rule that actually ran (including a fallback, or your own edges), the sample count, unequal widths drawn at count, the density bandwidth, and any reading that could not be binned or whose weight could not be used.
Feedback on Histogram & Density
Spotted a gap in this page, or something that didn't work as described? Comments are GitHub Discussions in the public styloviz/community repo, so posting needs a GitHub account.