@get-asset/sdk
Date Picker
One control for both jobs: a calendar period or a custom range, behind a mode switch. It owns the switch and the popover only — the two panels are a DatePicker.Period.Root and a DatePicker.Range.Root mounted inside it, both editing AssetProvider's single dateFrom/dateTo range. That range is what every date-driven component reports on, so a choice here moves the whole page.
Preview
Loading preview…
Anatomy
Import the primitive and compose the parts you need.
<DatePicker.Root><DatePicker.Anchor><DatePicker.Trigger><DatePicker.Value /></DatePicker.Trigger></DatePicker.Anchor><DatePicker.Portal><DatePicker.Content><DatePicker.ModeSwitch><DatePicker.ModeOption mode="period" /><DatePicker.ModeOption mode="range" /></DatePicker.ModeSwitch><DatePicker.PeriodMode><DatePicker.Period.Root>{/* period panel */}</DatePicker.Period.Root></DatePicker.PeriodMode><DatePicker.RangeMode><DatePicker.Range.Root><DatePicker.Range.Calendar /></DatePicker.Range.Root></DatePicker.RangeMode></DatePicker.Content></DatePicker.Portal></DatePicker.Root>
API reference
Root props
| Prop | Type | Default | Description |
|---|---|---|---|
mode | "period" | "range" | — | Locks the picker to a single panel and hides the mode switch. Omitted, both panels are offered. Mount "period" on a surface built around period-over-period comparisons, so the range always names a month, quarter or year. |
disabled | boolean | — | Disables the trigger and the mode switch. |
Parts
Popover
| Part | Description |
|---|---|
DatePicker.ValueasChild?, format? | Formats the provider range: "All 2026", "Q3 2026", "Mar 2026", or "1 Jan – 31 Mar 26" when it matches no calendar period. |
DatePicker.AnchorasChild? | Anchors the popover to the trigger. |
DatePicker.TriggerasChild? | Opens the popover on the mode matching the current range. |
DatePicker.Portal | Renders content outside clipping ancestors. |
DatePicker.ContentasChild? | Modal popover content, carrying the active mode as `data-mode`. |
Mode switch
| Part | Description |
|---|---|
DatePicker.ModeSwitchasChild? | Accessible group wrapping the two mode options. Renders nothing while Root's mode prop locks the panel. |
DatePicker.ModeOptionmode, asChild? | Switches to "period" or "range", defaulting to the labels Period and Custom. Reflects the active mode as aria-pressed and data-active. |
DatePicker.PeriodMode | Renders its children only while the period panel is active. |
DatePicker.RangeMode | Renders its children only while the custom-range panel is active. |
Panels
| Part | Description |
|---|---|
DatePicker.Period.* | The period panel compound: Root, Group, YearOption, QuarterOption, MonthOption, PreviousYear, DisplayYear, and NextYear. Root takes min, max, and disabled. |
DatePicker.Range.* | The custom-range panel compound: Root and Calendar. Root takes min, max, and disabled; the calendar picks a range in a three-click cycle. |
Hook
| Part | Description |
|---|---|
DatePicker.useDatePicker() | Returns the active mode, the provider range, its exact period when it has one, open state, and the mode and open actions. |
Modes
Both panels are views of the same canonical range, so switching modes never writes to the provider. Move from Period to Custom and the calendar opens on the days the chosen period covers; move back and the period grid still shows that period selected.
Every date-driven component under the provider follows the committed range, unless it was detached with its own dateFrom/dateTo props. Cards that compare against a previous period can only do so period-over-period when the range names one, so a surface built around those comparisons should mount the picker with mode="period"; a custom range is compared against the same number of days immediately before it.
Opening lands on the mode that matches what is selected: an exact calendar year, quarter, or month opens on Period, anything else on Custom. A range picked in Custom that happens to be a whole month is an exact period, so the next open shows Period with that month selected. A fixed mode always opens on its own panel instead.
Composition
The nested roots keep their own props: pass min and max to the DatePicker.Period.Root and DatePicker.Range.Root you mount inside PeriodMode and RangeMode. DatePicker.Root takes only mode and disabled, since the bounds belong to the panel that enforces them.