The distribution of raw values across equal or explicit buckets
Tags: chart histogram distribution aging reporting
The HistogramChart counts raw values into buckets and draws the count of each. Pass the observations themselves (cycle times, days open, sale prices) and let the chart bucket them, either into equal-width buckets or into explicit ranges such as warranty aging buckets.
Svelte only (
@classic-homes/charts-svelte); React support is pending.
Import
<script>
import { HistogramChart } from '@classic-homes/charts-svelte';
</script>Basic Usage
<script>
import { HistogramChart } from '@classic-homes/charts-svelte';
// Days from start to close for each home closed this year
const cycleDays = [96, 104, 108, 111, 113, 118, 119, 121, 124, 126, 131, 133, 140, 152, 171];
</script>
<HistogramChart title="Cycle Time Distribution" values={cycleDays} binWidth={10} />Props
Chart-Specific Props
| Prop | Type | Default | Description |
|---|---|---|---|
values |
number[] |
required | Raw observations; non-finite values are ignored |
bins |
number | HistogramBin[] |
- | A count of equal-width buckets, or explicit buckets (defaults to Sturges' rule with rounded widths) |
binWidth |
number |
- | Width of equal buckets (takes precedence over a bin count) |
seriesName |
string |
'Count' |
Series name shown in tooltips |
color |
string |
- | Bar colour (defaults to the first series colour) |
showLabels |
boolean |
false |
Show counts above the bars |
labelFormatter |
string | ((params: LabelFormatterParams) => string) |
- | Data label template or function |
xAxisConfig |
AxisConfig |
- | Bucket axis customisation |
yAxisConfig |
AxisConfig |
- | Count axis customisation |
referenceLines |
ReferenceLine[] |
- | Horizontal lines marking a count (e.g. a capacity) |
referenceBands |
ReferenceBand[] |
- | Shaded count ranges |
onClick |
(params: DataPointEventParams) => void |
- | Callback when a bucket is clicked; name is the bucket label and value its count |
Inherited Base Props
On a histogram, valueFormat writes the bucket bounds in the axis labels (counts stay plain numbers).
| Prop | Type | Default | Description |
|---|---|---|---|
title |
string |
required | Chart title for accessibility (aria-label) |
description |
string |
- | Description for screen readers (generated from the data when omitted) |
height |
number | string |
400 |
Chart height in pixels or CSS value |
minHeight |
number |
- | Minimum height in pixels; also bounds an 'auto' height |
maxHeight |
number |
- | Maximum height in pixels; also bounds an 'auto' height |
loading |
boolean |
false |
Show loading skeleton (an overlay when data is already shown) |
error |
string | null |
- | Error message to display |
onRetry |
() => void |
- | Show a Retry button on the error state, calling this |
emptyMessage |
string |
- | Message shown when data is empty |
theme |
'light' | 'dark' | 'auto' |
'auto' |
Theme preference |
animation |
boolean |
true |
Enable/disable animations (respects prefers-reduced-motion) |
showTooltip |
boolean |
true |
Show tooltip on hover |
showGrid |
boolean |
true |
Show grid lines |
valueFormat |
ValueFormat |
- | Preset ('number', 'integer', 'compact', 'currency', 'currencyCents', 'percent', 'percentValue', 'days'), Intl.NumberFormatOptions or a function; drives the value axis, tooltip, labels and data table |
locale |
string |
'en-US' |
Locale for valueFormat |
tooltipFormatter |
string | ((items: TooltipFormatterParams[]) => string) |
- | Custom tooltip template or HTML function |
tooltipValueFormatter |
(value: number) => string |
- | Format values in the default tooltip (overrides valueFormat there) |
option |
EChartsOption |
- | Raw ECharts option deep-merged over the generated one |
onReady |
(chart: EChartsType) => void |
- | Called with the ECharts instance when it is created |
events |
ChartEventHandlers |
- | Raw ECharts event handlers keyed by event name ('datazoom', 'legendselectchanged', ...) |
showDataTable |
boolean | 'sr-only' |
'sr-only' |
Data table for screen readers only, a visible "Show data" toggle (true) or none (false) |
exportable |
boolean | ChartExportConfig |
- | Show PNG and CSV download buttons, or { image, csv, filename } |
patterns |
boolean |
false |
Fill series with decal patterns as well as colour |
class |
string |
- | Custom CSS class |
showLegend |
boolean |
- | Show chart legend |
Data Structure
// values: number[] — raw observations
interface HistogramBin {
start?: number; // Lower bound (inclusive); omit for no lower bound
end?: number; // Upper bound (exclusive, except the last bucket); omit for no upper bound
label?: string; // Axis label (defaults to "start–end", "< end" or "start+")
}Examples
Warranty Aging Buckets
Explicit buckets keep business-defined ranges. Values outside every bucket are not counted, so leave the last bucket open-ended.
<HistogramChart
title="Open Warranty Requests by Age"
values={daysOpen}
bins={[
{ end: 7, label: '0–6 days' },
{ start: 7, end: 30, label: '7–29 days' },
{ start: 30, end: 60, label: '30–59 days' },
{ start: 60, label: '60+ days' },
]}
seriesName="Requests"
showLabels
/>Bucket Count and Formatted Bounds
<HistogramChart
title="Sale Price Distribution"
values={salePrices}
bins={8}
valueFormat="compact"
/>With a Reference Line
<HistogramChart
title="Cycle Time Distribution"
values={cycleDays}
binWidth={14}
referenceLines={[{ value: 'average', label: 'Avg per bucket' }]}
/>Accessibility
- The
titleprop is used asaria-label; a description of the busiest bucket and total count is generated whendescriptionis omitted - Buckets and counts are rendered as a screen-reader table (
showDataTable) - Tooltips show each bucket's share of the total
- Animations respect
prefers-reduced-motion
Related Charts
- BoxPlotChart - Spread per category
- BarChart - Categorical comparison