Input Date
A date field with a typeable value and a calendar button. Click the value to type. The calendar button opens the picker.
Usage
A composed control: InputGroup plus a calendar button that opens a Popover with the themed Calendar. Compose it inside a Field for the label and a11y wiring. Clicking the value places a caret. The calendar button (and Down Arrow) opens the popover.
Don't use the native <input type="date">: its picker can't be themed and
differs per browser/OS. For a month grid with no field, use
Calendar.
import { Field, FieldLabel } from '@epilot/spark-ui/field'
import { InputDate } from '@epilot/spark-ui/input-date'function StartDateField() {
const [value, setValue] = useState('')
return (
<Field>
<FieldLabel>Start date</FieldLabel>
<InputDate
calendarLabel={t('openCalendar')}
onValueChange={setValue}
value={value}
/>
</Field>
)
}Typing is owned by ictus inside Input Date.
4 becomes 04., a typed . / - commits a started group, and impossible
second digits are ignored. A half-typed value stays in the field;
onDateChange is undefined until the string is a complete, calendar-valid
date. Surface a Field error on blur when the value
is non-empty and unparseable.
calendarLabel is required. Input Date ships no English default for the
button.
Pass separator (. or /) to match the app locale. Field order is
day-month-year. Pass Calendar options such as locale through
calendarProps. Opening the popover shows the month of the parsed value, or
today if the field is empty.
On mobile, keep this click split if you swap the popover for a Drawer: type in the field, icon opens the drawer. Do not make the whole field the drawer trigger in the default usage.
For every Field / Input / InputGroup combination and state side by side, see the Field Matrix.
Examples
Picker only
When the job is picking a near-term day and weekday context matters more
than typing, set readOnly. Click the value or the calendar button to open
the popover. The field uses cursor-pointer so it does not look like a caret
input. Do not combine an editable input with click-to-open: readOnly is
what switches that rule.
API Reference
InputDate
Native <input> attributes except value, defaultValue, onChange, and
type. className merges onto the InputGroup chrome.
| Prop | Type | Default | Description |
|---|---|---|---|
calendarLabel | string | — | Accessible name of the calendar button and of the open popover. Required; no built-in copy. |
value | string | — | Controlled masked string (DD.MM.YYYY with the configured separator). |
defaultValue | string | "" | Uncontrolled initial masked string. |
onValueChange | (value: string) => void | — | Fires on every accepted keystroke and on a calendar pick. |
onDateChange | (date: Date | undefined) => void | — | Parsed local Date when the string is complete and valid, else undefined. |
readOnly | boolean | false | Picker-only: click the value opens the calendar. Typing is off. |
separator | string | "." | Written between day, month, and year. Typed . / - all commit this character. |
placeholder | string | DD.MM.YYYY | Shown while the value is empty. The default follows separator. |
open | boolean | — | Controlled popover visibility. |
defaultOpen | boolean | false | Uncontrolled initial popover visibility. |
onOpenChange | (open: boolean) => void | — | Fires when the popover opens or closes. |
calendarProps | Omit<CalendarProps, "mode" | "selected" | "onSelect"> | — | Passed to Calendar (locale, disabled, …). Opening shows the parsed value's month, or today if empty. A passed month overrides that. |
disabled | boolean | — | Disables the input and the calendar button. |
className | string | — | Merges with the InputGroup box styles. |
A calendar pick writes formatDate into the same string onValueChange
receives. Do not pass onChange: keystrokes are handled on keydown.
Accessibility
| Key / pointer | Action |
|---|---|
| Click the value | Places a caret. Does not open the popover. With readOnly, opens the popover. |
| Calendar button | Opens the popover. Stays in the tab order. |
| Down Arrow, Alt+Down Arrow | Opens the popover from the focused input. |
| Escape | Closes the popover (Popover default). |
Keep the calendar button in the tab order. Give calendarLabel a translated
name such as "Open calendar".