Period selector
PeriodSelector is the date range control of a dashboard. Place one on the page; every chart, card, list and table bound to its id through periodScope reads its route again when the range or the comparison changes. It draws a preset dropdown (or inline pills), an optional custom range, a comparison control, and optionally the resolved range as text.
PeriodSelectorUsage
import { PeriodSelector } from "@antelopejs/interface-dms/base/period-selector";
static period = PeriodSelector({ id: "sales", defaultPreset: "last-30-days" });
static revenue = KpiCard({ title: "Revenue", fetchUrl: "/api/sales/revenue", periodScope: "sales" });
On each change, the selector adds preset, from / to and comparison to every scoped widget's request. Period filtering shows how a route reads them.
Options
| Option | Type | Default | Description |
|---|---|---|---|
presetLabelsContent | Record<string, string> | – | |
comparisonLabelsContent | Record<string, string> | – | |
alignAppearance | "left" | "center" | "right" | – | |
sizeAppearance | "xs" | "sm" | "md" | "lg" | "xl" | – | |
showRangeLabelAppearance | boolean | – | |
rangeLabelAppearance | "absolute" | "relative" | – | Relative says how long ago the period starts, rather than its dates. |
comparisonControlAppearance | "menu" | "toggle" | "hidden" | – | How the comparisons are offered. |
variantAppearance | "default" | "segmented" | – | Segmented shows the periods as buttons side by side. |
defaultPresetBehavior | "last-hour" | "last-24h" | "today" | "yesterday" | "last-7-days" | "last-30-days" | … | – | |
defaultComparisonBehavior | "none" | "previous-period" | "previous-year" | "custom" | – | |
presetsBehavior | "last-hour" | "last-24h" | "today" | "yesterday" | "last-7-days" | "last-30-days" | …[] | – | The periods people can pick from. |
comparisonsBehavior | "none" | "previous-period" | "previous-year" | "custom"[] | – | |
maxDaysBehavior | number | – | The longest custom range the user can pick, in days. |
PeriodPreset is one of last-hour, last-24h, today, yesterday, last-7-days, last-30-days, last-90-days, this-month, last-month, this-quarter, last-quarter, ytd, last-year, all, custom. PeriodComparison is none, previous-period, previous-year or custom.
The period lives in the URL
Every selector writes its period into the page URL, keyed by its id: ?sales.period=last-7-days&sales.compare=previous-period, or ?sales.from=2026-10-01&sales.to=2026-10-31 for a custom range. A link or a reload opens the same period, the server renders it, and the default never flashes. A change replaces the history entry, so Back leaves the page. Without a period in the URL, the selector starts from the user's last choice on that page, then from defaultPreset.
Recipes
Several scopes on one page
Give each selector a distinct id and point disjoint widget groups at each. Their URL keys never collide.
Pills for a metrics page
variant: "segmented" turns a short preset list into inline pills: one click per range instead of open-then-pick. Keep the list to a handful; the custom range stays in its popover calendar.
All time
Offer all in presets for an "All time" choice. The bound widgets receive preset=all and no from / to; the route reads it as no time filter.
A relative label
rangeLabel: "relative" writes a window that reaches now from its start, in the reader's locale: "since 11:52", "since yesterday 11:52", "since Mon 11:52".
One remembered period across a module
rememberKey: "api" on the selector of each page of a module makes them share the remembered choice, so the period follows the user from page to page.
A compact comparison
A selector offering a single comparison draws one inline toggle instead of a menu. comparisonControl: "toggle" asks for it among several, and comparisonControl: "hidden" draws nothing and keeps the comparison on.
Cap a custom range
maxDays: 31 keeps a custom range to 31 days, both ends included. Presets and a range put in the URL by a link are not limited, so the route still enforces its own limit.
Pitfalls
- A widget only follows a selector whose
idequals itsperiodScope. The defaultidispage. presetLabelsandcomparisonLabelsrelabel the menus; use$keys so they translate.

