Vize

Date Range Picker

Accessible, unstyled date range picker: start/end DateFields plus a popover RangeCalendar.

Package @vizejs/ui/date-range-picker
Maturity stable
Own the source vize lib pull date-range-picker
Requires context, controllable-state, date-field, id, popover, range-calendar
Aliases range picker, booking dates, check-in check-out
Covers React Aria DateRangePicker, Reka UI DateRangePicker, WAI-ARIA APG date picker dialog

Usage

import { DateRangePicker, DateRangePickerRoot, DateRangePickerCalendar, DateRangePickerContent, DateRangePickerField, DateRangePickerTrigger, DateRangePickerArrow, DateRangePickerGrid, DateRangePickerHeading, DateRangePickerMonthSelect, DateRangePickerNext, DateRangePickerPrev, DateRangePickerYearSelect } from "@vizejs/ui/date-range-picker";

Or copy the source into your project with vize lib pull date-range-picker (see Source Distribution).

API

DateRangePicker

Source: src/families/date-time/date-range-picker/date-range-picker-root.vue

Props

Prop Type Default Description
id string | null undefined Consumer-owned base id; nullish values use a deterministic fallback.
modelValue DateRange | null undefined Controlled range; undefined selects uncontrolled mode and null clears.
defaultValue DateRange | null null Initial uncontrolled range.
open boolean undefined Controlled popover open state; undefined selects uncontrolled mode.
defaultOpen boolean false Initial uncontrolled open state.
modal boolean false Make outside content inert and contain focus while open.
min PlainDate | null undefined Earliest selectable date, inclusive.
max PlainDate | null undefined Latest selectable date, inclusive.
isDateUnavailable DateMatcher undefined Predicate for dates that cannot be selected.
locale string undefined BCP 47 locale for the field and calendar; defaults to the nearest LocaleProvider.
dir "ltr" | "rtl" undefined Text direction; defaults to the nearest LocaleProvider.
today PlainDate | null undefined Explicit current date for the calendar; the SSR-safe way to mark today.
now DateTimeNow undefined Injectable clock evaluated during setup on server and client.
timeZone string undefined IANA time zone used with now and host clocks.
disabled boolean false Disable the field, trigger, and calendar.
readOnly boolean false Lock the value while the calendar stays browsable.
required boolean false Mark the field as required.
startName string undefined Hidden input name that submits the ISO start date with forms.
endName string undefined Hidden input name that submits the ISO end date with forms.
allowNonContiguousRanges boolean false Allow committed ranges to span unavailable dates.
closeOnSelect boolean true Close the popover after a calendar selection.

Events

Event Payload Description
update:modelValue [value: DateRange | null] Fired when the picker requests a new controlled range.
change [value: DateRange | null, previous: DateRange | null, nativeEvent: Event | null] Fired after a distinct committed range with the previous range and triggering event.
update:open [value: boolean] Fired when the picker requests a new controlled open state.
open-change [value: boolean, previous: boolean, nativeEvent: Event | null] Fired after any distinct open-state request.

Slots

Slot Slot props Description
default DateRangePickerSlotState Picker composition: start/end DateRangePickerField, trigger, content, and DateRangePickerCalendar.

Exposed

Member Type Description
value —
open —
disabled —
readOnly —
state —
setValue —
setOpen —

DateRangePickerRoot

Source: src/families/date-time/date-range-picker/date-range-picker-root.vue

Props

Prop Type Default Description
id string | null undefined Consumer-owned base id; nullish values use a deterministic fallback.
modelValue DateRange | null undefined Controlled range; undefined selects uncontrolled mode and null clears.
defaultValue DateRange | null null Initial uncontrolled range.
open boolean undefined Controlled popover open state; undefined selects uncontrolled mode.
defaultOpen boolean false Initial uncontrolled open state.
modal boolean false Make outside content inert and contain focus while open.
min PlainDate | null undefined Earliest selectable date, inclusive.
max PlainDate | null undefined Latest selectable date, inclusive.
isDateUnavailable DateMatcher undefined Predicate for dates that cannot be selected.
locale string undefined BCP 47 locale for the field and calendar; defaults to the nearest LocaleProvider.
dir "ltr" | "rtl" undefined Text direction; defaults to the nearest LocaleProvider.
today PlainDate | null undefined Explicit current date for the calendar; the SSR-safe way to mark today.
now DateTimeNow undefined Injectable clock evaluated during setup on server and client.
timeZone string undefined IANA time zone used with now and host clocks.
disabled boolean false Disable the field, trigger, and calendar.
readOnly boolean false Lock the value while the calendar stays browsable.
required boolean false Mark the field as required.
startName string undefined Hidden input name that submits the ISO start date with forms.
endName string undefined Hidden input name that submits the ISO end date with forms.
allowNonContiguousRanges boolean false Allow committed ranges to span unavailable dates.
closeOnSelect boolean true Close the popover after a calendar selection.

