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.
import { gui } from '@golemui/gui-shared';
export default [ gui.inputs.dateTimeInput('meetingAt', { label: 'Meeting At', }),];{ "$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 (59 → 00). 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.
| prop | type | description |
|---|---|---|
hint | string | A description to display below the segmented inputs |
hourFormat | '12' | '24' | Forces 12-hour or 24-hour mode; when omitted the locale decides |
icon | string | A css class to display an icon inside the input |
invalidDateMessage | string | Localizable | Error message shown when the completed date does not exist, e.g. February 30 |
maxDate | string | Latest allowed date (ISO date, inclusive) |
maxDateMessage | string | Localizable | Error message shown when the entered date is after maxDate |
maxTime | string | Last allowed time (ISO time, inclusive) |
maxTimeMessage | string | Localizable | Error message shown when the entered time is after maxTime |
minDate | string | Earliest allowed date (ISO date, inclusive) |
minDateMessage | string | Localizable | Error message shown when the entered date is before minDate |
minTime | string | First allowed time (ISO time, inclusive) |
minTimeMessage | string | Localizable | Error message shown when the entered time is before minTime |
minuteStep | number | The ArrowUp/ArrowDown increment of the minute segment (default: 1) |
Use the property hint to add a description or validation instructions.
import { gui } from '@golemui/gui-shared';
export default [ gui.inputs.dateTimeInput('meetingAt', { hint: 'Please enter the meeting date and start time', label: 'Meeting At', }),];{ "$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.
import { gui } from '@golemui/gui-shared';
export default [ gui.inputs.dateTimeInput('meetingAt', { icon: 'calendar_month', label: 'Meeting At', }),];{ "$schema": "https://golemui.com/schemas/form.schema.json", "form": [ { "kind": "input", "type": "dateTimeInput", "path": "meetingAt", "label": "Meeting At", "props": { "icon": "calendar_month" } } ]}Hour Format
Section titled “Hour Format”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.
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)', }),];{ "$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" } } ]}Minute Step
Section titled “Minute Step”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.
import { gui } from '@golemui/gui-shared';
export default [ gui.inputs.dateTimeInput('meetingAt', { minuteStep: 15, label: 'Meeting At', }),];{ "$schema": "https://golemui.com/schemas/form.schema.json", "form": [ { "kind": "input", "type": "dateTimeInput", "path": "meetingAt", "label": "Meeting At", "props": { "minuteStep": 15 } } ]}Min and Max Boundaries
Section titled “Min and Max Boundaries”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.
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', }),];{ "$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" } } ]}Invalid Date
Section titled “Invalid Date”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.
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', }),];{ "$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" } } ]}Styling
Section titled “Styling”Date Time Inputs can be styled as explained in the Styling Guide.
CSS Variables
Section titled “CSS Variables”Following you will find a list with the CSS Variables and a quick description of what you will style.
| CSS Variable | Description |
|---|---|
--gui-text-default | Text color and active piece (date/time segment) visual underline color |
--gui-intent-error | Border color when invalid |
--gui-border-focus | Border color when a segment is focused |
--gui-shadow-focus | Focus shadow |
--gui-shadow-focus-error | Focus shadow when invalid |
Anatomy
Section titled “Anatomy”This is the anatomy of the Date Time Input Widget in case you want to use your CSS styles.
<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>