Skip to content

Date Time Input

Date Time Input widgets are Input Fields that let the user enter a date and a time together in a single row of segmented inputs, offering a keyboard-friendly alternative to interactive calendars. The segments follow the locale’s order, and whether the time renders in 12-hour or 24-hour mode follows the user’s locale too.

The widget emits a local ISO date-time string (YYYY-MM-DDTHH:mm:ss) on change, pair it with the { format: 'date-time' } validator.

datetimeinput.ts
import { gui } from '@golemui/gui-shared';
export default [
gui.inputs.dateTimeInput('meetingAt', {
label: 'Meeting At',
}),
];
datetimeinput.json
{
"$schema": "https://golemui.com/schemas/form.schema.json",
"form": [
{
"kind": "input",
"type": "dateTimeInput",
"path": "meetingAt",
"label": "Meeting At"
}
]
}

Typed values clamp at their limits (30 hours becomes 23 or 12 in 12-hour mode, and 95 minutes becomes 59). ArrowUp/ArrowDown increment the focused segment: date parts and hours stop at their limits while minutes wrap around (5900). The AM/PM segment is a toggle button: clicking it (or pressing Enter, Space, ArrowUp or ArrowDown) swaps AM and PM. If the completed date does not exist (e.g. February 30), the widget shows an error instead of a value; the message can be customized (and localized) with the invalidDateMessage prop.

Use these props to customize your Date Time Input widget.

proptypedescription
hintstringA description to display below the segmented inputs
hourFormat'12' | '24'Forces 12-hour or 24-hour mode; when omitted the locale decides
iconstringA css class to display an icon inside the input
invalidDateMessagestring | LocalizableError message shown when the completed date does not exist, e.g. February 30
maxDatestringLatest allowed date (ISO date, inclusive)
maxDateMessagestring | LocalizableError message shown when the entered date is after maxDate
maxTimestringLast allowed time (ISO time, inclusive)
maxTimeMessagestring | LocalizableError message shown when the entered time is after maxTime
minDatestringEarliest allowed date (ISO date, inclusive)
minDateMessagestring | LocalizableError message shown when the entered date is before minDate
minTimestringFirst allowed time (ISO time, inclusive)
minTimeMessagestring | LocalizableError message shown when the entered time is before minTime
minuteStepnumberThe ArrowUp/ArrowDown increment of the minute segment (default: 1)

Use the property hint to add a description or validation instructions.

datetimeinput.ts
import { gui } from '@golemui/gui-shared';
export default [
gui.inputs.dateTimeInput('meetingAt', {
hint: 'Please enter the meeting date and start time',
label: 'Meeting At',
}),
];
datetimeinput.json
{
"$schema": "https://golemui.com/schemas/form.schema.json",
"form": [
{
"kind": "input",
"type": "dateTimeInput",
"path": "meetingAt",
"label": "Meeting At",
"props": {
"hint": "Please enter the meeting date and start time"
}
}
]
}

Use the property icon to add an icon to the widget. The value of icon represents a set of CSS classes separated by spaces. The icon is displayed inside the input border.

datetimeinput.ts
import { gui } from '@golemui/gui-shared';
export default [
gui.inputs.dateTimeInput('meetingAt', {
icon: 'calendar_month',
label: 'Meeting At',
}),
];
datetimeinput.json
{
"$schema": "https://golemui.com/schemas/form.schema.json",
"form": [
{
"kind": "input",
"type": "dateTimeInput",
"path": "meetingAt",
"label": "Meeting At",
"props": {
"icon": "calendar_month"
}
}
]
}

By default the 12-hour/24-hour layout comes from the locale’s hour cycle. Use the property hourFormat ('12' or '24') to force one of them.

datetimeinput.ts
import { gui } from '@golemui/gui-shared';
export default [
gui.inputs.dateTimeInput('meetingAt12', {
hourFormat: '12',
label: 'Meeting At (12h)',
}),
gui.inputs.dateTimeInput('meetingAt24', {
hourFormat: '24',
label: 'Meeting At (24h)',
}),
];
datetimeinput.json
{
"$schema": "https://golemui.com/schemas/form.schema.json",
"form": [
{
"kind": "input",
"type": "dateTimeInput",
"path": "meetingAt12",
"label": "Meeting At (12h)",
"props": {
"hourFormat": "12"
}
},
{
"kind": "input",
"type": "dateTimeInput",
"path": "meetingAt24",
"label": "Meeting At (24h)",
"props": {
"hourFormat": "24"
}
}
]
}

Use the property minuteStep to control the ArrowUp/ArrowDown increment of the minute segment, useful for appointment-style forms where times snap to a grid (e.g. every 15 minutes). Typing a value is not restricted by the step. The default is 1.

datetimeinput.ts
import { gui } from '@golemui/gui-shared';
export default [
gui.inputs.dateTimeInput('meetingAt', {
minuteStep: 15,
label: 'Meeting At',
}),
];
datetimeinput.json
{
"$schema": "https://golemui.com/schemas/form.schema.json",
"form": [
{
"kind": "input",
"type": "dateTimeInput",
"path": "meetingAt",
"label": "Meeting At",
"props": {
"minuteStep": 15
}
}
]
}

