Skip to content

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, a single-line text field, optional clear control, and a chevron. The trigger fills the available width; a value longer than the field scrolls inside it. Clicking the field, or pressing Arrow Down, opens the calendar; focusing it does not. Use slot="value" to replace the typed text, or slot="trigger" to replace the whole shell.

  • Single date: model-value / .modelValue is a string in YYYY-MM-DD format. Calendar selection commits immediately when show-time is off.
  • Date and time: Set show-time to draft YYYY-MM-DDTHH:mm in 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-presets on range mode for the sidebar (Today, Last 7 days, Custom range, and so on). Named presets show their label in the trigger and switch to their dates while the field has focus, so they can be read and edited; an edit makes the range custom. Custom ranges show the date string. Optional period-presets subsets, reorders, or relabels the built-ins. Range values may include preset.
  • 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. vertical always stacks a scrollable month list.
  • Display format: Set display-format and display-date-time-format with Day.js-style format tokens to change visible input text only. Emitted values stay canonical.
  • Forgiving typing: Besides the display format, the field accepts other separators (., /, -, spaces), digits without separators (27031990), missing leading zeros, and month names, and rewrites the date in the display format on blur. See Specs — Typed input.
  • Inline clear: Shown by default when the field has a value. Set show-clear-button to false to hide it.
  • Constraints: Use min, max, and disabled-dates to block invalid calendar cells. In range mode, use max-range-days to 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 label prop or label slot; for / id wiring is handled automatically.
  • Field: The text field is a combobox with aria-haspopup="dialog", aria-expanded, and aria-controls pointing at the panel while it is open. It describes its expected format, and named presets add their dates (or, while focused, the preset name) to the description.
  • Opening: A click opens the panel and leaves focus in the field for typing. Arrow Down (also Alt + Arrow Down) opens it and moves focus in, to the selected preset or the active day. Focusing the field alone never opens the panel.
  • Panel: A role="dialog" named after the field (for example "Start date, Choose date"). It renders right after the field, so reading order and Tab order follow it, and is shown in the top layer so it still paints above dialogs and clipped containers. While focus is inside it is aria-modal and Tab stays inside.
  • Closing: Escape, Tab from the field, picking a date (single date without time), Apply, Cancel, or a click outside. Focus returns to the field, except after a click outside. With Apply, Escape also discards the draft like Cancel. Without Cancel, a visually hidden Close button lets touch screen reader users dismiss the panel.
  • Calendar: Each month is a role="grid" table named by its month, with full weekday names and the APG date grid keys. The calendar has one Tab stop, on the active day. Unavailable days stay focusable and are announced as unavailable; days outside min / max are disabled. A polite live region confirms range starts, completed ranges, and month changes.
  • Presets: The preset list is a listbox with one Tab stop; Arrow Up / Arrow Down, Home, and End move, Enter / Space pick. Selected rows use the checkmark appearance.
  • 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.
  • Invalid state: intent="danger" sets aria-invalid="true" on the control; aria-describedby includes supporting text when present.
  • Forced colours: Selection, the range band, today, and focus stay visible in Windows contrast themes.

Catnip Design System by Signicat