Brush chart

A dense time series with an overview strip: drag a window to zoom, resize it by its handles, and read events in place.

pnpm dlx shadcn@latest add @uiarc/brush-chart
Live · keyboard ready

Daily active users

16,534 a day, Jun 23, 2026 to Sep 20, 2026

Daily active users, Sep 21, 2024 to Sep 20, 2026. Showing Jun 23, 2026 to Sep 20, 2026.

Daily active users, Jun 23, 2026 to Sep 20, 2026
DateDaily active usersEvent
Jun 23, 202617,915 users
Jun 24, 202616,983 users
Jun 25, 202617,249 users
Jun 26, 202617,354 users
Jun 27, 202612,582 users
Jun 28, 202612,503 users
Jun 29, 202617,841 users
Jun 30, 202617,385 users
Jul 1, 202617,937 users
Jul 2, 202616,931 users
Jul 3, 202617,207 users
Jul 4, 202612,422 users
Jul 5, 202612,855 users
Jul 6, 202617,152 users
Jul 7, 202616,914 users
Jul 8, 202617,064 users
Jul 9, 202616,741 users
Jul 10, 202616,808 users
Jul 11, 202613,155 users
Jul 12, 202612,407 users
Jul 13, 202617,440 users
Jul 14, 202616,987 users
Jul 15, 202617,267 users
Jul 16, 202616,654 users
Jul 17, 202616,754 users
Jul 18, 202612,547 users
Jul 19, 202612,794 users
Jul 20, 202616,507 users
Jul 21, 202617,563 users
Jul 22, 202616,812 users
Jul 23, 202616,574 users
Jul 24, 202617,384 users
Jul 25, 202612,784 users
Jul 26, 202612,503 users
Jul 27, 202616,165 users
Jul 28, 202617,246 users
Jul 29, 202616,703 users
Jul 30, 202616,883 users
Jul 31, 202616,554 users
Aug 1, 202612,212 users
Aug 2, 202612,488 users
Aug 3, 202616,426 users
Aug 4, 202616,863 users
Aug 5, 202617,159 users
Aug 6, 202616,599 users
Aug 7, 202617,040 users
Aug 8, 202612,323 users
Aug 9, 202612,429 users
Aug 10, 202617,126 users
Aug 11, 202616,963 users
Aug 12, 202617,460 users
Aug 13, 202616,985 users
Aug 14, 202617,482 users
Aug 15, 202612,970 users
Aug 16, 202613,473 users
Aug 17, 202617,553 users
Aug 18, 202618,239 users
Aug 19, 202618,381 users
Aug 20, 202618,064 users
Aug 21, 202618,647 users
Aug 22, 202613,650 users
Aug 23, 202614,003 users
Aug 24, 202618,501 users
Aug 25, 202619,097 users
Aug 26, 202619,569 users
Aug 27, 202618,963 users
Aug 28, 202619,535 users
Aug 29, 202613,906 users
Aug 30, 202613,770 users
Aug 31, 202619,088 users
Sep 1, 202619,507 users
Sep 2, 202619,535 users
Sep 3, 202619,450 users
Sep 4, 202619,818 users
Sep 5, 202613,843 users
Sep 6, 202614,092 users
Sep 7, 202619,388 users
Sep 8, 202620,105 users
Sep 9, 202618,927 users
Sep 10, 202619,300 users
Sep 11, 202619,774 users
Sep 12, 202614,675 users
Sep 13, 202614,410 users
Sep 14, 202619,699 users
Sep 15, 202619,450 users
Sep 16, 202619,574 users
Sep 17, 202619,267 users
Sep 18, 202620,111 users
Sep 19, 202614,478 users
Sep 20, 202614,147 users
  • Product analytics with a year or more of daily data.
  • Incident reviews where events need to be read against a metric.
  • Any chart where people ask to zoom into a stretch without losing context.
  • Use line-chart for a few weeks of data or several series.
  • Use sparkline for a small inline trend without interaction.
  • Avoid it for data that dips below zero or needs a log scale.

Installation

