Date picker: Typing a date
The slotsmith date picker’s trigger is a text field: type a date in the locale’s order, such as MM/DD/YYYY, or pick it from the calendar beside the field. openOnFocus opens the calendar on focus, and trigger="button" swaps the field for one button showing the formatted date.
Due: none
import { useId, useState } from "react";
import { DatePicker } from "slotsmith/date-picker";
export default function Typing() {
const id = useId();
const [due, setDue] = useState<string | null>(null);
const [checkIn, setCheckIn] = useState<string | null>(null);
return (
<div style={{ display: "grid", gap: "1rem", maxWidth: 288 }}>
<div>
<label htmlFor={`${id}-due`}>Due date</label>
{/* The default: type the date, or open the calendar from the button. */}
<DatePicker id={`${id}-due`} value={due} onChange={setDue} />
</div>
<div>
<label htmlFor={`${id}-check-in`}>Check-in</label>
{/* The calendar opens as soon as the field is focused or clicked. */}
<DatePicker id={`${id}-check-in`} openOnFocus value={checkIn} onChange={setCheckIn} />
</div>
<p dir="ltr">Due: {due ?? "none"}</p>
</div>
);
}The text field
trigger is "input" by default. The field:
- Shows the value in the locale’s numeric order, with Latin digits, and that order as its placeholder:
MM/DD/YYYYinen-US,DD/MM/YYYYinen-GB,DD.MM.YYYYinde,YYYY/MM/DDinja. Aplaceholderyou pass replaces it. - Reads what was typed on Enter and when focus leaves the field. Any separator works (
3/5/2026,3-5-2026,3 5 2026), the year has four digits, and Arabic-Indic, Persian and full-width digits read as well. - Puts the value back when the text is not a date or names a day that cannot be picked: outside
minDateandmaxDate, or blocked bydisabledDates. Emptying the field clears the value. - Moves the calendar to the month being typed while it is open, without taking focus from the field.
In range mode the ends are written 03/05/2026 – 03/09/2026; an en dash, an em dash or a hyphen with spaces around it separates them, and ends typed backwards are swapped. In multiple mode the days are separated by commas.
The naming and validation props you pass to DatePicker (id, aria-label, aria-labelledby, aria-describedby, aria-invalid, aria-required and autoFocus) go to the field, so a <label htmlFor> names it.
Keyboard
| Key | In the field |
|---|---|
| Down Arrow | Opens the calendar and moves focus into it, or moves into it when it is already open. |
| Enter | Reads what was typed, and closes the calendar if it is open. |
| Escape | Closes the calendar; with the calendar closed, drops what was typed. |
Inside the calendar the keys are the grid’s. A pick, or Escape, returns focus to the field.
Opening on focus
With openOnFocus the calendar opens when the field is focused or clicked, and focus stays in the field so typing goes on. Focus coming back to the field after a pick does not open it again. The button beside the field still opens and closes it.
The button trigger
trigger="button" gives the earlier shape: one role="combobox" button showing the date formatted with format, such as “Mar 12, 2026”, that opens the calendar when pressed. Use it where a date is only picked, never typed, such as a cell editor.
Reminder
Trip
import { useId, useState } from "react";
import { DatePicker, type DateRange } from "slotsmith/date-picker";
export default function ButtonTrigger() {
const id = useId();
const [reminder, setReminder] = useState<string | null>(null);
const [trip, setTrip] = useState<DateRange | null>(null);
return (
<div style={{ display: "grid", gap: "1rem", maxWidth: 288 }}>
<div>
<p id={`${id}-reminder`}>Reminder</p>
{/* One button: it shows the date as "Mar 12, 2026" and opens the calendar when pressed. */}
<DatePicker trigger="button" aria-labelledby={`${id}-reminder`} value={reminder} onChange={setReminder} />
</div>
<div>
<p id={`${id}-trip`}>Trip</p>
<DatePicker
trigger="button"
mode="range"
aria-labelledby={`${id}-trip`}
placeholder="Pick your dates"
format={{ day: "numeric", month: "long" }}
value={trip}
onChange={setTrip}
/>
</div>
</div>
);
}The first picker shows one date; the second a range, with its own placeholder and a format without the year.
Slots
The field adds two slots: Input, the text field inside the Trigger frame, and Toggle, the calendar button around the Icon. The frame carries data-trigger="input" and the state attributes; the Input carries role="combobox". Its name, “Open calendar”, is the openCalendar label, translated in every bundled language. The ready-made adapters render each library’s own bare input and icon button.