Date-range input
SvDateRangeInput: a compact start/end field that opens a two-month range calendar with one-click presets (Today, Last 7 days, ...). Composes the same headless range engine as SvCalendar, and carries the shared editor contract - label, hint, error validation, dir (RTL) and localizable messages.
A live, editable Svelte 5 component example from the SvGrid gallery (Date & Time). Read the SvGrid UI component docs for the full API.
What this example shows
SvDateRangeInput - a compact start/end range FIELD (not a full inline calendar): a text field that opens a portalled two-month range calendar with one-click presets. It composes the same headless range engine SvCalendar uses, and carries the shared editor contract - label / hint / error validation, `dir` (RTL) and localizable `messages` - like every field editor.
Imports, features and API used
Imports: @svgrid/grid
Source code (283-daterange-input.svelte)
<script lang="ts">
/**
* SvDateRangeInput - a compact start/end range FIELD (not a full inline
* calendar): a text field that opens a portalled two-month range calendar with
* one-click presets. It composes the same headless range engine SvCalendar
* uses, and carries the shared editor contract - label / hint / error
* validation, `dir` (RTL) and localizable `messages` - like every field editor.
*/
import { SvDateRangeInput } from '@svgrid/grid'
import type { DateRangeValue, CalendarPreset } from '@svgrid/grid'
const startOfDay = (d: Date) => new Date(d.getFullYear(), d.getMonth(), d.getDate())
const addDays = (d: Date, n: number) => { const x = new Date(d); x.setDate(x.getDate() + n); return x }
const presets: CalendarPreset[] = [
{ label: 'Today', value: () => { const t = startOfDay(new Date()); return [t, t] } },
{ label: 'Last 7 days', value: () => [addDays(startOfDay(new Date()), -6), startOfDay(new Date())] },
{ label: 'Last 30 days', value: () => [addDays(startOfDay(new Date()), -29), startOfDay(new Date())] },
{ label: 'This month', value: () => { const n = new Date(); return [new Date(n.getFullYear(), n.getMonth(), 1), startOfDay(n)] } },
{ label: 'Year to date', value: () => [new Date(new Date().getFullYear(), 0, 1), startOfDay(new Date())] },
]
let basic = $state<DateRangeValue>([addDays(startOfDay(new Date()), -6), startOfDay(new Date())])
let reportRange = $state<DateRangeValue>(null)
let rtl = $state(false)
const fmt = new Intl.DateTimeFormat(undefined, { dateStyle: 'medium' })
const days = (r: DateRangeValue) => (r ? Math.round((+r[1] - +r[0]) / 86400000) + 1 : 0)
// A required field is "invalid" until a range is chosen.
const reportError = $derived(reportRange ? undefined : 'Please choose a reporting period')
</script>
<div class="wrap">
<header>
<h2>Date-range input</h2>
<p>
A field-shaped range picker: it reads back <code>[start, end]</code> and opens a
two-month range calendar with presets. Same headless engine as
<code>SvCalendar</code>, plus the shared editor contract (label, validation, RTL).
</p>
<label class="rtl-toggle"><input type="checkbox" bind:checked={rtl} /> Right-to-left</label>
</header>
<div class="grid">
<section>
<h3>Basic</h3>
<SvDateRangeInput
value={basic}
{presets}
firstDayOfWeek={1}
dir={rtl ? 'rtl' : undefined}
onChange={(r) => (basic = r)}
/>
<p class="out">
{#if basic}{fmt.format(basic[0])} → {fmt.format(basic[1])} <span class="muted">· {days(basic)} days</span>{:else}<span class="muted">No range</span>{/if}
</p>
</section>
<section>
<h3>As a form field (label + validation)</h3>
<SvDateRangeInput
value={reportRange}
label="Reporting period"
hint="Used for the exported summary"
required
invalid={!!reportError}
error={reportError}
{presets}
dir={rtl ? 'rtl' : undefined}
onChange={(r) => (reportRange = r)}
/>
</section>
<section>
<h3>Localized messages (French)</h3>
<SvDateRangeInput
value={basic}
formatString="dd/MM/yyyy"
locale="fr-FR"
placeholder="Choisir une periode"
dir={rtl ? 'rtl' : undefined}
messages={{ clear: 'Effacer', open: 'Ouvrir le calendrier', to: 'au', dialog: 'Choisir une periode' }}
onChange={(r) => (basic = r)}
/>
<p class="muted small">Every string (including the "to" separator) is overridable via <code>messages</code>.</p>
</section>
</div>
</div>
<style>
.wrap { padding: 20px; max-width: 900px; display: flex; flex-direction: column; gap: 18px; }
header h2 { margin: 0 0 4px; font-size: 20px; font-weight: 700; }
header p { margin: 0; color: var(--sg-muted, #64748b); font-size: 13.5px; line-height: 1.5; max-width: 680px; }
code { background: var(--sg-row-hover-bg, #eef2ff); padding: 1px 5px; border-radius: 5px; font-size: 12px; }
.rtl-toggle { display: inline-flex; align-items: center; gap: 6px; margin-top: 12px; font-size: 13px; font-weight: 600; color: var(--sg-muted, #64748b); }
.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 22px; }
section h3 { margin: 0 0 10px; font-size: 13px; text-transform: uppercase; letter-spacing: 0.03em; color: var(--sg-muted, #64748b); }
.out { margin: 10px 0 0; font-size: 14px; font-weight: 600; }
.muted { color: var(--sg-muted, #94a3b8); font-weight: 400; }
.small { font-size: 12px; line-height: 1.5; margin-top: 8px; }
</style>Related documentation
Related articles
- Real-Time Grids - Live WebSocket Updates in SvGrid - How to wire a high-frequency WebSocket feed into SvGrid without frame drops - covering stable row identity, RAF batching, and flash feedback done right.
- Building a Real-Time Trading Grid in Svelte - How to wire a WebSocket tick feed into SvGrid without dropping frames - rAF batching, stable row identity, flash animations, and the exact patterns that scale past 150 ticks per second.
- Building a Logistics / Fleet Tracking Grid in Svelte - How to build a live fleet operations grid with real-time telemetry updates, expandable trip history, and exception-first row styling.
More Date & Time examples
- Calendar - SvCalendar: a themeable month/year/decade calendar with single / range / week / multi selection, min-max, restricted + important dates and week numbers. The same component SvGrid mounts to edit a date cell - and usable standalone in any SvGrid app.
- Time picker - SvTimePicker: an analog clock-dial picker with 12/24-hour, minute snapping and hour to minute auto-switch. Drag the hand or click a number. The SvGrid time cell editor, usable standalone in any SvGrid app.
- Date-time picker - SvDateTimePicker: a formatted input plus a portalled dropdown with DATE / TIME tabs (calendar + clock). Type a masked value or pick it; invalid input reverts. min/max, nullable, 12/24-hour, spin buttons. The SvGrid datetime cell editor, standalone in any SvGrid app.
- Calendar - range + presets - SvCalendar as a date-range picker: selectionMode="range" with a one-click presets rail (Today, Last 7 days, This month, Year to date...), animated month navigation and mouse-wheel scrolling. Presets resolve relative to today. Same component, no extra dependency.
- Calendar - date of birth - SvCalendar as a date-of-birth picker: single selection with max clamped to today so future dates are blocked, opening on the decade (year) grid for fewer clicks to a birth year, with a live age readout. Same component SvGrid mounts to edit a date cell.