Window range

Pro

A time window over a live area chart: drag its edges to resize, drag or flick it to pan with momentum, and the dates roll to their new values.

Live · keyboard ready
Visitors104,206+6.5%vs previous 30 days
  • Choosing the date range of an analytics report while seeing the shape of the data behind it.
  • Scrubbing a window over usage, revenue or latency to compare periods.
  • A compact overview with a movable window above a detailed chart or table.
  • Use date-range-picker when people pick exact dates from a calendar or the range spans years.
  • Use brush-chart when the window should zoom a large detailed chart and show events in place.
  • Use slider or gooey-range for numeric ranges that have no series to show.

Installation

Pro source and install commands unlock with a Pro plan.

example.tsx
import { useState } from "react";import { WindowRange } from "@/components/arc/window-range/window-range"; const day = new Intl.DateTimeFormat("en-US", { month: "short", day: "numeric", timeZone: "UTC" });const FIRST = Date.UTC(2026, 3, 1); export function VisitorsReport({ visits }: { visits: number[] }) {  const last = visits.length - 1;  const [range, setRange] = useState<[number, number]>([last - 29, last]);   return (    <WindowRange      label="Report dates"      data={visits}      value={range}      onValueChange={setRange}      onValueCommit={loadReport}      minSpan={6}      format={index => day.format(FIRST + index * 86_400_000)}      formatSpan={span => `${span + 1} days`}      live    />  );}

WindowRange

A time window over a live area chart. Drag either edge of the frame to resize the window, drag inside it to pan and flick to let it coast, or press outside to glide it there. The chart outside the window fades back, the one inside stays in full color, and the start, end and length readouts roll to their new values. New data morphs the chart in place, and a live dot pulses on the latest point.

PropTypeDefaultDescription
dataRequiredreadonly number[]–The series behind the window, one number per point, spread evenly from min to max. Pass a new array to morph the chart to it.
value[number, number]–Controlled window as [start, end] in domain units. Pair with onValueChange. A new value from outside glides the frame there.
defaultValue[number, number]the last quarterStarting window when uncontrolled.
onValueChange(value: [number, number]) => void–Runs on every change while dragging, coasting after a flick or pressing keys.
onValueCommit(value: [number, number]) => void–Runs once the window has settled after a drag, a flick or a key. Use it to fetch the report for the window.
minnumber0Start of the domain, for example day 0.
maxnumberdata.length - 1End of the domain.
stepnumber1Both ends snap to this step, counted from min. With one point per day and the default, the window moves in days.
largeStepnumbera tenth of the domainHow far Page Up, Page Down and Shift with an arrow move an edge or the window.
minSpannumberstepThe narrowest window as end minus start, in domain units.
maxSpannumberthe whole domainThe widest window as end minus start, in domain units.
format(value: number) => string–Formats the start and end readouts and the spoken values, for example a day index as Aug 31.
formatSpan((span: number) => string) | null–Formats the middle readout from end minus start, for example span => `${span + 1} days`. Pass null to hide it.
ticksreadonly { value: number; label: string }[]–Labels under the chart, such as the first day of each month.
labelstring"Date range"Names the group and prefixes the names of the start, window and end sliders.
livebooleanfalsePulses a dot on the latest point to show that the series is still arriving.
accentstring–Any CSS color for the frame and the line. Defaults to the selection control color for the frame and the first chart series for the line.
heightnumber112Height of the chart in px, from 64 to 240.
disabledbooleanfalseDims the control and ignores pointer and keys.
classNamestring–Class on the root element.
styleCSSProperties–Inline styles on the root element.
Tab
Moves focus to the start edge, the window, then the end edge.
Arrow RightorArrow Left
On an edge, moves that edge by one step. On the window, pans the whole window by one step.
Arrow UporArrow Down
Same as Arrow Right and Arrow Left.
Shift+Arrow, Page UporPage Down
Moves the edge or the window by the large step.
HomeorEnd
On the window, pans it to the start or end of the domain. On an edge, moves it as far as the span limits allow.
  • The component is a group named by label with three focusable role="slider" elements: the start edge, the window and the end edge.
  • Each edge speaks its formatted date, with aria-valuemin and aria-valuemax that respect minSpan and maxSpan. The window speaks both ends, such as Aug 31 to Sep 29, and its range is the start positions it can take.
  • The chart, the frame and the rolling readouts are decorative and hidden from assistive technology; the sliders carry every value.
  • Pressing into a limit with a key nudges the frame against it instead of failing silently.
  • Pointer focus draws no ring; keyboard focus shows Arc's shared focus ring. A pressed part takes focus so keys continue where the pointer left off.
  • One requestAnimationFrame loop steps the frame's springs at 240 Hz and writes transforms straight to the DOM through a cache; it stops at rest, offscreen and in background tabs.
  • Dragging an edge or the window follows the finger one to one with coalesced pointer events. Past either end of the domain, or past the span limits, the frame rubber bands.
  • Releasing a pan keeps the measured speed: the landing point is projected from the flick, snapped to a step and reached on a critically damped spring that starts at the flick's speed, so the window decelerates like a scroll view and bumps softly into either end. Grabbing it mid coast stops it where it is.
  • A press outside the window glides it to center on the finger on a softer spring; dragging on moves it from there. Keys, presets and new values from props glide the same way.
  • The full color chart shows through a clip that is scaled to the window while its content is scaled back, so moving the window never relayouts or repaints the chart; outside it the muted copy shows.
  • The readouts roll each changed digit, and month names as a whole word, in the direction of change. During a drag or a coast they update in place so they never trail the frame.
  • New data morphs the line and area from the old shape on a smooth spring. The live dot pulses with a compositor animation.
  • With reduced motion the frame jumps to each value, there is no coast, rubber band, roll, chart morph or pulse, and every value, key and readout still works.
  • The chart and frame fill their container from 320px up. The readouts share one row, with the length in the middle; hide it with formatSpan null in very tight spaces.
  • The plot takes the press with touch-action pan-y, so vertical page scroll still works over the chart. The edges have hit areas that reach 14px outward, and the frame never draws narrower than its two edges.
  • Tick labels sit under their values; pass fewer ticks at narrow widths.
  • Moving the window only writes transforms on the frame, the edges and the clip; the chart path is written only when data changes.
  • The chart is one SVG path pair drawn twice with a non scaling stroke, so resizing the container needs no recalculation beyond one measure.
  • Pointer math reads the plot rectangle once per press, and the loop idles at rest and pauses offscreen with an IntersectionObserver and in background tabs.

Notes for AI

Give your coding assistant the Markdown reference instead of screenshots.

  • Use it to pick a time window over a series people can see: analytics reports, billing usage, logs or metrics. Keep the data to one point per step, a few hundred points at most.
  • Map the domain to indices and format them: pass min 0, one data point per day and a format that turns the index into a date. formatSpan receives end minus start, so add one for an inclusive day count.
  • Recompute totals in onValueChange for live feedback, and fetch in onValueCommit, which fires once the window settles.
  • Pair it with quick range buttons that set value; the frame glides to them and the readouts roll.
  • Set live only when the latest point really is still changing.

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