Brush chart
FreeA chart you zoom by dragging a brush, with event annotations.
pnpm dlx shadcn@latest add https://caliperui.site/r/brush-chart.json| Point | Actual | Event |
|---|---|---|
| Jan 31, 2026 | 110.3286058026949 | |
| Feb 1, 2026 | 111.41137421215416 | |
| Feb 2, 2026 | 112.69336486745937 | |
| Feb 3, 2026 | 114.15567739543687 | |
| Feb 4, 2026 | 115.77441406604554 | |
| Feb 5, 2026 | 117.52134208299938 | |
| Feb 6, 2026 | 119.36467601440859 | |
| Feb 7, 2026 | 121.26995867951817 | |
| Feb 8, 2026 | 123.20101607905738 | |
| Feb 9, 2026 | 125.12095990470253 | |
| Feb 10, 2026 | 126.99320984456976 | |
| Feb 11, 2026 | 128.78250735303743 | |
| Feb 12, 2026 | 130.45589278975032 | |
| Feb 13, 2026 | 131.98361884782787 | |
| Feb 14, 2026 | 133.33997495695044 | |
| Feb 15, 2026 | 134.50399981419793 | v2 launch |
| Feb 16, 2026 | 135.460062295891 | |
| Feb 17, 2026 | 136.19829465131374 | |
| Feb 18, 2026 | 136.71486597298707 | |
| Feb 19, 2026 | 137.012088364664 | |
| Feb 20, 2026 | 137.09835286475754 | |
| Feb 21, 2026 | 136.98789690098792 | |
| Feb 22, 2026 | 136.70040972090447 | |
| Feb 23, 2026 | 136.26048673319784 | |
| Feb 24, 2026 | 135.69694788193405 | |
| Feb 25, 2026 | 135.04203894397213 | |
| Feb 26, 2026 | 134.330537884438 | |
| Feb 27, 2026 | 133.59879103630553 | |
| Feb 28, 2026 | 132.8837058149575 | |
| Mar 1, 2026 | 132.2217278831683 | |
| Mar 2, 2026 | 131.64783111288503 | |
| Mar 3, 2026 | 131.19454833553738 | |
| Mar 4, 2026 | 130.8910697422142 | |
| Mar 5, 2026 | 130.76243392022664 | |
| Mar 6, 2026 | 130.82883394529514 | |
| Mar 7, 2026 | 131.10505776000102 | |
| Mar 8, 2026 | 131.60007834759438 | |
| Mar 9, 2026 | 132.316805058892 | |
| Mar 10, 2026 | 133.25200298387614 | |
| Mar 11, 2026 | 134.39638260249257 | |
| Mar 12, 2026 | 135.73485723010728 | |
| Mar 13, 2026 | 137.24696112289723 | |
| Mar 14, 2026 | 138.9074166559965 | |
| Mar 15, 2026 | 140.68683485588522 | |
| Mar 16, 2026 | 142.55252987279067 | |
| Mar 17, 2026 | 144.4694248211904 | |
| Mar 18, 2026 | 146.40102388437256 | |
| Mar 19, 2026 | 148.31042374259815 | |
| Mar 20, 2026 | 150.16133629461314 | |
| Mar 21, 2026 | 151.91909432928094 | |
| Mar 22, 2026 | 153.55161227661645 | |
| Mar 23, 2026 | 155.03027541241295 | |
| Mar 24, 2026 | 156.33073287345664 | |
| Mar 25, 2026 | 157.43357250607207 | |
| Mar 26, 2026 | 158.32485884555896 | |
| Mar 27, 2026 | 158.99651931720703 | |
| Mar 28, 2026 | 159.44656795589282 | |
| Mar 29, 2026 | 159.67916044419746 | |
| Mar 30, 2026 | 159.70447894374416 | |
| Mar 31, 2026 | 159.5384499114866 | |
| Apr 1, 2026 | 159.20230272125693 |
Jan 31, 2026 – Apr 1, 2026
Selected Jan 31, 2026 to Apr 1, 2026.
When to use #
Use it for
- Long histories where people need to focus on a range.
- Marking releases and incidents on a trend.
Skip it when
- Short series.
Installation #
pnpm dlx shadcn@latest add https://caliperui.site/r/brush-chart.json
Adds its 5 files to components/ui/, each with its own stylesheet, and installs their packages. No account needed. The first part also adds Caliper UI’s tokens; import them once as in Installation.
Usage #
This is the code behind the preview above.
import { useState } from "react" import { BrushChart } from "@/components/ui/brush-chart" export function ZoomableHistory() { const start = Date.UTC(2026, 0, 1); const data = Array.from({ length: 120 }, (_, index) => ({ date: start + index * 86400000, value: 100 + index * 0.6 + Math.sin(index / 6) * 8 })); const [range, setRange] = useState<[number, number]>([start + 30 * 86400000, start + 90 * 86400000]); return ( <div className="w-full max-w-2xl"> <BrushChart label="Daily revenue" data={data} range={range} onRangeChange={setRange} annotations={[{ date: start + 45 * 86400000, label: "v2 launch" }]} /> </div> ); }
API reference #
BrushChart
component
Accessibility #
It exposes slider and status semantics, with aria-label, aria-hidden, aria-valuemin, aria-valuemax, aria-valuenow and aria-valuetext kept in step with state. Changes that matter are announced through a live region.
Motion #
Transitions use the shared duration and easing tokens. Under prefers-reduced-motion those tokens collapse to instant and travel distances go to zero, so state changes still happen without movement.