Use minDate / maxDate (ISO dates) and minTime / maxTime (ISO times), all inclusive, to specify the boundaries for accepted values. A completed value outside a boundary raises an input error instead of a value; customize (and localize) the messages with minDateMessage, maxDateMessage, minTimeMessage and maxTimeMessage.

datetimeinput.ts
import { gui } from '@golemui/gui-shared';
export default [
gui.inputs.dateTimeInput('meetingAt', {
hint: 'Meetings between 2026-02-01 and 2026-07-31, office hours 9:00 to 18:00',
minDate: '2026-02-01',
maxDate: '2026-07-31',
minTime: '09:00:00',
maxTime: '18:00:00',
minDateMessage: 'No meetings before February 2026',
maxDateMessage: 'No meetings after July 2026',
minTimeMessage: 'Office not open until 9:00',
maxTimeMessage: 'Office closed from 18:00',
label: 'Meeting At',
}),
];
datetimeinput.json
{
"$schema": "https://golemui.com/schemas/form.schema.json",
"form": [
{
"kind": "input",
"type": "dateTimeInput",
"path": "meetingAt",
"label": "Meeting At",
"props": {
"hint": "Meetings between 2026-02-01 and 2026-07-31, office hours 9:00 to 18:00",
"minDate": "2026-02-01",
"maxDate": "2026-07-31",
"minTime": "09:00:00",
"maxTime": "18:00:00",
"minDateMessage": "No meetings before February 2026",
"maxDateMessage": "No meetings after July 2026",
"minTimeMessage": "Office not open until 9:00",
"maxTimeMessage": "Office closed from 18:00"
}
}
]
}

Use the property invalidDateMessage to customize (and localize) the error shown when the completed date segments don’t form a real calendar date, such as February 30 or the 13th month.

datetimeinput.ts
import { gui } from '@golemui/gui-shared';
export default [
gui.inputs.dateTimeInput('meetingAt', {
hint: 'Type a date that doesn\'t exist, e.g. February 30',
invalidDateMessage: 'Please enter a real calendar date',
label: 'Meeting At',
}),
];
datetimeinput.json
{
"$schema": "https://golemui.com/schemas/form.schema.json",
"form": [
{
"kind": "input",
"type": "dateTimeInput",
"path": "meetingAt",
"label": "Meeting At",
"props": {
"hint": "Type a date that doesn't exist, e.g. February 30",
"invalidDateMessage": "Please enter a real calendar date"
}
}
]
}

Date Time Inputs can be styled as explained in the Styling Guide.

Following you will find a list with the CSS Variables and a quick description of what you will style.

CSS VariableDescription
--gui-text-defaultText color and active piece (date/time segment) visual underline color
--gui-intent-errorBorder color when invalid
--gui-border-focusBorder color when a segment is focused
--gui-shadow-focusFocus shadow
--gui-shadow-focus-errorFocus shadow when invalid

This is the anatomy of the Date Time Input Widget in case you want to use your CSS styles.

datetimeinput-anatomy.html
<gui-date-time class="gui-field">
<label class="gui-label" for="fieldUid" id="fieldUid_label">
Label
<div class="gui-widget-hint" id="fieldUid_hint">Hint</div>
</label>
<div class="gui-widget">
<!-- Segments follow the locale's order; en-US shown here -->
<div class="gui-widget-input gui-date-time-input gui-calendar--icon" role="group">
<div class="gui-date-time-input__touch-target">
<input type="text" inputmode="numeric" class="gui-date-time-input__part" data-type="month" maxlength="2" placeholder="mm" tabindex="0" value="07">
<div class="gui-date-time-input__visual-underline"></div>
</div>
<span class="gui-date-time-input__separator">/</span>
<div class="gui-date-time-input__touch-target">
<input type="text" inputmode="numeric" class="gui-date-time-input__part" data-type="day" maxlength="2" placeholder="dd" tabindex="-1" value="04">
<div class="gui-date-time-input__visual-underline"></div>
</div>
<span class="gui-date-time-input__separator">/</span>
<div class="gui-date-time-input__touch-target">
<input type="text" inputmode="numeric" class="gui-date-time-input__part gui-date-time-input__year" data-type="year" maxlength="4" placeholder="yyyy" tabindex="-1" value="2026">
<div class="gui-date-time-input__visual-underline"></div>
</div>
<span class="gui-date-time-input__separator">, </span>
<div class="gui-date-time-input__touch-target">
<input type="text" inputmode="numeric" class="gui-date-time-input__part" data-type="hour" maxlength="2" placeholder="hh" tabindex="-1" value="09">
<div class="gui-date-time-input__visual-underline"></div>
</div>
<span class="gui-date-time-input__separator">:</span>
<div class="gui-date-time-input__touch-target">
<input type="text" inputmode="numeric" class="gui-date-time-input__part" data-type="minute" maxlength="2" placeholder="mm" tabindex="-1" value="30">
<div class="gui-date-time-input__visual-underline"></div>
</div>
<!-- Only rendered in 12-hour mode, at the locale's position -->
<div class="gui-date-time-input__touch-target">
<button type="button" class="gui-date-time-input__part gui-date-time-input__dayperiod" data-type="dayPeriod" tabindex="-1" aria-label="AM/PM">AM</button>
<div class="gui-date-time-input__visual-underline"></div>
</div>
</div>
<span class="gui-widget-icon calendar_month" data-icon="calendar_month"></span>
</div>
</gui-date-time>