SvDateRangeInput
A compact start/end field that opens a two-month range calendar with one-click
presets (Today, Last 7 days, This month, ...). Emits an inclusive [start, end]
tuple or null.
SvDateRangeInput composes the existing headless range engine: the popover is
just a <SvCalendar selectionMode="range">, so hover-preview, min/max,
restricted / important dates and keyboard all come for free. It carries the
shared editor contract (label, hint, error validation, size, RTL, localizable
messages) via SvField, exactly like the other field editors, and the popover
portals to <body> so it is never clipped by a scrolling grid.
Basic usage
<script lang="ts">
import { SvDateRangeInput } from '@svgrid/grid'
let range = $state<[Date, Date] | null>(null)
</script>
<SvDateRangeInput
value={range}
formatString="yyyy-MM-dd"
months={2}
onChange={(v) => (range = v)}
/>
Props
SvDateRangeInput extends SvEditorProps (disabled, readonly, required,
invalid, error, label, hint, size, dir, name, id, ariaLabel).
Its own props:
| Prop | Type | Default | Description |
|---|---|---|---|
value |
DateRangeValue |
null |
Inclusive [start, end] range, or null. |
onChange |
(value: DateRangeValue) => void |
- | Fires with the new range (or null when cleared). |
formatString |
string |
yyyy-MM-dd |
Display format for each end (token engine). |
min / max |
DateLike | null |
null |
Selectable bounds. |
months |
number |
2 |
Number of month panels shown side by side. |
firstDayOfWeek |
number |
0 |
0 = Sunday .. 6 = Saturday. |
weekNumbers |
boolean |
false |
Show the calendar's week-number column. |
locale |
string |
navigator | BCP-47 locale for names and formatting. |
placeholder |
string |
Select date range |
Empty-field placeholder. |
presets |
ReadonlyArray<CalendarPreset> |
- | Quick shortcuts shown in the calendar's side rail. |
animate |
boolean | slide | fade |
false |
Animate the calendar's month navigation. |
autoOpen |
boolean |
false |
Open the popover as soon as the field is focused. |
Helper types
DateRangeValue = [Date, Date] | null- an inclusive start/end tuple.CalendarPreset = { label: string; value: Date | number | string | readonly [start, end] | (() => ...) }- pass a function for "today"-relative shortcuts that resolve at click time.
Patterns
Preset shortcuts
Presets appear in a side rail on the calendar; function values resolve relative to today at click time, so "Last 7 days" is always correct:
<SvDateRangeInput
presets={[
{ label: 'Last 7 days', value: () => [addDays(new Date(), -6), new Date()] },
{ label: 'This month', value: () => [startOfMonth(new Date()), new Date()] },
]}
onChange={(v) => (range = v)}
/>
Bounded ranges
Pass min / max to keep the selection inside an allowed window - out-of-range
days render disabled in the popover calendar:
<SvDateRangeInput min={new Date(2024, 0, 1)} max={new Date()} onChange={(v) => (range = v)} />
Labelled form field
Because it carries the editor contract, label, hint, and validation wire up
like any other field editor:
<SvDateRangeInput
label="Reporting period"
hint="Both ends inclusive"
required
size="lg"
onChange={(v) => (range = v)}
/>
Two-way bound booking range
Keep the tuple in your own $state and derive from it - here a night count for a
booking. min={new Date()} blocks past check-in dates:
<script lang="ts">
import { SvDateRangeInput, type DateRangeValue } from '@svgrid/grid'
let stay = $state<DateRangeValue>(null)
const nights = $derived(stay ? Math.round((+stay[1] - +stay[0]) / 86400000) : 0)
</script>
<SvDateRangeInput
label="Check-in / check-out"
value={stay}
min={new Date()}
months={2}
onChange={(v) => (stay = v)}
/>
<p>{nights} night(s)</p>
Tip: the range is inclusive and both ends are normalized to start-of-day, so subtracting the two timestamps gives whole nights without time-of-day drift.
Accessibility
- Built on
SvField, solabel,hint, anderrorare wired viafor/aria-describedby;invalidsetsaria-invalid. - The read-only field exposes
aria-haspopup="dialog"andaria-expanded;ArrowDown(or Alt+ArrowDown) opens the popover,Escapecloses it. - The popover is a
role="dialog"containing the full SvCalendar keyboard model for range selection. disabled/readonlyblock interaction;dir="rtl"mirrors the layout.
See also
- Date & time overview - the whole family at a glance.
- SvCalendar - the range calendar it wraps.
- SvDateTimePicker - the single date + time sibling.