Date Picker

Date Picker component enables users to enter a date either through text input or selecting a date from the Calendar dropdown.

Import#

import { DatePicker } from '@volue/wave-react';
// you may also access Date Picker's context via hook:
// import { useDatePickerContext } from '@volue/wave-react';

Date Picker is a compound component that consists of multiple parts:

  • DatePicker: The wrapper that contains all the parts of a date picker and provides context for its children.
  • DatePicker.TextInput: A Text Input that allows users to input date as text.
  • DatePicker.CalendarTrigger: The trigger that opens DatePicker.Calendar.
  • DatePicker.Calendar: The calendar that enables users to select and view dates. Composes Popover and Calendar components under the hood.
  • DatePicker.Clear: The button that clears the user selection.

Examples#

Basic#

By default, the DatePicker is uncontrolled and the calendar's initial view is set to current month.

Users can enter a date either through text input or open a calendar popover to select dates in a standard month grid.

By default, the expected text input format (as shown in the placeholder) is localised to the user's browser locale. DatePicker parses the text typed into the field internally and splits it into appropriate date segments according to the detected format.

DatePicker supports partial input and automatically detects incorrect input. If one of the date segments is invalid, it will fallback to the last valid segment value. This ensures that no extra effort is needed on the consumer side to handle input that cannot be converted into a date.

You can pass defaultValue for uncontrolled DatePicker.

Controlled#

You can easily make the DatePicker controlled, by passing your own state to value prop. onValueChange handler is called when the date value changes, allowing you to sync state.

The component returns dates in Date format or null to indicate no selection. You must take care of conversion to the desired format yourself.

For simple locale-respective date formatting we recommend using the native Intl API. useDateFormatter hook exported by Wave accepts same arguments as Intl.DateTimeFormat constructor and returns a memoized instance of it.

Alternatively you can use a date-management library such as date-fns, which has multiple utility functions including format.

With Form Field#

Use DatePicker with Form Field in order to enhance layout with a clear label. Optionally, you may want to connect helper text and/or validation feedback message to the DatePicker.

When using DatePicker without FormField.Label, be mindful to provide aria-label instead.

Validation#

Since DatePicker allows user to enter a date through a text input, it has to handle invalid user input, i.e. not meeting the expected date format or providing a date that falls out of min/max bounds.

By default, DatePicker attempts to parse the provided input into a valid Date object according to the expected format as shown in the placeholder. If that fails, the text field will highlight itself in red to provide visual cue that it needs correction. You can subscribe to the onError callback which is triggered when the input error changes and use the FormField.FeedbackMessage to communicate a detailed error message to the user.

onError callback provides a reason for the error which can be either an incorrect date or a date outside of the specified minDate or maxDate range.

Alternatively, you may want to prevent entering incorrect values through DatePicker.TextInput altogether. When shouldAutoCorrectInput is set to true, DatePicker will handle partial user input, automatically cap the input to the specified limits and revert to the last correct date after user typed an incorrect value. onError callback will not be fired as no error messaging is needed in that case.

Disabled state#

Pass isDisabled prop to the accompanying FormField and it will cascade down to the DatePicker.

You can also pass isDisabled prop directly to DatePicker.

Size#

As with other types of input controls, we offer the ability to change the size property. medium and small sizes are available, with the medium size used by default.

Min/max date#

It's possible to cap the date range that can be selected.

DatePicker.Calendar will display non-selectable dates as disabled and contrain the navigation forward/backward in time. Dates typed into DatePicker.TextInput that are out of specified limits will trigger onError callback or get automatically capped when shouldAutoCorrentInput is true.

If you don't supply a default date when using the minDate/maxDate props and today falls outside of the range limits it gets automatically constrained to either min or max.

When choosing range that spans over several years, calendar automatically displays Select Menus for month/year, to let the user more easily find the period they want to choose from without having to cycle through multiple months.

When only a subset of days within a month is available to choose from, both year/month selects and navigation buttons are not shown.

Date range#

DatePicker allows user to pick a single date, but date range selection can easily be implemented by using controlled "from" and "to" date pickers.

By using modifiers on the DatePicker.Calendar, we are able to visually highlight the selected date range in both pickers.

If you don't need the flexibility of manual date range input and the user is more likely to select a more narrow scope, it's possible to use a single range picker control by composing Popover, Button and Calendar components.

Displaying two months makes it easier for users to select date ranges that span across both.

Enforcing a locale#

If you want to enforce a locale, you can pass it as a prop. This will override the user's browser locale. locale property expects a date-fns locale object.

For example, to localize the calendar and text input format in German, import the locale object from date-fns and pass it to the component.

import { de } from 'date-fns/locale';
// import { enGB, nb, ... } from 'date-fns/locale';

Enforcing a time zone#

To change the time zone, pass IANA time zone identifier or a UTC offset to timeZone prop.

When working with time zones, make sure to use TZDate object from date-fns timezone utils instead of the native Date object.

import { TZDate } from '@date-fns/tz';

Custom trigger#

By leveraging individual parts of the DatePicker, it's possible to build custom solutions based on how you want the user to be able to select a date.

For example, a DatePicker without DatePicker.TextInput that uses Button displaying currently selected date as a DatePicker.CalendarTrigger. DatePicker.Clear is included in the calendar's footer to provide the ability to clear the active selection.


Accessibility features#

  • DatePicker provides deep keyboard interactions.

  • Necessary ARIA roles and attributes are provided to give directions to a screen reader user.


API Reference#

DatePicker#

Prop
Type
Default
defaultValue
Date
No default value
value
Date | null
No default value
onValueChange
function
No default value
minDate
Date | null
No default value
maxDate
Date | null
No default value
size
enum
"medium"
locale
Locale
No default value
timeZone
string
No default value
isDisabled
boolean
No default value
isRequired
boolean
No default value
shouldAutoCorrectInput
boolean
false
onError
function
No default value

DatePicker.TextInput#

In addition to the props below, you can pass Text Input props.

Prop
Type
Default
trailingVisual
React.ReactNode
No default value

DatePicker.CalendarTrigger#

Prop
Type
Default
as
enum
button
css
StitchesCss
No default value

DatePicker.Calendar#

In addition to the props below, you can pass Popover props and most of the Calendar props.

Prop
Type
Default
locale
Locale
No default value
timeZone
string
No default value
modifiers
DayModifiers
No default value

DatePicker.Clear#

In addition to the props below, you can pass Box props to control the spacing.

Prop
Type
Default
as
enum
button
css
StitchesCss
No default value