Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content

TimeRangePicker

Popover time-window scoper with preset chips and a range calendar — preserves time-of-day when dates change.

Import

TimeRangePicker is a registry composite — you own the source after installing:

npx ploxum add time-range-picker
import {
  TimeRangePicker,
  type TimeRange,
  type TimeRangePreset,
} from "@/components/time-range-picker";

Requires react-day-picker as an npm dependency (declared in the registry item, installed alongside the source). Also depends on @roger-emerson/ploxum-primitives (Button, Popover, SegmentedControl) and @roger-emerson/ploxum-icons (Clock).

Usage

const HOUR = 3_600_000;
 
const presets: TimeRangePreset[] = [
  {
    id: "1h",
    label: "1h",
    resolve: () => ({ from: new Date(Date.now() - HOUR), to: new Date() }),
  },
  {
    id: "24h",
    label: "24h",
    resolve: () => ({ from: new Date(Date.now() - 24 * HOUR), to: new Date() }),
  },
  {
    id: "7d",
    label: "7d",
    resolve: () => ({ from: new Date(Date.now() - 7 * 24 * HOUR), to: new Date() }),
  },
];
 
function DashboardToolbar() {
  const [range, setRange] = useState<TimeRange>(presets[1].resolve());
 
  return (
    <TimeRangePicker
      align="end"
      onChange={setRange}
      presets={presets}
      value={range}
    />
  );
}

The trigger is a secondary Button rendering the current window in monospace (Jun 8 19:00 – Jun 9 19:00). Picking dates on the calendar keeps the existing time-of-day from value.from / value.to; selecting only a start day extends the range to that day's end. Choosing a calendar date clears the active preset.

Props

TimeRangePicker

PropTypeDefaultDescription
valueTimeRangeCurrent window. Controlled.
onChange(range: TimeRange) => voidFires on preset selection or calendar range change.
presetsTimeRangePreset[]Optional preset row, rendered as a SegmentedControl above the calendar.
align"start" | "end""start"Popover alignment relative to the trigger.
classNamestringExtra classes on the trigger Button.

TimeRange

FieldTypeDescription
fromDateWindow start (inclusive).
toDateWindow end.

TimeRangePreset

FieldTypeDescription
idstringStable key; tracked as the active segment.
labelstringSegment label (keep short: 1h, 24h, 7d).
resolve() => TimeRangeCalled at click time so relative windows resolve against now.

Design rules

  • Never import react-day-picker's stylesheet. The composite restyles DayPicker entirely through its classNames prop with ploxum tokens; pulling in react-day-picker/style.css will fight it.
  • The trigger readout and calendar day cells are monospace + tabular numerals — date math must not shift layout.
  • Presets resolve() lazily so "last 1h" means the hour before the click, not the hour before mount.
  • The popover does not trap focus (per heuristic 9) — the operator can Esc or click away mid-selection without losing the prior window.

Storybook

Composites/TimeRangePicker ↗