Events

Event Payload Description
update:modelValue [value: DateRange | null] Fired when the picker requests a new controlled range.
change [value: DateRange | null, previous: DateRange | null, nativeEvent: Event | null] Fired after a distinct committed range with the previous range and triggering event.
update:open [value: boolean] Fired when the picker requests a new controlled open state.
open-change [value: boolean, previous: boolean, nativeEvent: Event | null] Fired after any distinct open-state request.

Slots

Slot Slot props Description
default DateRangePickerSlotState Picker composition: start/end DateRangePickerField, trigger, content, and DateRangePickerCalendar.

Exposed

Member Type Description
value DateRange | null Committed range, or null until both endpoints are known.
open boolean Whether the calendar popover is open.
disabled boolean Whether the picker is disabled.
readOnly boolean Whether the value is locked while the calendar can still be browsed.
state PickerOpenState Stable open-state token.
setValue (value: DateRange | null) => boolean Request a range; returns whether it differs.
setOpen (value: boolean) => boolean Request an open state; returns whether it differs.

DateRangePickerCalendar

Source: src/families/date-time/date-range-picker/date-range-picker-calendar.vue

Props

Prop Type Default Description
numberOfMonths number 1 Number of consecutive months rendered.
pagedNavigation boolean false Move month controls by numberOfMonths.
fixedWeeks boolean false Always render six week rows per month.
weekStartsOn Weekday undefined First day of week (0 = Sunday); defaults to the locale preference.
weekdayFormat CalendarWeekdayFormat "short" Weekday column label width.
calendar string undefined Intl calendar used for display labels only.
numberingSystem string undefined Intl numbering system for labels.
ariaLabel string undefined Accessible name for the calendar group.

Slots

Slot Slot props Description
default CalendarSlotState Range calendar composition; defaults to a header plus one grid per month.

DateRangePickerContent

Source: src/families/date-time/date-range-picker/date-range-picker-content.vue

Props

Prop Type Default Description
placement Placement "bottom-start" Preferred placement before collision handling.
initialFocus () => HTMLElement | null | undefined undefined Initial focus target; defaults to the roving calendar day.
ariaLabel string undefined Accessible dialog name.
ariaLabelledby string undefined Ids that label the dialog.

Slots

Slot Slot props Description
default Record<string, never> Popover body, typically DateRangePickerCalendar.

DateRangePickerField

Source: src/families/date-time/date-range-picker/date-range-picker-field.vue

Props

Prop Type Default Description
boundary (required) DateRangeBoundary undefined (required) Range endpoint this field edits.
placeholderValue PlainDate | null undefined Date whose segments seed arrow-key stepping from empty; defaults to the picker today or host date.
placeholders FieldSegmentPlaceholders { year: "yyyy", month: "mm", day: "dd" } Placeholder text for empty segments.
emptyText string "Empty" Text announced for empty segments.
ariaLabel string undefined Accessible name for the segment group.
ariaLabelledby string undefined Ids that label the segment group.
ariaDescribedby string undefined Ids that describe the group and every segment.
ariaErrormessage string undefined Id of the validation message used while invalid.
ariaInvalid boolean false Force the invalid state.

Slots

Slot Slot props Description
default DateFieldSlotState Extra content after the segments, typically the picker trigger after the end field. Receives field state.
segment FieldSegmentState Segment content. Receives the segment state; defaults to its text.

Exposed

Member Type Description
focus —

DateRangePickerTrigger

Source: src/families/overlays/popover/popover-trigger.vue

Props

Prop Type Default Description
type "button" | "reset" | "submit" "button" Native button submission behavior.
disabled boolean false Remove the trigger from activation and sequential keyboard focus.
ariaLabel string undefined Accessible name when no visible label supplies one.

Events

Event Payload Description
click [nativeEvent: MouseEvent] Fired before the trigger toggles the popover. Call preventDefault() to keep state unchanged.

Slots

Slot Slot props Description
default PopoverSlotState Trigger contents. Receives the current Popover state and trigger availability.

Exposed

Member Type Description
element Readonly<ShallowRef<HTMLElement | null>> Template ref to the rendered root element.
focus —

