A row of date-range presets — Today, Last 7 days, Month to date, Last month, Year to date — with a custom from/to range behind the last option, that answers with a relative expression like "last7d" instead of a pair of dates. Reach for it above anything that shows numbers for a period: an analytics or product dashboard, a revenue, sales or KPI report, billing and invoice history, usage and metering pages, a logs, events or audit-trail viewer, error and monitoring views, an admin table that filters by date, a search or order history, cohort and retention reports, attendance and timesheet summaries, a CSV or PDF export range, and the period selector beside any chart. Common asks it answers: "date range picker react", "date range preset component", "last 7 days selector", "date range filter", "period selector dashboard", "relative date range react", "date range in URL query param", "shadcn date range picker", "shadcn date range preset", "react-date-range alternative", "react-daterange-picker alternative", "MUI DateRangePicker shortcuts equivalent", "antd RangePicker presets equivalent", "date range shortcuts", "this month last month selector", "analytics time range selector", "from to date filter component". Official shadcn/ui has nothing for this and no combination of its parts reaches it: calendar is a react-day-picker wrapper that pulls in react-day-picker and date-fns and answers with a Date for a day, the Date Picker page is that same calendar inside a popover, and neither carries the idea of a period at all — startOfDay, endOfDay, subDays and DateRange do not appear anywhere in the library. Distinct from pulld date-input, which types one full date (and is what this composes for its custom fields), from month-picker, which chooses a single calendar month, from calendar-heatmap, which draws a year of days rather than selecting a span of them, and from weekly-hours, which sets recurring opening times rather than a one-off period. The component turns on one distinction that every hand-rolled version collapses: a relative period is an expression, not a value. Fold "last 7 days" into "2026-09-17..2026-09-23" at the moment it is clicked — which is what storing a { from: Date, to: Date } pair does — and you have written down the answer to a question nobody asked again. Share that URL and the recipient sees your week rather than theirs. Open the same saved view tomorrow and the figures have not moved, which is the single most common "the dashboard is broken" report there is and the hardest to see, because the page is faithfully showing the stale week it was told to. Here the value stays the string "last7d" all the way into the URL, the saved view and the form post, and resolveDateRange evaluates it at the moment you query. Three more things it settles that are invisible until they are wrong. The resolved range is half-open — start included, end excluded — so there is never a last instant to pick and therefore never the 23:59:59 that silently drops the final second of the period, nor the 23:59:59.999 that drops the final millisecond; the end is simply the day after the last one you want, and the summary line shows the last day actually included rather than that excluded end, because telling a reader their range ends on the 24th when the 24th is not in it is just false. Which day is "today" is a property of a time zone rather than of the clock, so todayIn takes an IANA zone and throws on one the runtime does not know instead of quietly falling back to whatever zone the server happens to run in — the reason a browser and the job that aggregates the rows can otherwise disagree by a day at the edges for anyone working late. And whether "Last 7 days" includes today is a real fork with two defensible answers, so it is written out as ordinary data in DEFAULT_PRESETS that you can replace one line at a time rather than buried in the component; there is deliberately no "this week", because the first day of the week is Sunday, Monday or Saturday depending on where you are and a component that quietly picked one would be wrong for much of the world without ever saying so. The preset id and a custom range share one query expression — "last7d" or "2026-09-01..2026-09-30" — so ?period= round-trips either without a second encoding to keep in sync, and parseDateRange refuses backwards ranges and impossible days like 2026-02-30 so a link a stranger edited cannot build a query. Calendar arithmetic is done without a date library: January's "last month" lands in the previous year on its own, February is as long as it actually was that year, and a year under 100 stays that year instead of becoming nineteen-hundred-something the way Date.UTC would have it. It is a real radiogroup with a roving tabindex — one tab stop for the whole row, then arrow keys inside it, which select as they move, with Home and End at the ends and wrapping at both, and left and right following the writing direction so they do not run backwards on an RTL page. A permanently mounted polite live region names the span in words through Intl, so the dates are announced rather than left as a visual-only state, and it stays in the accessibility tree when empty instead of being rendered along with its message. Choosing the custom option reports nothing until both dates make a range, so the dashboard behind the picker is never blanked mid-edit, and the fields open seeded with the range being looked at rather than two empty boxes. Uncontrolled, or controlled by pairing value with onValueChange; give it a name and it posts the expression with a plain form or a server action. The maths is exported too — resolveDateRange, parseDateRange, formatDateRange, todayIn, shiftDay, toCalendarDay, toPlainDate and lastIncludedDay — so a server route can resolve the same string the picker produced without reimplementing any of it. Styled entirely with shadcn tokens (primary, input, accent, ring, muted-foreground, destructive), so it follows light and dark mode, and it ships zero npm dependencies — no date library, no icon package.
pnpm dlx shadcn@latest add "https://pulld.pages.dev/r/date-range-preset.json"