Components / Charts
BrushChart
A dense time series with an overview strip: drag a window to zoom, resize it by its handles, and read events in place.
Install
npx shadcn@latest add https://irisui.dev/r/brush-chart.jsonimport { BrushChart } from "@/components/iris/brush-chart/brush-chart";Preview
BrushChart
A dense time series with an overview strip: drag a window to zoom, resize it by its handles, and read events in place.
When to use
- Long daily or hourly histories (months to years) where people need the whole picture and a close look at any stretch: active users, requests, revenue per day.
- Marking launches, incidents and pricing changes with short
annotationsthat show on both the plot and the overview. - Linking range presets (30D, 90D, 1Y) or other charts to the window through a controlled
range. - Not for a few weeks of data, multiple series or values below zero; use
LineChart. The value axis starts at zero, so it suits counts and totals better than prices.
Usage
import { BrushChart } from "@/components/iris/brush-chart/brush-chart";
function ActiveUsers({ days }) {
// [{ date: epochMs, value: 3240 }, ...] ascending
const last = days[days.length - 1].date;
const [range, setRange] = React.useState([days[days.length - 90].date, last]);
return h(BrushChart, {
data: days,
label: "MyRoomie daily active users",
unit: "users",
range,
onRangeChange: setRange,
annotations: [
{ date: Date.UTC(2026, 2, 24), label: "Profile Boost", description: "Profile Boost from €2.99/week" },
],
});
}
Props
| Prop | Type | Default | Description |
|---|---|---|---|
data |
{ date: Date | number; value: number }[] |
required | Points in ascending time order. |
label |
string |
required | Names the chart for assistive technology. |
unit |
string |
"" |
Unit after values in the tooltip and table. |
formatValue / formatTick / formatDate |
functions | compact ticks | Tooltip values, value axis, dates in tooltip and announcements. |
annotations |
{ date; label; description? }[] |
[] |
Event markers on both charts. Keep labels to a word or two. |
range |
[number, number] |
— | Controlled window in epoch ms; a new value glides the window there. |
defaultRange |
[number, number] |
whole series | Initial window when uncontrolled. |
onRangeChange |
(range) => void |
— | Fires while the window is dragged, resized, stepped or reset. |
minSpan |
number |
7 days | Smallest window in ms. |
height / overviewHeight |
number |
240 / 52 |
Main plot and overview strip heights. |
emptyLabel |
string |
"No data yet" |
Shown with fewer than two points. |
className |
string |
— | Class on the root figure. |
ref |
Ref<HTMLElement> |
— | Forwarded to the root figure. |
Notes
- Keyboard: on the plot, Left/Right move the crosshair. On the window, Left/Right pan a tenth (Shift or Page keys pan half),
+/-zoom around the centre. On a handle, Left/Right move that edge one point (Shift: ten). Home/End go to the ends; Escape or0resets to the whole series. - Accessibility: the window and both handles are sliders with dates in
aria-valuetext; the plot is a focusable group whose readings include any event that day; a hidden table lists the points in the window. Markers carry a text label, not colour alone. - Reads
--series-1for the line and area,--series-2for event markers,--lineand--line-strongfor the grid.