cupertino-datetime-picker

DateTimePicker

The compact picker, a date pill and a time pill that each open a panel, or the same panels laid out inline.

import { DateTimePicker } from "@/components/ui/cupertino/date-time-picker";

const [date, setDate] = useState<Date | null>(null);

<DateTimePicker value={date} onChange={setDate} />;

Value

The value is a Date | null. Pass value and onChange to control it, or defaultValue to let the picker own it. With no value the pills show their placeholders and the first pick starts from now.

Picking a day keeps the clock time; picking a time keeps the day. The Date you receive is always a new object in local time.

Mode

mode is UIDatePicker.Mode: "date", "time", or the default "dateTime".

Display

display="compact" (the default) renders the pills. display="inline" lays the calendar out in place, with the time on a "Time" row underneath, the way the iOS event editor does.

<DateTimePicker display="inline" />

The inline root has a --cdp-bg background and 13px corners but no shadow or border, so it sits flat in a list. Add the sheet look with a class:

<DateTimePicker display="inline" className="shadow-[var(--cdp-shadow)]" />

Locale

locale drives every visible string: month and weekday names, the first day of the week, the 12- or 24-hour clock, the AM/PM labels, and the pill formats. It defaults to navigator.language.

<DateTimePicker locale="de-DE" />

hourCycle overrides the clock the locale implies.

<DateTimePicker locale="en-US" hourCycle="h23" />

Minute interval

minuteInterval sets the minute wheel step, like UIDatePicker.minuteInterval. Typing still accepts any minute; the wheel settles on the nearest step.

<DateTimePicker mode="time" minuteInterval={5} />

Range

min and max disable days outside the range. Months you cannot reach are not offered by the arrows either.

<DateTimePicker min={addDays(today, -3)} max={addDays(today, 10)} />

Disabled

Props

PropTypeDefault
valueDate | nullControlled value.
defaultValueDate | nullnullInitial value when uncontrolled.
onChange(date: Date | null) => voidCalled with every pick.
mode"date" | "time" | "dateTime""dateTime"Which parts are editable.
display"compact" | "inline""compact"Pills with popovers, or the panels in place.
localestringnavigator.languageNames, week start, clock, pill formats.
hourCycle"h12" | "h23"from locale12- or 24-hour clock.
minuteIntervalnumber1Minute wheel step.
min / maxDateDays outside the range are disabled.
disabledbooleanfalseDisables the pills.
labels{ date?: string; time?: string }Date / TimePill placeholders while there is no value.
classNamestringOn the root element.

Building your own row

The pill and popup styles are exported as pillClass and popupClass, so a row of your own (quick picks plus a calendar, an "Add time" pill that is empty until pressed) uses the same panels and looks the same. See the panels page.

On this page