Add Brush chart with the shadcn CLI, or copy the source by hand.

pnpm dlx shadcn@latest add @uiarc/brush-chart

Adds the component and its local dependencies, and installs motion. First time? Add the @uiarc registry to components.json, or use the full URL:

example.tsx
import { useState } from "react";import { BrushChart } from "@/registry/components/brush-chart/brush-chart"; export function ActiveUsers({ days }: { days: { date: number; value: number }[] }) {  const [range, setRange] = useState<[number, number]>([days[days.length - 90].date, days[days.length - 1].date]);  return <BrushChart data={days} label="Daily active users" unit="users" range={range} onRangeChange={setRange}    annotations={[{ date: Date.UTC(2026, 2, 24), label: "v2", description: "Offline mode and shared spaces" }]} />;}

BrushChart

A detailed time series with an overview strip. Drag the window to pan, its handles to resize, or across empty track to draw a new one; double click resets. Zoomed out, a seven point average and band replace the raw line.

PropTypeDefaultDescription
dataRequired{ date: Date | number; value: number }[]–Points in ascending time order.
labelRequiredstring–Names the chart for assistive technology.
unitstring""Unit after values in the tooltip and table.
formatValue(value: number) => string–Formats values in the tooltip and table.
formatTick(value: number) => string–Formats the value axis. Defaults to a compact number.
formatDate(date: Date) => string–Formats dates in the tooltip and announcements.
annotations{ date: Date | number; label: string; description?: string }[][]Events drawn as markers on both charts; labels show where they fit.
range[number, number]–Controlled window as epoch milliseconds. A new value glides the window there.
defaultRange[number, number]–Initial window when uncontrolled. Defaults to the whole series.
onRangeChange(range: [number, number]) => void–Called while the window is dragged, resized, stepped, or reset.
minSpannumber7 daysSmallest window in milliseconds.
heightnumber240Main plot height in pixels.
overviewHeightnumber52Overview strip height in pixels.
emptyLabelstring"No data yet"Shown with fewer than two points.
classNamestring–Extra class on the figure.
ArrowLeftorArrowRight (plot)
Moves the crosshair between points in view.
ArrowLeftorArrowRight (window)
Pans by a tenth of the window; Shift or PageUp and PageDown pan by half.
+or- (window)
Zooms in or out around the window's centre.
ArrowLeftorArrowRight (handles)
Moves that edge by one point; Shift moves by ten.
HomeorEnd
Moves the window or edge to the start or end.
Escapeor0
Resets the window to the whole series.
  • The window and both handles are sliders with dates as aria-valuetext.
  • The plot is a focusable group; each reading is announced with its date, value, and any event on that day.
  • A visually hidden table lists every point in the window with its event.
  • Event markers pair the second series hue with a text label or tooltip; they never rely on color alone.
  • The line draws in from the left once, the first time it is seen.
  • Dragging tracks the pointer 1:1; presets, resets, and controlled changes glide the window on a spring.
  • The value axis springs to the tallest point in view, and the raw line crossfades with the smoothed trend as density changes.
  • Reduced motion places the window directly and keeps the crosshair without travel.
  • Both charts fill their container; date ticks pick days, weeks, months, or years to fit the width.
  • Handles have a 28 by 44px hit area for touch, and the strip keeps vertical page scroll free.
  • Event labels are placed left to right and skip themselves when they would collide.
  • Past two points per pixel, each pixel column keeps only its low and high, so spikes survive and paths stay small.
  • The overview path is built once per width; the rolling average is computed once per data change.
  • Window moves re-render one component; a few thousand points stay smooth.

Notes for AI

Give your coding assistant the Markdown reference instead of screenshots.

  • Choose it for long daily or hourly series where people need both the whole history and a close look.
  • Control range to sync presets (30D, 90D, 1Y) or other charts with the window.
  • Use annotations for launches, incidents, and pricing changes; keep labels to a word or two.
  • The value axis starts at zero, so it suits counts and totals rather than prices that hover far from zero.

The full library index for assistants is at /llms.txt.