import {
CalendarContent,
CalendarDay,
CalendarDays,
CalendarHeader,
CalendarMonth,
CalendarMonthLabel,
CalendarMonths,
CalendarNextButton,
CalendarPrevButton,
CalendarViewButton,
CalendarViewButtonGroup,- Browser support
- Newly available 2024
- Chrome 125
- Edge 125
- Firefox 128
- Safari 18
- Safari on iOS 18
- Bundle size
Summary
DateRangeField is a compound component for connected start and end date entry that combines typed range input, optional calendar selection, and shared range validation. It is the field-first range layer when one business concept owns both dates.
Imports
import {
DateRangeField,
DateRangeFieldInput,
DateRangeFieldCalendar,
DateRangeFieldTriggerIconButton,
type DateRangeFieldProps,
} from '@vega-ui/react';Exported Types
DateRangeFieldPropsDateRangeFieldInputPropsDateRangeFieldCalendarPropsDateRangeFieldTriggerIconButtonProps
Minimal Composition
import {
CalendarContent,
CalendarDay,
CalendarDays,
CalendarHeader,
CalendarMonth,
CalendarMonthLabel,
CalendarMonths,
CalendarNextButton,
CalendarPrevButton,
CalendarViewButton,
CalendarViewButtonGroup,Required Parts
DateRangeField: root state and range-format ownerDateRangeFieldInput: typed range entry surface
Optional Parts
DateRangeFieldTriggerIconButton: calendar trigger affordanceDateRangeFieldCalendar: visual range picker content, usually mounted inPopover
Composition Order
DateRangeFieldDateRangeFieldInputPopoverDateRangeFieldTriggerIconButtonDateRangeFieldCalendar
Variants
- Input-only versus input-plus-calendar composition
- Compact filter range versus fuller booking range flows
- Constraint-driven range state through
min,max, anddisabledDates
Edge Cases
- Partial ranges are expected during editing and need explicit handling.
- Range semantics such as inclusive booking days or reporting cutoffs belong to the consumer.
- Overlay behavior should be tested inside filters, drawers, and other stacked layouts.
- Typed range parsing, visual blocked days, and final business validation should stay aligned instead of becoming separate rule systems.
Common Mistakes
- Passing
Dateobjects or display-format strings tomin/maxinstead of ISOYYYY-MM-DDstrings. - Treating the start and end date as unrelated values.
- Leaving the meaning of the range ambiguous in labels or helper text.
- Relying on visual calendar blocking without matching validation rules.
Examples
Basic
Basic: booking range with a calendar popover
One field for a start and an end date: type both, or pick two days in the calendar. defaultValue is a [start, end] pair of ISO days. Without rangeSeparator the dates are joined by an en dash between non-breaking spaces.
import {
CalendarContent,
CalendarDay,
CalendarDays,
CalendarHeader,
CalendarMonth,
CalendarMonthLabel,
CalendarMonths,
CalendarNextButton,
CalendarPrevButton,
CalendarViewButton,
CalendarViewButtonGroup,Controlled/Stateful
Controlled/Stateful: number of nights
value and onChangeValue on the root keep the [start, end] pair in parent state, so the night count and the price come straight from ISO days. Each side is '' until it is a complete date.
import { useState } from 'react';
import {
CalendarContent,
CalendarDay,
CalendarDays,
CalendarHeader,
CalendarMonth,
CalendarMonthLabel,
CalendarMonths,
CalendarNextButton,
CalendarPrevButton,
CalendarViewButton,Controlled/Stateful: preset ranges
Buttons set the controlled range from outside, and the input shows it in format. The presets are computed from today's date in the click handler, so the page renders the same on the server.
import { useState } from 'react';
import {
Button,
CalendarContent,
CalendarDay,
CalendarDays,
CalendarHeader,
CalendarMonth,
CalendarMonthLabel,
CalendarMonths,
CalendarNextButton,
CalendarPrevButton,Form/Integration
Form/Integration: report filter with two API parameters
onChangeValue mirrors the range into two hidden inputs, so FormData holds from and to as ISO days instead of the typed text. required and a pattern for the full range block an empty or one-sided period, and the reset button restores defaultValue.
import { FormEvent, useState } from 'react';
import {
Button,
CalendarContent,
CalendarDay,
CalendarDays,
CalendarHeader,
CalendarMonth,
CalendarMonthLabel,
CalendarMonths,
CalendarNextButton,
CalendarPrevButton,Layout/Overlay
Layout/Overlay: range in a filter drawer
The calendar popover opens above the drawer that contains the field. The drawer form uses method='dialog': submitting applies the filter and closes the drawer.
import { CSSProperties, useState } from 'react';
import { XIcon } from '@vega-ui/icons';
import {
Button,
CalendarContent,
CalendarDay,
CalendarDays,
CalendarHeader,
CalendarMonth,
CalendarMonthLabel,
CalendarMonths,
CalendarNextButton,Error
Error: both dates required
A single date is a valid entry for the field. Native required and a pattern for the full range make submit fire invalid until both dates are complete; the handler picks the message from validity, and typing clears it.
import { FormEvent, useState } from 'react';
import {
Button,
CalendarContent,
CalendarDay,
CalendarDays,
CalendarHeader,
CalendarMonth,
CalendarMonthLabel,
CalendarMonths,
CalendarNextButton,
CalendarPrevButton,Disabled
Disabled: locked billing period
disabled on the root disables the input and the calendar trigger, and the helper text explains why.
import {
CalendarContent,
CalendarDay,
CalendarDays,
CalendarHeader,
CalendarMonth,
CalendarMonthLabel,
CalendarMonths,
CalendarNextButton,
CalendarPrevButton,
CalendarViewButton,
CalendarViewButtonGroup,Edge
Edge: reversed and out-of-range dates
A range typed backwards is swapped, so 15.01.2026 - 10.01.2026 becomes 10.01.2026 - 15.01.2026. Each date is clamped to min and max and to the length of its month; the readout shows the resulting pair.
import { useState } from 'react';
import {
CalendarContent,
CalendarDay,
CalendarDays,
CalendarHeader,
CalendarMonth,
CalendarMonthLabel,
CalendarMonths,
CalendarNextButton,
CalendarPrevButton,
CalendarViewButton,Edge: blackout dates
disabledDates blocks days in the calendar, but a typed range or a picked range around the blocked days still reaches the value. The submit handler checks whether the range covers a blackout day and shows an error.
import { FormEvent, useState } from 'react';
import {
Button,
CalendarContent,
CalendarDay,
CalendarDays,
CalendarHeader,
CalendarMonth,
CalendarMonthLabel,
CalendarMonths,
CalendarNextButton,
CalendarPrevButton,Anatomy
Overview
DateRangeField is a compound component that coordinates a connected start and end date through one field, optional calendar picker, and shared range rules.
Required Parts
DateRangeField
Required. Owns range parsing, formatting, and date constraint rules.
DateRangeFieldInput
Required. Provides the typed start-to-end range entry surface.
Optional Parts
DateRangeFieldTriggerIconButton
Optional trigger affordance for opening a calendar overlay.
DateRangeFieldCalendar
Optional visual range picker that should usually be mounted inside Popover.
Its children are the Calendar parts: CalendarHeader with CalendarPrevButton, CalendarViewButtonGroup (CalendarViewButton view='month' and view='year'), and CalendarNextButton, then CalendarContent with CalendarDays, CalendarMonths, and CalendarYears. The calendar takes locale and calendar from DateRangeField.
Composition Order
DateRangeFieldDateRangeFieldInputPopoverDateRangeFieldTriggerIconButtonDateRangeFieldCalendarCalendarHeaderandCalendarContentwith the calendar views
Valid Composition Patterns
import {
CalendarContent,
CalendarDay,
CalendarDays,
CalendarHeader,
CalendarMonth,
CalendarMonthLabel,
CalendarMonths,
CalendarNextButton,
CalendarPrevButton,
CalendarViewButton,
CalendarViewButtonGroup,Invalid Composition Patterns
Range input outside DateRangeField
This breaks coordinated parsing and range selection state.
Range picker without clear range semantics in surrounding copy
Users should not have to guess whether the range is inclusive, report-based, or booking-based.
Treating incomplete ranges as fully valid values
Start and end date flows need explicit handling while the field is partially filled.