Date Input
The catnip-input-date custom element lets users type or pick a single date, date and time, or date range from a floating calendar panel. It uses the same integrated label and supporting-text patterns as Input, Number Input, and Chip Input. Shared field behaviour is summarised on Inputs overview.
Overview
catnip-input-date values are canonical date strings, not UTC timestamps. Single-date values must use YYYY-MM-DD. Date-time values use YYYY-MM-DDTHH:mm without a timezone suffix, so they represent the selected calendar date and time rather than a converted UTC instant. Use display-format only to change the visible text in the input.
Every type uses one combined trigger: leading calendar icon, typed value, optional clear control, and a chevron. The trigger fills the available width so the value can stay on one line; if the container is too narrow (typical for date-time ranges), the value wraps and the field grows in height. Use slot="value" to replace the typed text, or slot="trigger" to replace the whole shell.
- Single date:
model-value/.modelValueis a string inYYYY-MM-DDformat. Calendar selection commits immediately whenshow-timeis off. - Date and time: Set
show-timeto draftYYYY-MM-DDTHH:mmin the panel. Reset / Cancel / Apply confirm the value. - Range: Set
mode="range"to bind{ start?: string; end?: string }. The trigger shows both endpoints separated by an em dash. Date-only range commits when the end date is selected. Date-time range uses the same Apply footer as single date-time. - Range presets: Set
show-presetson range mode for the sidebar (Today, Last 7 days, Custom range, and so on). Named presets show their label in the trigger; custom ranges show the date string. Optionalperiod-presetssubsets, reorders, or relabels the built-ins. Range values may includepreset. - Panel orientation:
panel-orientation="horizontal"(default) pages one month, or two side-by-side months in range mode. Range horizontal panels switch to the stacked vertical layout below 800px.verticalalways stacks a scrollable month list. - Display format: Set
display-formatanddisplay-date-time-formatwith Day.js-style format tokens to change visible input text only. Emitted values stay canonical. - Inline clear: Shown by default when the field has a value. Set
show-clear-buttontofalseto hide it. - Constraints: Use
min,max, anddisabled-datesto block invalid calendar cells. In range mode, usemax-range-daysto cap the inclusive number of calendar days between start and end. - Calendar: Month navigation, a clickable month/year header, weekday headers, current/selected/range states, and keyboard navigation for day movement. In range mode the header opens a year grid beside a month grid (stacked in the vertical layout). Single date still opens the year grid only.
Live example
Accessibility
- Label: Use the
labelprop orlabelslot;for/idwiring is handled automatically. - Trigger: The native text control exposes
aria-haspopup="grid",aria-expanded, and panel linkage while open. It uses the available width and wraps instead of truncating. - Time: Panel time fields are labeled text inputs (
HH:mm), not native time pickers. Range times sit under each month and share the calendar column divider. - Calendar: Arrow keys move by day/week, Home / End move within the week, PageUp / PageDown change month, Shift + PageUp / Shift + PageDown change year, Enter / Space select, and Escape closes.
- Presets: The range preset list is a listbox; selected rows use the checkmark appearance.
- Invalid state:
intent="danger"setsaria-invalid="true"on the control;aria-describedbyincludes supporting text when present.