Date Time Picker
Edit a local date and time in one control.
The post goes live at this time in your local time zone.
Installation
pnpm dlx shadcn@4.18.0 add @siteplane/date-time-pickerComplete the one-time setup first. Registry JSON lists source files and dependencies.
For this page’s examples, also install:
pnpm dlx shadcn@4.18.0 add @siteplane/button @siteplane/form @siteplane/inputField is installed with Input.
Usage
import { DateTimePicker } from "@/siteplane/components/date-time-picker";
<DateTimePicker aria-label="Meeting start" />;Controlled value
Pass value and onValueChange to keep the date and time in React state. onValueChange receives undefined when the field is cleared; store null for an empty controlled value, because undefined makes the picker uncontrolled.
12-hour clock
Set hourCycle={12} for an application that shows times such as 9:00 PM. The time adds an AM/PM segment after the minutes, which takes focus and arrow keys like the other segments; typing A or P sets it. The time selector names each hour with its day period, such as 09 PM. The value stays in 24-hour time, and the form still receives YYYY-MM-DDTHH:mm.
import { DateTimePicker } from "@/siteplane/components/date-time-picker";
<DateTimePicker aria-label="Snooze until" hourCycle={12} />;Unavailable dates
Use calendarProps.disabled to block past dates and weekends. The calendar doesn't offer these dates, and a typed date that breaks a rule marks the field invalid once it loses focus or the form is submitted; FieldError shows the message. Time rules, such as business hours, are not checked, so validate them in your form and again on the server.
Interviews take place Monday to Friday.
Minute step
minuteStep sets the minute options in the time selector, here every 15 minutes. Typed minutes are not rounded, so check the step on the server if it matters.
Disabled, read-only and invalid
A disabled Field also disables the picker, and readOnly shows a date and time that can't be changed on the regular field surface. For an error from your application, such as a time outside business hours, set invalid on Field and explain the problem in a FieldError.
Set by the organizer.
Submission and reset
With name, DateTimePicker submits a hidden local YYYY-MM-DDTHH:mm string without seconds, UTC offset or Z suffix; convert time zones in your application. The example submits { "startsAt": "2026-10-14T10:30" }, and an empty field submits an empty string. Changing locale changes only the display. With required, submitting an empty field is blocked, the field is focused and FieldError shows the required message. Native form reset restores defaultValue; reset controlled state yourself.
API reference
| Prop | Type | Default | Description |
|---|---|---|---|
aria-label | string | unset | Accessible name when no FieldLabel or aria-labelledby names the picker. |
aria-labelledby / aria-describedby | string | unset | External label and help ids; inside a Field, FieldLabel, FieldDescription and FieldError are connected automatically. |
aria-invalid | AriaAttributes[aria-invalid] | unset | External invalid state; while set, it replaces the built-in date checks. |
value / default | DateTimePickerValue | null (value only) | uncontrolled / unset | Controlled or initial value; null is an empty controlled value. |
on | (value: DateTimePickerValue | undefined) => void | unset | Reports a complete date and time, or undefined when cleared. |
disabled | boolean | false | Prevents editing/opening; a disabled Field also disables the picker. |
class | string | unset | Outer control styling; the picker keeps its content width unless a width utility such as w-full is set. |
locale | string | context | Formatting locale, not time zone. |
calendar | CalendarOptions | unset | The calendar options below: defaultMonth, disabled, startMonth, endMonth and todayDate. |
read | boolean | false | Read-only field on the regular surface; required blocks form submission while empty, focuses the field and shows the required message in FieldError. |
size | sm | md | lg | xl | provider / lg | Control size. |
text | sm | base | unset | Field text size; unset is 14px, or 16px at xl, like Input. |
variant | default | elevated | inset | soft | default | Input surface. |
form | string | unset | Associated form ID. |
name | string | unset | Hidden serialized input name; a Field name takes precedence. |
minute | number | 5 | Minute selector options; normalized to an integer between 1 and 60. |
hour | 12 | 24 | 24 | Clock of the time segments and the time selector; 12 adds the locale's AM/PM segment. The value stays in 24-hour time. |
open | string | Open date calendar / Open time selector | Picker button labels. |
incomplete | string | Enter a complete date and time. | The error of a required picker while its date and time are incomplete, shown by FieldError. |
size and variant use the same scale and surfaces as Input; see Input sizes and variants.
Calendar options
calendarProps takes CalendarOptions, the type of the same options on Calendar. startMonth and endMonth (Date, unset) limit the calendar to the first and last allowed months. disabled (unset) makes days unavailable with one matcher or a list of matchers, each a Date, a (date: Date) => boolean test or a rule with after, before, from, to and dayOfWeek (0 Sunday through 6 Saturday); true disables the whole calendar. Both apply to picking in the calendar and to typed dates.
defaultMonth (Date, unset) sets the month the calendar shows when it opens; while it is set, it also wins over the month of the selected date. todayDate (Date, the device's date) sets the day the calendar marks as today; without a selected date, the calendar opens on its month, and typed segments start from it.
Exported types: DateTimePickerProps, DateTimePickerValue. These describe the contracts above.
Usage notes
Values use native Date calendar fields in the local runtime time zone. Locale changes formatting, not the zone. DateTimePickerValue is {date:Date,time:{hour,minute}}; no time-zone selector or automatic zone conversion is exposed. The time button stays disabled until a date is set, and the time selector's labels (Hours, Minutes) are English. Inside a Field, FieldLabel names DateTimePicker and clicking it focuses the first segment; outside a Field, pass aria-label or aria-labelledby. Arrow keys change the focused date or time segment. Only the props listed above are supported, and DateTimePicker renders its own segments, buttons and popovers; it accepts no children or ref. The named Props type and value type are exported from the component module.
The date and the time, with the date button between them, read in the direction of the locale, which the arrow keys follow too, and are isolated from the text around them. An en-US value keeps its date before its time in a right-to-left page, while the field keeps the page's direction: its time button sits at the page's inline end.