Date and time picker with Flatpickr
Use uiDatePicker(config) with date-picker.html for single dates, date ranges, multiple dates, and optional time selection. createAdmin registers the provider. The factory is available as datePicker from @agon/atrium/components/date-picker. Flatpickr 4.6.13, its stylesheet, and the four supported calendar dictionaries load on demand. Open /components/date-picker for working examples.
Minimal integration
Compose the shared partial inside a parent-owned form model:
<section x-data="{ appointment: '2026-09-24' }"> <h1>Appointment</h1> <div x-data="uiDatePicker({ label: 'Appointment date', name: 'appointment', required: true })" x-modelable="value" x-model="appointment" > <include src="ui:date-picker.html"></include> </div> <p>Selected date: <span x-text="appointment"></span></p></section>Setting appointment in your page provider updates the calendar. Selecting or clearing a date updates the parent model. Bind complex options and trusted callbacks from a named page provider rather than writing functions inside Alpine expressions. See lazy page registration.
Configuration
| Setting | Default | Behavior |
|---|---|---|
value | '', or [] for range/multiple mode. | Initial model when the parent does not supply one. |
label | ''. | Plain-text label, overriding labelKey. |
labelKey | datePickerLabel. | Translation key used for the visible label and calendar name. |
name | ''. | Native form field name. |
required | false. | Native form validation. |
disabled | false. | Initial disabled state. The provider’s disabled property can change reactively. |
options | {}. | Supported native Flatpickr options. |
Common configurations include:
const range = { options: { mode: 'range' } };const multiple = { options: { mode: 'multiple', minDate: '2026-09-20' } };const meeting = { options: { enableTime: true } };const time = { options: { enableTime: true, noCalendar: true } };const customMobile = { options: { disableMobile: true } };const inline = { options: { inline: true } };The wrapper owns defaultDate, onChange, altInput, wrap, static, and appendTo. These settings cannot replace its input, model handling, or DOM ownership. Use the bubbling date-change event for application reactions. Its detail.value matches the model. Explicit external model changes synchronize silently, so they do not produce a second change event. Programmatic clear() does emit the event.
Single-date models are strings. Range and multiple-date models are arrays of strings, including an empty array after clearing. Defaults are Y-m-d, Y-m-d H:i when time is enabled, and H:i for time-only inputs. Set options.dateFormat to change the wire format. The native range input displays a localized separator, so read the model rather than splitting its visible text or relying on native form serialization for an array.
These values represent browser-local calendar dates and times. They do not automatically convert into UTC or the shell’s selected time zone. Your application must define time-zone conversion, date-only storage, range completeness, and backend validation.
Language, theme, and mobile behavior
The calendar follows $store.ui.locale for English, French, German, and Italian. A language change recreates it while retaining the model. An object in options.locale can override individual dictionary settings, such as firstDayOfWeek. The wrapper selects the language itself, so supply locale overrides as an object rather than a locale-name string.
Calendar chrome uses the shared theme surface, text, border, focus, and accent tokens. The calendar, fields, and controls follow shell direction and responsive card layouts. Machine-formatted input values retain left-to-right ordering inside an RTL shell. No separate vendor color theme is necessary.
Flatpickr uses supported native mobile inputs by default. Their appearance belongs to the operating system. Set disableMobile: true to retain the custom calendar on phones. Range and multiple selection use the custom picker where native controls cannot provide those modes. Generated mobile inputs retain the field label and disabled state. The showcase includes both paths.
Lifecycle and application responsibilities
The provider initializes after template references exist. open() opens the picker, clear() clears its model, and refresh() retries loading or rebuilds native options. Initialization errors display a translated retry action. destroy() cancels pending initialization and removes native calendars and their global listeners. Route removal invokes it through Alpine.
Keep the component inside your application’s existing card, grid, or form layout. Do not initialize a second Flatpickr instance on its input. Callbacks, custom date restrictions, persistence, API submission, and validation belong to the consumer.
For a Livewire host, keep the native field under wire:ignore and bridge date-change or the parent model through your existing Livewire integration. Atrium does not bundle Livewire or a second Alpine runtime. The supplied acceptance suite covers Alpine CSP integration, not a complete Livewire application.
Author
Laurent Declercq l.declercq@agon-innovation.ch
License
Unless otherwise stated all source code is licensed under LGPL 2.1 and has the following copyright:
© 2026, Agon Partners Innovation AG, All rights reserved.Version
Version: 20260921