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
DateField is a compound component for single-date entry that combines typed input, optional calendar selection, and field-level constraints in one control. It is the field-first date-input layer, with the calendar acting as an optional picking aid rather than the primary abstraction.
Imports
import {
DateField,
DateFieldInput,
DateFieldCalendar,
DateFieldTriggerIconButton,
type DateFieldProps,
} from '@vega-ui/react';Exported Types
DateFieldPropsDateFieldInputPropsDateFieldCalendarPropsDateFieldTriggerIconButtonProps
Minimal Composition
import {
CalendarContent,
CalendarDay,
CalendarDays,
CalendarHeader,
CalendarMonth,
CalendarMonthLabel,
CalendarMonths,
CalendarNextButton,
CalendarPrevButton,
CalendarViewButton,
CalendarViewButtonGroup,Required Parts
DateField: root state and formatting ownerDateFieldInput: typed date entry surface
Optional Parts
DateFieldTriggerIconButton: calendar trigger affordanceDateFieldCalendar: visual picker content, usually mounted inPopover
Composition Order
DateFieldDateFieldInputPopoverDateFieldTriggerIconButtonDateFieldCalendar
Variants
- Input-only versus input-plus-calendar composition
- Trigger-driven picker versus typed entry only
- Constrained state through
min,max, anddisabledDates
Edge Cases
- Locale, timezone, and serialization rules still belong to the consumer.
- Partial typed values are common during editing and should not be treated as final values.
- Overlay behavior should be tested inside dialogs, drawers, and scroll containers.
- The same business rule should drive typed validation and calendar blocking; they should not drift into two different policies.
Common Mistakes
- Passing
Dateobjects or display-format strings tomin/maxinstead of ISOYYYY-MM-DDstrings. - Assuming the field solves timezone policy by itself.
- Leaving the trigger icon button unlabeled in accessible flows.
- Treating
min,max, anddisabledDatesas visual hints instead of validation rules.
Examples
Basic
Basic: typed date with a calendar popover
A labelled field where users type a date or pick it in a popover calendar. defaultValue on the root is an ISO YYYY-MM-DD day; the input shows it in format, and the helper text tells users which format to type.
import {
CalendarContent,
CalendarDay,
CalendarDays,
CalendarHeader,
CalendarMonth,
CalendarMonthLabel,
CalendarMonths,
CalendarNextButton,
CalendarPrevButton,
CalendarViewButton,
CalendarViewButtonGroup,Controlled/Stateful
Controlled/Stateful: preset dates
value and onChangeValue on the root keep the ISO day in parent state. Buttons set it from outside and the input shows it in format; while the typed text is incomplete the value is ''.
import { useState } from 'react';
import {
Button,
CalendarContent,
CalendarDay,
CalendarDays,
CalendarHeader,
CalendarMonth,
CalendarMonthLabel,
CalendarMonths,
CalendarNextButton,
CalendarPrevButton,Controlled/Stateful: check-out starts after check-in
The check-in day drives the min of the check-out field. When check-in moves past an already typed check-out, the check-out is clamped to the new min and onChangeValue reports the clamped day, so the night count stays correct.
import { useState } from 'react';
import {
CalendarContent,
CalendarDay,
CalendarDays,
CalendarHeader,
CalendarMonth,
CalendarMonthLabel,
CalendarMonths,
CalendarNextButton,
CalendarPrevButton,
CalendarViewButton,Form/Integration
Form/Integration: submitting an ISO date
DateFieldInput is a native <input>: with a name it would submit the typed text, for example 15.01.2026. Here onChangeValue mirrors the ISO day into a hidden input, so FormData gets 2026-01-15. required and pattern block an empty or incomplete date, 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: date field inside a dialog
The calendar popover opens above the dialog that contains the field. The form uses method='dialog', so a valid submit closes the dialog.
import { CSSProperties } from 'react';
import { XIcon } from '@vega-ui/icons';
import {
Button,
CalendarContent,
CalendarDay,
CalendarDays,
CalendarHeader,
CalendarMonth,
CalendarMonthLabel,
CalendarMonths,
CalendarNextButton,Layout/Overlay: close the calendar after a pick
The popover stays open after a pick by default, so users can correct it. To close it on pick, control open on the Popover and close it from onChangeValue of DateFieldCalendar; navigating months does not call it.
import { useState } from 'react';
import {
CalendarContent,
CalendarDay,
CalendarDays,
CalendarHeader,
CalendarMonth,
CalendarMonthLabel,
CalendarMonths,
CalendarNextButton,
CalendarPrevButton,
CalendarViewButton,Error
Error: required and incomplete dates
required and pattern are native constraints of the input: submit fires invalid while the field is empty or the date is incomplete. The handler picks the message from validity, error on the root and aria-invalid mark the field, and typing clears the error. The mask clamps every complete date to a real day, so checking completeness is enough.
import { FormEvent, useState } from 'react';
import {
Button,
CalendarContent,
CalendarDay,
CalendarDays,
CalendarHeader,
CalendarMonth,
CalendarMonthLabel,
CalendarMonths,
CalendarNextButton,
CalendarPrevButton,Disabled
Disabled: locked contract date
disabled on the root disables the input and the calendar trigger. The helper text explains why the date cannot be changed.
import {
CalendarContent,
CalendarDay,
CalendarDays,
CalendarHeader,
CalendarMonth,
CalendarMonthLabel,
CalendarMonths,
CalendarNextButton,
CalendarPrevButton,
CalendarViewButton,
CalendarViewButtonGroup,Disabled: disabled by a fieldset
A native <fieldset disabled> disables the input and the trigger button inside it, so the calendar cannot open either. The checkbox toggles the whole group without passing disabled to the field.
import { useState } from 'react';
import {
CalendarContent,
CalendarDay,
CalendarDays,
CalendarHeader,
CalendarMonth,
CalendarMonthLabel,
CalendarMonths,
CalendarNextButton,
CalendarPrevButton,
CalendarViewButton,Disabled: read-only date
readOnly on DateFieldInput keeps the value focusable, selectable and submitted with the form. The field has no readOnly of its own and DateFieldCalendar writes into the input even when it is read-only, so leave the calendar trigger out.
import { DateField, DateFieldInput, HelperText, Label } from '@vega-ui/react';
export default function ReadOnlyDate() {
return (
<div style={{ display: 'grid', gap: 'var(--spacing-3)', width: '100%', maxWidth: 280 }}>
<Label htmlFor='account-created'>Account created</Label>
<DateField format='dd.MM.yyyy' separator='.' defaultValue='2024-09-02'>
<DateFieldInput id='account-created' name='accountCreated' readOnly aria-describedby='account-created-hint' />
</DateField>
<HelperText id='account-created-hint'>Set by the system. The value is still submitted with the form.</HelperText>
</div>
);Edge
Edge: typed dates are clamped
A typed day past the end of the month is clamped to the month length, so 31.02.2026 becomes 28.02.2026. A complete date outside min and max is replaced by the nearest bound, so 05.01.2026 becomes 10.01.2026. The calendar disables the same days.
import { useState } from 'react';
import {
CalendarContent,
CalendarDay,
CalendarDays,
CalendarHeader,
CalendarMonth,
CalendarMonthLabel,
CalendarMonths,
CalendarNextButton,
CalendarPrevButton,
CalendarViewButton,Edge: weekends unavailable
disabledDates takes ISO days or a function. It applies only to the calendar: a typed weekend is accepted, so the submit handler checks the same isWeekend rule and shows an error.
import { FormEvent, useState } from 'react';
import {
Button,
CalendarContent,
CalendarDay,
CalendarDays,
CalendarHeader,
CalendarMonth,
CalendarMonthLabel,
CalendarMonths,
CalendarNextButton,
CalendarPrevButton,Edge: calendar popup in another locale
locale sets month and weekday names and the first day of the week in the calendar. The typed format still comes from format, and the labels of the trigger and month buttons are yours to translate.
import {
CalendarContent,
CalendarDay,
CalendarDays,
CalendarHeader,
CalendarMonth,
CalendarMonthLabel,
CalendarMonths,
CalendarNextButton,
CalendarPrevButton,
CalendarViewButton,
CalendarViewButtonGroup,Anatomy
Overview
DateField is a compound component that coordinates typed date entry, optional calendar selection, and shared field state under one root.
Required Parts
DateField
Required. Owns date parsing, formatting, disabled-date rules, and shared field state.
DateFieldInput
Required. Provides the typed date input surface.
Optional Parts
DateFieldTriggerIconButton
Optional trigger affordance for opening a calendar overlay.
DateFieldCalendar
Optional visual date 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 DateField.
Composition Order
DateFieldDateFieldInputPopoverDateFieldTriggerIconButtonDateFieldCalendarCalendarHeaderandCalendarContentwith the calendar views
Valid Composition Patterns
import {
CalendarContent,
CalendarDay,
CalendarDays,
CalendarHeader,
CalendarMonth,
CalendarMonthLabel,
CalendarMonths,
CalendarNextButton,
CalendarPrevButton,
CalendarViewButton,
CalendarViewButtonGroup,Invalid Composition Patterns
DateFieldInput outside DateField
This breaks shared formatting and value synchronization.
Calendar trigger without an actual calendar overlay
The button suggests a picker flow that does not exist.
Treating calendar constraints as presentation-only
min, max, and disabledDates should stay aligned with real validation rules.