Skip to content

DateTimeEditor

Edits a date_time field in the viewer’s wall-clock time and emits the UTC instant the field stores.

The button carries a calendar icon, the stored instant or the placeholder, and the invalid state; the popover under it holds a typed day, the calendar and the time, in that order.

Terminal window
pnpm dlx shadcn@latest add https://sg-widgets.vercel.app/r/react/date-time-editor.json
Terminal window
pnpm dlx shadcn-svelte@latest add https://sg-widgets.vercel.app/r/svelte/date-time-editor.json
DateTimeEditor: three sizes, a second zone, unset, and the three marked states

React

Loading the React demo…

Svelte

Loading the Svelte demo…

typed, in America/Los_Angeles emitted
2026-03-04 and 05:06 "2026-03-04T13:06:00Z"
2026-03-04 and 05:06:07, with seconds shown "2026-03-04T13:06:07Z"
2026-03-04 and no time "2026-03-04T08:00:00Z"
both empty null
a time and no date nothing; a time needs a date

The zone the typed time is read in is named under the button.

proptypedefaultmeaning
valuestring | nullnullThe stored instant, UTC. Two-way in Svelte.
onValueChange(value: string | null) => void—Called when either input commits or a day is picked.
fieldPick<FieldSchema, 'displayName' | 'mandatory'> | nullnullSupplies the accessible label and the required flag.
timeZonestringthe runtime'sIANA zone the typed wall-clock time is read in.
showSecondsbooleanfalseSeconds in the time input and on the button.
hintbooleantrueName the zone under the button.
disabledbooleanfalse
readonlybooleanfalseKeeps the value readable and does not open the popover.
invalidbooleanfalseForced invalid state.
errorstring | nullnullA message from the caller, shown in place of the parse error.
onErrorChange(error: string | null) => void—Called when the parse error appears or clears.
placeholderstring'YYYY-MM-DD'Shown on the button and in the typed day while the field is unset.
openbooleanfalseWhether the calendar popover is showing. Two-way in Svelte.
class / classNamestring—Merged after the widget's own classes.
errorMessagefrom ValueEditor(message: string) => ReactNode / Snippet<[string]>—Renders the message. Default is a small destructive line under the control.
size'sm' | 'md' | 'lg''md'Button height.
inlinebooleanfalseThe row form: the button takes the width of its value and the zone line goes.
eventpayloadwhen
onOpenChangebooleanThe calendar opened or closed.

onValueChange fires on commit and on a pick. Input that does not parse emits nothing.

onOpenChange fires when the calendar popover opens or closes. Svelte also binds it with bind:open.

errorMessage receives the message and renders it.

keydoes
EnterOn the button, opens the popover. In the typed day or the time, commits both and closes the popover.
EscapeIn the popover, restores the stored instant and closes the popover.
SpaceOpens the popover, from the button.
TabMoves through the typed day, the calendar and the time.
arrowsMove between days inside the calendar, and between segments inside the time.
Enterfrom ValueEditorCommits the draft. In a textarea it adds a line, and commitOnEnter turns the commit off.
Escapefrom ValueEditorRestores the stored value and drops what the last parse said.
Tabfrom ValueEditorLeaves the control, which commits.

A picked day leaves the popover open, so the time can follow it.

The field is stored and read as UTC YYYY-MM-DDTHH:MM:SSZ at second resolution. A written offset is normalised away and a zoneless string is taken as UTC, not as site-local, so a wall-clock time has to be converted before it is sent (field_types/date_time).

Only null clears the field; the empty string is a 400 (field_types/date_time).

Most timestamp fields are server-managed, and the name does not predict it. Read the schema’s editable flag before offering this control (field_types/date_time).