date-picker

Form-associated calendar date picker with text entry, month navigation, keyboard support, and progressive enhancement over native input[type=date].

Overview

The <date-picker> component wraps a native <input type="date"> and replaces the inconsistent browser chrome with a combobox text input and calendar popup. Users can type a date directly or pick from the calendar grid. It supports min/max date ranges, disabled dates, locale-aware formatting, and participates in form submission via ElementInternals.

Attributes

Attribute Type Default Description
name string Form field name for submission.
data-disabled-dates string Comma-separated ISO dates to disable. Optionally append :reason for visual variants (e.g. 2026-04-05:booked,2026-04-06).
data-highlight-dates string Comma-separated ISO dates to highlight. Optionally append :category for visual variants (e.g. 2026-12-25:holiday,2026-04-15:deadline).
disabled boolean false Disables the picker.
required boolean false Marks the field as required for form validation.

Native input attributes

The following attributes are read from the child <input type="date">:

Attribute Effect
value Initial date in YYYY-MM-DD format.
min Earliest selectable date.
max Latest selectable date.

Date Constraints

Use min and max on the native input to restrict the date range. Use data-disabled-dates to exclude specific dates.

Disabled Date Styles

Append a :reason to any disabled date to get a distinct visual treatment. Dates without a reason use the default faded style. Three built-in reasons are provided:

Reason Visual Treatment Use Case
booked Strikethrough text Reservations, appointments already taken
unavailable Diagonal hatching Out-of-service, maintenance, closed periods
holiday Accent color, bold Public holidays, special dates

Custom reasons are also supported. Any value is set as data-disabled-reason on the calendar button, so you can target it with CSS:

Highlighted Dates

Use data-highlight-dates to visually mark key dates that remain selectable. Append a :category to each date for distinct styling. Three built-in categories are provided:

Category Visual Treatment Use Case
holiday Warm accent background and text Public holidays, observances
deadline Red accent background and text Due dates, cutoff dates
event Blue accent background and text Meetings, scheduled events

Dates without a category get a subtle default highlight. All highlighted dates remain fully selectable.

Custom categories are supported. Any value is set as data-highlight on the button:

Form Integration

The component is form-associated via ElementInternals and works inside <form-field> for validation messaging. The submitted value is always in ISO format (YYYY-MM-DD).

Text Entry

The date input accepts typed dates in the following formats. The calendar navigates live as you type.

Format Example
ISO date 2026-04-15 or 2026/04/15
Month name + day + year April 15, 2026 or Apr 15 2026
Day + month name + year 15 Apr 2026
Month + year (partial) April 2026 — navigates calendar without selecting a day

Locale-aware month names are also accepted. Ambiguous numeric formats like 4/15/2026 are intentionally rejected to avoid locale confusion.

Keyboard

Text input

Key Action
Enter Parse typed text and select the date if valid.
Arrow Down Open calendar and move focus into the date grid.
Escape Close calendar and revert text to selected date.
Tab Close calendar and move to next form field.

Calendar grid

Key Action
Arrow Left / Arrow Right Move focus one day.
Arrow Up / Arrow Down Move focus one week.
Page Up / Page Down Move focus one month.
Shift + Page Up / Shift + Page Down Move focus one year.
Home / End Move to first / last day of the week.
Enter / Space Select the focused date.
Escape Close calendar and return focus to text input.
Tab Close calendar and move to next form field.

Events

Event Detail Description
date-picker:change { value, date } Fired when a date is selected. value is the ISO string, date is a Date object.
date-picker:open Fired when the calendar opens.
date-picker:close Fired when the calendar closes.

Accessibility

The text input uses role="combobox" with aria-haspopup="dialog" and aria-expanded, following the W3C Date Picker Combobox pattern. The calendar popup uses role="dialog" with an accessible label. The date grid uses role="grid" with individual day buttons. Today is marked with aria-current="date", the selected date with aria-selected="true", and disabled dates with aria-disabled="true". The month/year header uses aria-live="polite" so screen readers announce navigation changes.

Localization

The trigger button formats dates using Intl.DateTimeFormat and the user’s locale. Month/year headers and first-day-of-week detection are also locale-aware. The submitted form value is always ISO-formatted regardless of display locale.

JavaScript API

Property Type Description
value string Get or set the selected date as an ISO string (YYYY-MM-DD).
min string Get or set the earliest selectable date. Updates the calendar immediately.
max string Get or set the latest selectable date. Updates the calendar immediately.

Recipe: Date Range (Linked Pickers)

Two standard <date-picker> elements can be linked for date range selection. When the start date is picked, it sets min on the end picker. When the end date is picked, it sets max on the start. No custom range component needed.

The min and max properties update the calendar constraints in real time. Dates outside the allowed range are automatically greyed out in the grid.