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-pickerimport {
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
| Prop | Type | Default | Description |
|---|---|---|---|
value | TimeRange | — | Current window. Controlled. |
onChange | (range: TimeRange) => void | — | Fires on preset selection or calendar range change. |
presets | TimeRangePreset[] | — | Optional preset row, rendered as a SegmentedControl above the calendar. |
align | "start" | "end" | "start" | Popover alignment relative to the trigger. |
className | string | — | Extra classes on the trigger Button. |
TimeRange
| Field | Type | Description |
|---|---|---|
from | Date | Window start (inclusive). |
to | Date | Window end. |
TimeRangePreset
| Field | Type | Description |
|---|---|---|
id | string | Stable key; tracked as the active segment. |
label | string | Segment label (keep short: 1h, 24h, 7d). |
resolve | () => TimeRange | Called 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
classNamesprop with ploxum tokens; pulling inreact-day-picker/style.csswill 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.
