Charts
Histogram
A numeric distribution grouped into adjacent equal-width ranges.
When to use it: Use it to show shape, concentration, spread, and outliers in continuous observations.
Example
import {
ChartDescription,
ChartTable,
ChartTitle,
ChartTooltip,
Histogram,
HistogramBin,
HistogramPlot,
} from "@comp0/react";
const responseTimes = [180, 210, 230, 250, 270, 290, 310, 340, 380, 420, 480, 620] as const;
const formatMilliseconds = (value: number) => `${Math.round(value)} ms`;
export function Example() {
return (
<Histogram
values={responseTimes}
valueLabel="Response time"
frequencyLabel="Requests"
formatValue={formatMilliseconds}
className="w-full max-w-2xl rounded-lg has-[:focus-visible]:outline-2 has-[:focus-visible]:outline-offset-4 has-[:focus-visible]:outline-teal-600 dark:has-[:focus-visible]:outline-teal-400"
>
<ChartTitle className="text-base font-semibold text-zinc-950 dark:text-zinc-50">
API response-time distribution
</ChartTitle>
<HistogramPlot
aria-label="Histogram showing API response-time distribution"
binCount={5}
className="mx-auto mt-5 aspect-square w-full max-w-md overflow-visible"
>
{(bin) => (
<HistogramBin key={bin.index} bin={bin} className="group outline-none">
<rect
x={bin.x}
y={bin.y}
width={bin.width}
height={bin.height}
className="fill-teal-600 stroke-white group-data-active:stroke-zinc-950 dark:fill-teal-400 dark:stroke-zinc-950 dark:group-data-active:stroke-white"
strokeWidth="1"
vectorEffect="non-scaling-stroke"
/>
</HistogramBin>
)}
</HistogramPlot>
<ChartDescription className="mt-5 text-sm text-zinc-600 dark:text-zinc-400">
Most sampled requests completed below 350 milliseconds, with one slower outlier.
</ChartDescription>
<ChartTable className="mt-4 w-full border-collapse text-left text-sm [&_td]:border-t [&_td]:border-zinc-200 [&_td]:py-2 [&_th]:border-zinc-200 [&_th]:py-2 dark:[&_td]:border-zinc-800 dark:[&_th]:border-zinc-800">
<caption className="sr-only">Sampled API response times</caption>
<thead>
<tr>
<th scope="col">Sample</th>
<th scope="col">Response time</th>
</tr>
</thead>
<tbody>
{responseTimes.map((responseTime, index) => (
<tr key={`${responseTime}-${index}`}>
<th scope="row">{index + 1}</th>
<td>{formatMilliseconds(responseTime)}</td>
</tr>
))}
</tbody>
</ChartTable>
<ChartTooltip className="pointer-events-none z-50 rounded-md bg-zinc-950 px-2 py-1 text-sm text-white shadow-lg dark:bg-zinc-50 dark:text-zinc-950" />
</Histogram>
);
}Anatomy
Dashed frames are invisible state providers; shaded shapes own real DOM. Numbered pins match the list below.
A wireframe sketch of the assembled component. Each numbered marker matches a part in the list that follows.
Histogram
Native figure sharing observations, labels, and value formatting. Owns a DOM element.
ChartTitle
Native figcaption that visibly names the figure. Owns a DOM element.
HistogramPlot / HistogramBin
Adjacent SVG bins positioned against value and frequency axes. Owns a DOM element.
ChartDescription
Visible prose summarizing shape and outliers. Owns a DOM element.
ChartTable
Native table containing underlying observations or exact bin counts. Owns a DOM element.
ChartTooltipOptional
Optional floating range and count shown on hover or focus. Owns a DOM element.
Step by step
- 1
Add the main part
Start Histogram with finite observations and visible value and frequency labels.
- 2
Add the supporting parts
Choose a meaningful binCount and wrap each rendered range in HistogramBin.
- 3
Make the behavior clear
Describe the distribution and keep the underlying observations or bin counts in a native ChartTable.
Exampletsx <Histogram values={responseTimes} valueLabel="Response time" frequencyLabel="Requests"> <ChartTitle>Response-time distribution</ChartTitle> <HistogramPlot aria-label="Histogram of response times"> {(bin) => ( <HistogramBin bin={bin}> <rect x={bin.x} y={bin.y} width={bin.width} height={bin.height} /> </HistogramBin> )} </HistogramPlot> <ChartTable> <caption>Response times</caption> </ChartTable> <ChartTooltip /> </Histogram>;
Keyboard
- ⇥
- Enters the chart at its current bin and leaves with one more Tab.
- ←→
- Moves between adjacent bins.
- HomeEnd
- Moves to the first or last bin.
- Esc
- Dismisses an open ChartTooltip.
Forms and accessibility
Charts are descriptive content and do not create form values.
Accessibility checklist
- Name both the measured value axis and the frequency axis.
- Choose bins that communicate the distribution honestly; changing bin count can materially change its appearance.
- Wrap each custom bar in HistogramBin so its range and count are keyboard reachable.
- Keep the underlying observations or exact bin counts available in a native table.
- Adjacent bins should remain visibly separable in every color scheme.
API reference
import { ChartDescription, ChartTable, ChartTitle, ChartTooltip, Histogram, HistogramBin, HistogramPlot } from "@comp0/react";Histogram
DOM elementNative figure sharing observations, labels, and value formatting.
| Prop | Type | Description |
|---|---|---|
values | readonly number[] | Finite observations grouped into ranges by HistogramPlot. |
valueLabel | string | Visible headings for values and counts. |
frequencyLabel | string | Visible headings for values and counts. |
formatValue | (value: number) => string | Formats range boundaries and horizontal ticks. |
ChartTitle
DOM elementNative figcaption that visibly names the figure.
HistogramPlot / HistogramBin
DOM elementAdjacent SVG bins positioned against value and frequency axes.
| Prop | Type | Description |
|---|---|---|
aria-label | string | Concise text alternative naming the distribution. |
binCount | number | Positive number of equal-width bins; defaults from the observation count. |
xMin | number | Optional value bounds and visible tick counts. |
xMax | number | Optional value bounds and visible tick counts. |
xTickCount | number | Optional value bounds and visible tick counts. |
yTickCount | number | Optional value bounds and visible tick counts. |
children | (bin: HistogramBinState) => ReactNode | Custom bin renderer receiving its range, count, and geometry. |
bin | HistogramBinState | Bin state passed from the plot to HistogramBin. |
ChartDescription
DOM elementVisible prose summarizing shape and outliers.
ChartTable
DOM elementNative table containing underlying observations or exact bin counts.
ChartTooltip
OptionalDOM elementOptional floating range and count shown on hover or focus.
Style hooks
Attributes that appear while a state is true. Target them with Tailwind data variants such as data-open:bg-zinc-100, or with any CSS selector.
HistogramPlot / HistogramBin
| Style hook | Meaning |
|---|---|
[data-count] | The number of observations in this bin. |
[data-active] | The bin currently reached by pointer or keyboard. |
ChartTooltip
| Style hook | Meaning |
|---|---|
[data-open] | A value tooltip is visible. |