Date Pickers
Calendar dates, ranges, and times with native fallbacks and full localization.
Setup
Date picker styles are included in Manifest CSS or a standalone stylesheet, both referencing theme variables.
Date picker functionality is included in manifest.js with all core plugins, or it can be selectively loaded.
<!-- Manifest CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/mnfst@latest/lib/manifest.min.css" />
<!-- Manifest JS -->
<script src="https://cdn.jsdelivr.net/npm/mnfst@latest/lib/manifest.min.js"></script>
Field
Native Input
The simplest date field is a native <input type="date">, displaying the browser's built-in picker when pressed. No plugin required.
<input type="date">
Picker Field
For full control over content, format, and styling, add x-date to an input. The plugin renders a themed calendar dropdown under the field and writes the selection back as a localized display value.
<input x-date placeholder="Select a date">
Triggers aren't input-specific — a <button x-date> opens the same dropdown, with its authored text serving as the placeholder until the selection replaces it. Triggers with element children (icons, custom layout) keep their content untouched; display the value yourself with x-model or $date().
<button x-date>Pick a date</button>
Keep the authored type="date" for graceful degradation: until the plugin loads (or if JavaScript is disabled), the browser's native picker serves as the fallback, and its min/max attributes carry over.
<input x-date type="date" min="2026-01-01" max="2026-12-31">
Default Value
Seed the field with a value attribute in ISO format (YYYY-MM-DD) — the same value a native date input would carry.
<input x-date value="2026-06-15">
For two-way reactive binding, use x-model instead. When both are present, x-model wins. The model holds the ISO value; the field displays the localized format.
<div x-data="{ when: '' }">
<input x-date x-model="when" placeholder="Select a date">
<span x-text="when"></span>
</div>
Form Participation
Add a name attribute to submit with a <form>. The plugin synthesizes a paired hidden input carrying the ISO value and keeps it in sync. The visible field holds the human-readable format while the form receives the machine-readable one.
<form>
<input x-date name="event_date" placeholder="Event date">
<button type="submit">Save</button>
</form>
Time Fields
The input's authored type declares what the field picks. type="time" makes a standalone time picker — a dropdown of hour and minute columns (plus AM/PM in 12-hour locales). type="datetime-local" combines the calendar with a time row.
<!-- Time only -->
<input x-date type="time" placeholder="Pick a time">
<!-- Date + time -->
<input x-date type="datetime-local" placeholder="Pick date & time">
Time-only values are HH:mm strings; datetime values are YYYY-MM-DDTHH:mm. The x-date.time modifier on a plain input is equivalent to type="datetime-local".
Calendar
To author a calendar directly — without a field — place x-date on a container. The wrapper element determines its presentation: <div> renders in the page flow, <menu popover> anchors as a dropdown, and <dialog popover> opens as a modal.
<!-- Inline -->
<div x-date x-model="picked"></div>
<!-- Dropdown -->
<button popovertarget="cal-menu">Choose date</button>
<menu id="cal-menu" popover x-date></menu>
<!-- Dialog -->
<button popovertarget="cal-dialog">Choose date</button>
<dialog id="cal-dialog" popover x-date></dialog>
Clicking the calendar heading jumps to month and year views for fast long-range navigation, the same way native pickers do.
Selection Modes
Range
The x-date.range modifier selects a start and end date. Hovering previews the span before the second click commits it. The model value is a { start, end } object; the form/string value is start/end.
<div x-data="{ stay: { start: '', end: '' } }">
<input x-date.range x-model="stay" placeholder="Select a range">
</div>
For travel-booking layouts, pair ranges with a multi-month calendar — the months config key (1–4) lays months side by side:
<div x-date.range="{ months: 2 }"></div>
Multiple
The x-date.multiple modifier toggles any number of individual dates. The model value is an array of ISO strings; the form value is comma-separated.
<div x-data="{ dates: [] }">
<div x-date.multiple x-model="dates"></div>
</div>
Configuration
Pass an object as the directive's value for reactive configuration. All keys are optional and re-evaluate like any Alpine expression.
| Key | Type | Description |
|---|---|---|
months |
number (1–4) | Calendar months displayed side by side. Default 1. |
firstDay |
string | number | First weekday override — a name ('monday') or index (0 = Sunday). Defaults to the locale's. |
min / max |
ISO string | Selectable bounds. Also read from the input's native min/max attributes. |
disabled |
array | function | Unselectable dates — ISO strings, { from, to } spans, or a (date) => boolean predicate. |
presets |
array | Quick-pick chips shown in the footer (see below). |
now / clear |
boolean | Set false to hide the Today/Now or Clear action. Both default true. |
<div x-date="{
min: '2026-06-01',
max: '2026-06-30',
disabled: ['2026-06-13', { from: '2026-06-20', to: '2026-06-22' }]
}"></div>
Presets
Each preset is a labeled value matching the selection mode: { label, value } for single dates, { label, start, end } for ranges, { label, dates } for multiples. Because the config is a live expression, preset values can be computed.
<div x-date.range="{
presets: [
{ label: 'This weekend', start: '2026-06-13', end: '2026-06-14' },
{ label: 'Next week', start: '2026-06-15', end: '2026-06-21' }
]
}"></div>
Keyboard
The day grid is fully keyboard-operable with a single tab stop (the selection, or today).
| Key | Action |
|---|---|
← → |
Previous / next day |
↑ ↓ |
Previous / next week |
PageUp PageDown |
Previous / next month |
Home |
Start of week |
Enter / Space |
Select the focused day |
Escape |
Close the dropdown |
Localization
Calendars localize themselves from the active locale: month and weekday names, first day of the week, date display formats, and the 12/24-hour clock all come from Intl. Switching locale re-renders every calendar, with no configuration needed.
The few built-in UI strings are overridable through the universal _ui block — namespaced under date — in any local data file your project loads. Override only the keys you want; anything omitted stays in English.
{
"data": {
"content": {
"en": "/data/content.en.yaml",
"fr": "/data/content.fr.yaml"
}
}
}
| Key | Default | Used for |
|---|---|---|
today |
Today | Footer jump-to-today action |
now |
Now | Time picker's current-time action |
clear |
Clear | Footer / time picker clear action |
previousMonth |
Previous month | Header arrow label (assistive tech) |
nextMonth |
Next month | Header arrow label (assistive tech) |
time |
Time | Date+time row label |
Because overrides are namespaced per element, one shared _ui block can localize other Manifest elements too (i.e. _ui.colorpicker).
Magic Method
Use the $date(id) magic method to read or change a picker from anywhere on the page. The id is the field's or calendar's element id. Used on its own it returns the primary value as a string.
<input id="event" x-date placeholder="Choose…">
<span x-text="$date('event').iso"></span>
<span x-text="$date('event').formatted"></span>
| Property | Returns |
|---|---|
$date(id) |
Primary value string — ISO date, start/end, comma list, or HH:mm per mode. |
$date(id).iso |
Same as the primary value. |
$date(id).formatted |
Localized display string. |
$date(id).date |
The selected Date object (single mode). |
$date(id).range |
{ start, end } ISO strings (range mode). |
$date(id).start / .end |
Range endpoints individually. |
$date(id).dates |
Array of ISO strings (multiple mode). |
$date(id).time |
HH:mm string when a time is set. |
$date(id).mode |
'single', 'range', or 'multiple'. |
| Action | Effect |
|---|---|
$date(id).setDate(iso) |
Select a date programmatically. |
$date(id).setTime('HH:mm') |
Set the time of day. |
$date(id).clear() |
Clear the selection. |
$date(id).open() / .close() |
Open or close a field's dropdown. |
Styles
Theme
The default calendar uses the following theme variables:
| Variable | Purpose |
|---|---|
--color-popover-surface |
Calendar background |
--color-content-stark |
Day numbers and primary text |
--color-content-subtle |
Weekday labels, muted text, disabled days |
--color-brand-surface / --color-brand-inverse |
Selected day fill and text |
--color-field-surface |
Hover states and preset chips |
--color-line |
Borders, dividers, and the today ring |
--radius |
Calendar, day, and field corner radius |
--spacing-field-height |
Header and control heights |
--transition |
Hover and focus transitions |
--icon-previous / --icon-next |
Header navigation chevrons (SVG masks) |
Tailwind CSS
If using Tailwind, individual fields and calendars can be customized with utility classes.
<input x-date class="max-w-48 rounded-full" placeholder="Compact">
<div x-date class="border border-line shadow-lg"></div>
Customization
Modify base styles with custom CSS targeting [x-date] (or the .date-picker marker class the plugin stamps on every calendar root, which also covers modified directives like x-date.range). The generated markup is semantic HTML, so the inner parts are plain element selectors:
| Selector | Part |
|---|---|
header |
Month navigation — arrows and heading button |
section |
One calendar month (multi-month layouts) |
[role=grid] abbr |
Weekday labels |
[role=grid] button |
Day cells |
[role=listbox] button |
Month / year jump cells |
fieldset |
Time-of-day row (date+time) |
.time-options |
Hour / minute / AM-PM columns |
footer |
Today, presets, and Clear actions |
Day and cell states are attributes and plain classes: [aria-selected=true] (selected), [aria-current=date] (today), :disabled, .outside (adjacent-month days), and .range-start / .range-end / .in-range for range spans.
/* Rounder selected days */
[x-date] [role=grid] button[aria-selected=true],
.date-picker [role=grid] button[aria-selected=true] {
border-radius: 50%;
}
/* Tone down the range band */
.date-picker [role=grid] button.in-range {
background: color-mix(in oklch, var(--color-brand-surface) 15%, transparent);
}
Article does not exist
There is no documentation at this path.