DateRangePickerArrow

Source: src/families/overlays/popover/popover-arrow.vue

Slots

Slot Slot props Description
default PopoverArrowSlotState Decorative arrow contents. Receives coordinates for optional custom drawing.

Exposed

Member Type Description
element Readonly<ShallowRef<HTMLElement | null>> Template ref to the rendered root element.
x —
y —

DateRangePickerGrid

Source: src/families/date-time/calendar/calendar-grid.vue

Props

Prop Type Default Description
monthIndex number 0 Zero-based index of the visible month this grid renders.
showWeekNumbers boolean false Render a leading row header with the ISO 8601 week number of each row.
weekNumberLabel string "Wk" Visible week-number column header.
weekNumberHeader string "Week" Full week-number column header used as abbr.

Slots

Slot Slot props Description
weekday CalendarWeekdaySlotState Weekday column header content. Receives the weekday, its labels, and column index.
weekNumber CalendarWeekNumberSlotState Week-number row header content. Receives the ISO week and the row's days.
day CalendarDayState Day button content. Receives the complete day state; defaults to the localized day number.

DateRangePickerHeading

Source: src/families/date-time/calendar/calendar-heading.vue

Slots

Slot Slot props Description
default CalendarHeadingSlotState Heading content. Receives the localized heading and visible months.

DateRangePickerMonthSelect

Source: src/families/date-time/calendar/calendar-month-select.vue

Props

Prop Type Default Description
ariaLabel string "Month" Accessible name of the native select.

Events

Event Payload Description
change [month: number, nativeEvent: Event] Fired after the user picks a month, with the ISO month number.

DateRangePickerNext

Source: src/families/date-time/calendar/calendar-next.vue

Props

Prop Type Default Description
unit CalendarNavigationUnit "month" Whether the control pages by month (or numberOfMonths when paged) or by year.
ariaLabel string undefined Accessible name; defaults to "Next month" or "Next year".

Events

Event Payload Description
click [nativeEvent: MouseEvent] Fired before navigation. Call preventDefault() to keep the view unchanged.

Slots

Slot Slot props Description
default CalendarNavigationSlotState Control content. Receives the unit and whether navigation is possible.

DateRangePickerPrev

Source: src/families/date-time/calendar/calendar-prev.vue

Props

Prop Type Default Description
unit CalendarNavigationUnit "month" Whether the control pages by month (or numberOfMonths when paged) or by year.
ariaLabel string undefined Accessible name; defaults to "Previous month" or "Previous year".

Events

Event Payload Description
click [nativeEvent: MouseEvent] Fired before navigation. Call preventDefault() to keep the view unchanged.

Slots

Slot Slot props Description
default CalendarNavigationSlotState Control content. Receives the unit and whether navigation is possible.

DateRangePickerYearSelect

Source: src/families/date-time/calendar/calendar-year-select.vue

Props

Prop Type Default Description
from number undefined First listed year; defaults to the min year or ten years before the view.
to number undefined Last listed year; defaults to the max year or ten years after the view.
ariaLabel string "Year" Accessible name of the native select.

Events

Event Payload Description
change [year: number, nativeEvent: Event] Fired after the user picks a year.

Behavior

Normative state x input -> outcome table for the DateRangePicker compound (@vizejs/ui/date-range-picker): date-range-picker-root.vue, date-range-picker-field.vue (one per boundary), date-range-picker-content.vue, and date-range-picker-calendar.vue, with DateRangePickerTrigger re-exporting PopoverTrigger. Popover, field, and range-calendar rules follow their own contracts. Every row is proven by the named test.

# State Input Outcome Proven by
Q1 closed trigger / two day activations the popover opens focused on today, the range commits in order, the popover closes, and both fields plus startName/endName inputs update renders start and end fields and commits a two-click calendar range
Q2 complete range clear one field / type it back clearing an endpoint commits null but keeps the other draft; typing it back commits an ordered range even when entered reversed editing one field keeps a draft endpoint until both are known and orders the range
Q3 imperative expose / disabled setValue updates both fields and the open calendar; setValue(null) empties them; disabled pickers disable the trigger exposes imperative range and open control and respects disabled
Q4 SSR/hydration closed and open requests byte-identical markup in both states; an open range picker hydrates silently renders byte-identical closed and open range picker markup across SSR requests, hydrates an open range picker without mismatches

Root data: data-vize-ui="date-range-picker", data-state, data-start, data-end, data-disabled, data-readonly. Each field root carries data-boundary.