Date & Time
DateRangePicker
Start and end segmented inputs in one field, backed by a two-month range calendar. Constrain the span with minDays/maxDays and add per-endpoint time entry.
Playground
Experiment with different props in real-time.
07202026
07242026
Basic Usage
Bind a DateRange with start and end.
07202026
07242026
<script lang="ts">
import { DateRangePicker } from 'sv5ui';
import { today, getLocalTimeZone } from '@internationalized/date';
import type { DateRange } from 'bits-ui';
const now = today(getLocalTimeZone());
let value = $state<DateRange>({ start: now, end: now.add({ days: 4 }) });
</script>
<DateRangePicker bind:value />Day Constraints
Limit the length of the selected range.
mmddyyyy
mmddyyyy
<!-- Enforce a 3 to 10 night stay -->
<DateRangePicker minDays={3} maxDays={10} />Time Input
Set timeInput to add start and end time fields below the calendar.
mmddyyyy––––AM
mmddyyyy––––AM
<!-- Start and end time fields below the calendar -->
<DateRangePicker timeInput />Single Month
mmddyyyy
mmddyyyy
<!-- One month instead of the default two -->
<DateRangePicker numberOfMonths={1} />Min & Max
mmddyyyy
mmddyyyy
<script lang="ts">
import { DateRangePicker } from 'sv5ui';
import { today, getLocalTimeZone } from '@internationalized/date';
const now = today(getLocalTimeZone());
</script>
<DateRangePicker minValue={now} maxValue={now.add({ months: 2 })} />Variants
mmddyyyy
mmddyyyy
mmddyyyy
mmddyyyy
mmddyyyy
mmddyyyy
mmddyyyy
mmddyyyy
<DateRangePicker variant="outline" />
<DateRangePicker variant="soft" />
<DateRangePicker variant="subtle" />
<DateRangePicker variant="ghost" />Sizes
mmddyyyy
mmddyyyy
mmddyyyy
mmddyyyy
mmddyyyy
mmddyyyy
<DateRangePicker size="xs" />
<DateRangePicker size="md" />
<DateRangePicker size="xl" />Form Field
The range submits as {name}-start and {name}-end hidden inputs.
mmddyyyy
mmddyyyy
Please pick a date range
<script lang="ts">
import { DateRangePicker, FormField } from 'sv5ui';
import type { DateRange } from 'bits-ui';
let range = $state<DateRange | undefined>(undefined);
const error = $derived(
range?.start && range?.end ? '' : 'Please pick a date range'
);
</script>
<FormField label="Stay dates" {error}>
<!-- Submits {name}-start and {name}-end hidden inputs -->
<DateRangePicker bind:value={range} name="stay" />
</FormField>UI Slots
Use the ui prop to override classes. Pass ui.calendarSlots to reach the calendar's own slots.
| Slot | Description |
|---|---|
root | The field wrapper |
field | The field container |
input | The start and end segmented inputs |
separator | The icon between the two inputs |
trigger | The calendar popover trigger button |
content | The popover content |
calendar | The two-month range calendar |
time | The time-input row (when timeInput is set) |
Props
| Prop | Type | Default |
|---|---|---|
value | DateRange | - |
onValueChange | (value) => void | - |
placeholder | DateValue | current date |
open | boolean | false |
minDays | number | - |
maxDays | number | - |
granularity | 'day' | 'hour' | 'minute' | 'second' | 'day' |
locale | string | 'en' |
minValue | DateValue | - |
maxValue | DateValue | - |
isDateDisabled | DateMatcher | - |
excludeDisabled | boolean | false |
timeInput | boolean | false |
closeOnRangeSelect | boolean | true |
numberOfMonths | number | 2 |
separatorIcon | string | 'lucide:minus' |
icon | string | 'lucide:calendar' |
variant | 'outline' | 'soft' | 'subtle' | 'ghost' | 'none' | 'outline' |
calendarVariant | 'solid' | 'outline' | 'soft' | 'subtle' | 'solid' |
color | ColorType | 'primary' |
size | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'md' |
disabled | boolean | false |
readonly | boolean | false |
required | boolean | false |
name | string | - |
ref | HTMLElement | null | null |
class | string | - |
ui | Record<Slot, Class> | - |