Date Picker
A date field with a calendar popover for selecting dates.
Features
- Full keyboard navigation
- Localization support
- Can be controlled or uncontrolled
- Focus is fully managed
- Supports both date and date-time formats
Overview
The Date Picker is a combination of the Date Field , Calendar , and Popover . It's fully accessible, and works with all modern browsers & devices.
Anatomy
- Field: The element which contains the date segments
- Segment: An individual segment of the date (day, month, year, etc.)
- Label: The label for the date field
- Hidden Input: A hidden input element containing the value of the field
- Validation: The container for the validation message
- Calendar: The container of the months and days of the calendar
- Cell: A single date in the calendar
- Grid: A month in the calendar
- Previous Button: A button for navigating to the previous page of the calendar
- Next Button: A button for navigating to the next page of the calendar
- Heading: A visual heading for the calendar
- Trigger: The button which opens/closes the popover.
- Content: Contains the content within the popover
- Arrow: An optional arrow component
Scaffold a Date Picker
This section is designed to help you get started with the correct markup for a date picker. Since it's a combination of three other builders, there are a lot of working parts. This section will help you understand how to bring them all together, though it's highly recommended you read the docs for the Date Field , Calendar , and Popover builders as well.
Let's start by initializing our date picker using the createDatePicker
function and destructuring
the pieces we need:
Next, we can setup our field. Notice that in addition to the segments that we normally add to a Date Field , we also add a trigger button for the Popover .
Once that's in place, we can setup our calendar, which will be contained within the Popover 's content.
And with those pieces in place, we just need to add some styles and we have a fully functional date picker.
Placeholder
In this section, we'll learn about the placeholder props, which are used to change what type of value the field represents, and what day the calendar displays when no date is selected.
Set the Placeholder Date
The Date Picker has two placeholder props, placeholder
(controlled), and defaultPlaceholder
(uncontrolled), which are used to change how the field segments are rendered, and what is first
displayed in the calendar when no date is selected.
By default, the placeholder will be set to a CalendarDate
object with current date (and no time),
but you can override this by passing any DateValue
object to the defaultPlaceholder
prop.
Below, we'll set the placeholder to a CalendarDateTime
object representing February 1st, 2021.
Although we didn't include a time when instantiating the CalendarDateTime
object, the builder is
smart enough to know that the date picker should represent a date and a time, and will render the
appropriate segments.
When a time isn't included with a CalendarDateTime
object, the time will default to 00:00:00.000
on that date.
Values
The Date Picker has two value props, value
(controlled), and defaultValue
(uncontrolled), which
are used to determine what date the field is populated with, and what day is selected in the
calendar popover.
Setting a Default Value
To have a date selected by default, we can use either value prop. Below, we'll set the
defaultValue
to a CalendarDate
of January 11, 2024.
And as the example below demonstrates, the field is populated with the date, and the calendar has that date selected.
Using the Value Store
The value
store returned from the createDatePicker
function is a writable store containing a
DateValue
object with whatever type of date was passed via the placeholder or value props.
You can use this value to display the selected date in your markup somewhere, or to perform some action when the value changes.
Usage with Forms
It's likely that you'll want to use the Date Picker in an HTML form, and to do that, you'll want to
use the hiddenInput
element that's returned from the createDatePicker
function.
The hiddenInput
element is a hidden input element that contains an ISO 8601 string of the value of
the field, and is updated whenever the value changes.
If you do plan on using the hiddenInput
, ensure that you set the name
prop, as it will be used
as the name of the input element.
Appearance & Behavior
Fixed Weeks
By default, the calendar will render as many weeks as it needs to display all of the days in that
month. However, if you want the calendar to always render the maximum number of weeks (6), you can
set the fixedWeeks
prop to true
.
Now, regardless of the month, the calendar will always render 6 weeks, so there isn't a jump in the UI when navigating between different sized months.
Multiple Months
By default, the calendar will display one month, but you can change this by setting the
numberOfMonths
prop.
Paged Navigation
By default, when the calendar has more than one month, the previous and next buttons will shift the
calendar forward or backward by one month. However, you can change this behavior by setting the
pagedNavigation
prop to true
, which will shift the calendar forward or backward by the number of
months being displayed.
Localization
The date picker will automatically format the content of the field & calendar according to the
locale
prop, which defaults to 'en-US', but can be changed to any locale supported by the
Intl.DateTimeFormat
constructor.
Prevent Deselection
By default, users can deselect a selected date without selecting another, by selecting the date
again. This results in the value
potentially being undefined
. If you'd like to disable this
behavior, you can set the preventDeselect
prop to true
, which will prevent the user from being
able to deselect dates.
Now the user is unable to deselect a date without selecting another in the calendar. Note, the user can still clear the field by deleting the value in the field, this only handles the calendar behavior.
Validation
Although possible to implement your own logic using change functions , the Date Picker provides a few props that make it a bit easier.
Unavailable Dates
An unavailable date is a date that is not selectable, but is still visible and focusable in the calendar.
You can pass a Matcher
function to the isDateUnavailable
prop, which will be used to determine
if a date is unavailable. The Matcher
function is called with a DateValue
object, and should
return a boolean indicating whether the date is unavailable.
The unavailable dates will have the data-unavailable
attribute set, which you can use to style
differently than the other dates.
Disabled Dates
Disabled dates are not selectable, nor are they focusable in the calendar. Keyboard navigation will skip over them entirely, and should be used for dates that have no meaning in the context of the calendar.
You can pass a Matcher
function to the isDateDisabled
prop, which will be used to determine if a
date is disabled. The Matcher
function is called with a DateValue
object, and should return a
boolean indicating whether the date is disabled.
In this example, we're disabling the first 10 days of each month.
Minimum & Maximum Values
While the isDateDisabled
prop is useful for more complex logic, the Date Picker also provides the
minValue
and maxValue
props, which are used to set the min and max selectable dates, which is
nice if you're just trying to limit the range of dates that can be selected.
If a date is before the minValue
, or after the maxValue
, it will be disabled.
API Reference
createDatePicker
The builder function used to create the date picker component.
Props
Prop | Default | Type / Description |
defaultValue | - | DateValue | undefined The default value for the date picker. When provided the |
value | - | Writable<DateValue | undefined> A writable store than can be used to control the value of the date picker from outside the builder. Useful if you want to sync the value of the date picker with another store used in your app. |
onValueChange | - | ChangeFn<DateValue | undefined> A function called when the value of the date picker changes. It receives a single argument, which is an object containing |
defaultPlaceholder | CalendarDate | DateValue The date that is used when the date picker is empty to determine what point in time the calendar should start at. |
placeholder | - | Writable<DateValue> A writable store that can be used to control the placeholder date from outside the builder. When this prop is provided, the |
onPlaceholderChange | - | ChangeFn<DateValue> A function called when the placeholder value changes. It receives a single argument, which is an object containing |
isDateUnavailable | - | Matcher | undefined A function that accepts a date and returns a boolean indicating whether the date is unavailable. |
minValue | - | DateValue | undefined The minimum date that can be selected. |
maxValue | - | DateValue | undefined The maximum date that can be selected. |
disabled | false | boolean Whether the calendar is disabled. |
readonly | false | boolean Whether the calendar is readonly. |
locale | 'en' | string The locale to use when formatting the date. |
preventDeselect | false | boolean Whether to prevent the user from deselecting the current value by pressing it. |
pagedNavigation | false | boolean Whether to use paged navigation for the calendar. |
weekStartsOn | 0 | 0 | 1 | 2 | 3 | 4 | 5 | 6 The day of the week the calendar starts on. 0 is Sunday, 6 is Saturday, etc. |
fixedWeeks | false | boolean Whether to always show 6 weeks in the calendar. |
calendarLabel | 'Event date' | string An accessible label for the calendar. |
ids | - | DatePickerIds Override the default ids used by the various elements within the date picker. |
Elements
Element | Description |
The container of the months and days of the calendar | |
A visual heading for the calendar | |
A grid representing a month of the calendar | |
A cell representing a single date in the calendar | |
A button which moves the calendar to the next page | |
A button which moves the calendar to the previous page | |
The element which contains the date segments | |
An individual segment of the date | |
The label for the date field | |
The element containing the validation message | |
The hidden input used to submit the value within a form |
States
State | Description |
value | A writable store which represents the current value of the calendar. |
months | A readable store containing month objects for each month in the calendar. |
weekdays | A readable store containing the days of the week, formatted to the |
headingValue | A readable store containing the heading for the calendar, formatted to the |
segmentValues | A writable store containing the current values of the date segments. |
segmentContents | A readable store used to dynamically render the date segments. |
segmentContentsObj | A readable store containing the current values of the date segments. |
placeholder | A writable store which represents the placeholder value of the calendar. |
isInvalid | A readable store which represents whether the calendar is invalid. |
Helpers
Helper | Description |
nextPage | A function that moves the calendar to the next page. |
prevPage | A function that moves the calendar to the previous page. |
nextYear | A function that moves the calendar to the next year. |
prevYear | A function that moves the calendar to the previous year. |
setYear | A function that sets the year of the calendar. |
setMonth | A function that sets the month of the calendar. |
isDateDisabled | A function that returns whether the given date is disabled. |
isDateUnavailable | A function that returns whether the given date is unavailable. |
isDateSelected | A function that returns whether the given date is selected. |
Options
Option | Description |
defaultValue | The default value for the date picker. When provided the |
onValueChange | A function called when the value of the date picker changes. It receives a single argument, which is an object containing |
defaultPlaceholder | The date that is used when the date picker is empty to determine what point in time the calendar should start at. |
onPlaceholderChange | A function called when the placeholder value changes. It receives a single argument, which is an object containing |
isDateUnavailable | A function that accepts a date and returns a boolean indicating whether the date is unavailable. |
minValue | The minimum date that can be selected. |
maxValue | The maximum date that can be selected. |
disabled | Whether the calendar is disabled. |
readonly | Whether the calendar is readonly. |
locale | The locale to use when formatting the date. |
preventDeselect | Whether to prevent the user from deselecting the current value by pressing it. |
pagedNavigation | Whether to use paged navigation for the calendar. |
weekStartsOn | The day of the week the calendar starts on. 0 is Sunday, 6 is Saturday, etc. |
fixedWeeks | Whether to always show 6 weeks in the calendar. |
calendarLabel | An accessible label for the calendar. |
ids | Override the default ids used by the various elements within the date picker. |
calendar
The container of the months and days of the calendar
Data Attributes
Data Attribute | Value |
[data-invalid] | Present when the calendar is invalid. |
[data-disabled] | Present when the calendar is disabled. |
[data-readonly] | Present when the calendar is readonly. |
[data-melt-calendar] | Present on all calendar elements. |
Custom Events
Event | Value |
m-keydown | (e: ) => void |
grid
A grid representing a month of the calendar
Data Attributes
Data Attribute | Value |
[data-disabled] | Present when the calendar is disabled. |
[data-melt-calendar-grid] | Present on all grid elements. |
cell
A cell representing a single date in the calendar
Data Attributes
Data Attribute | Value |
[data-disabled] | Present when the date is disabled. |
[data-selected] | Present when the date is selected. |
[data-value] | The ISO string value of the date. |
[data-unavailable] | Present when the date is unavailable. |
[data-today] | Present when the date is today. |
[data-outside-month] | Present when the date is outside the current month it is displayed in. |
[data-outside-visible-months] | Present when the date is outside the months that are visible on the calendar. |
[data-focused] | Present when the date is focused. |
[data-melt-calendar-cell] | Present on all cell elements. |
Custom Events
Event | Value |
m-click | (e: ) => void |
heading
A visual heading for the calendar
Data Attributes
Data Attribute | Value |
[data-invalid] | Present when the calendar is invalid. |
[data-disabled] | Present when the calendar is disabled. |
[data-melt-calendar-heading] | Present on all heading elements. |
prevButton
A button which moves the calendar to the previous page
Data Attributes
Data Attribute | Value |
[data-disabled] | Present when the calendar is disabled. |
[data-melt-calendar-prevButton] | Present on all prevButton elements. |
Custom Events
Event | Value |
m-click | (e: ) => void |
nextButton
A button which moves the calendar to the next page
Data Attributes
Data Attribute | Value |
[data-disabled] | Present when the calendar is disabled. |
[data-melt-calendar-nextButton] | Present on all nextButton elements. |
Custom Events
Event | Value |
m-click | (e: ) => void |
field
The element which contains the date segments
Data Attributes
Data Attribute | Value |
[data-invalid] | Present when the date field is invalid. |
[data-disabled] | Present when the date field is disabled. |
[data-melt-datefield-field] | Present on all field elements. |
segment
An individual segment of the date
Data Attributes
Data Attribute | Value |
[data-invalid] | Present when the field is invalid. |
[data-disabled] | Present when the field is disabled. |
[data-segment] | SegmentPart |
[data-melt-datefield-segment] | Present on all segment elements. |
Custom Events
Event | Value |
m-keydown | (e: ) => void |
m-focusout | (e: ) => void |
m-click | (e: ) => void |
label
The label for the date field
Data Attributes
Data Attribute | Value |
[data-invalid] | Present when the field is invalid. |
[data-melt-datefield-label] | Present on all label elements. |
validation
The element containing the validation message
Data Attributes
Data Attribute | Value |
[data-invalid] | Present when the field is invalid. |
[data-melt-datefield-validation] | Present on all validation elements. |
hiddenInput
The hidden input for the date field
Data Attributes
Data Attribute | Value |
[data-melt-datefield-hiddenInput] | Present on all hiddenInput elements. |
Custom Events
Event | Value |
m-click | (e: ) => void |
m-keydown | (e: ) => void |
trigger
The button(s) which open/close the popover.
Data Attributes
Data Attribute | Value |
[data-state] |
|
[data-melt-popover-trigger] | Present on all trigger elements. |
Custom Events
Event | Value |
m-click | (e: ) => void |
m-keydown | (e: ) => void |
content
The popover content.
Data Attributes
Data Attribute | Value |
[data-side] | 'top' | 'right' | 'bottom' | 'left' |
[data-align] | 'start' | 'center' | 'end' |
[data-state] |
|
[data-melt-popover-content] | Present on all content elements. |
overlay
The optional popover overlay element, which can be used to give the popover modal-like behavior where the user cannot interact with the rest of the page while the popover is open.
Data Attributes
Data Attribute | Value |
[data-state] |
|
[data-melt-popover-overlay] | Present on all overlay elements. |
close
The button(s) which close the popover.
Data Attributes
Data Attribute | Value |
[data-melt-popover-close] | Present on all close elements. |
Custom Events
Event | Value |
m-click | (e: ) => void |
m-keydown | (e: ) => void |
arrow
The optional arrow element.
Data Attributes
Data Attribute | Value |
[data-side] | 'top' | 'right' | 'bottom' | 'left' |
[data-arrow] |
|
[data-melt-popover-arrow] | Present on all arrow elements. |
On This Page