[data-reveal]{opacity:1!important;transform:none!important}
Period selector
Components

Period selector

A date range picker whose period, kept in the page URL, drives every widget that names its scope.

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.

Period selectorPeriodSelector
Connecting to the DMS preview…
ConnectingDMS 0.9.57 options set

Usage

src/pages/sales.ts
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

Options of the Period selector block
OptionTypeDefaultDescription
presetLabelsContentRecord<string, string>–
comparisonLabelsContentRecord<string, string>–
alignAppearance"left" | "center" | "right"–
sizeAppearance"xs" | "sm" | "md" | "lg" | "xl"–
showRangeLabelAppearanceboolean–
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"[]–
maxDaysBehaviornumber–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 id equals its periodScope. The default id is page.
  • presetLabels and comparisonLabels relabel the menus; use $ keys so they translate.

Next steps

Period filtering

Read the period in a route.

Live toggle

The other control of a monitoring toolbar.