Date Time Picker
Date Time Picker widgets are Input Fields that let the user enter a date and a time in a single compact field: they can type it using their keyboard or open a drop-down calendar with time slots to pick both visually. The popover closes only when both the day and the time are selected, and also with the Esc key. For an always-visible inline variant, use the Date Time Calendar.
The widget emits a local ISO date-time string (YYYY-MM-DDTHH:mm:ss) — pair it with the { format: 'date-time' } validator.
import { gui } from '@golemui/gui-shared';
export default [ gui.inputs.dateTimePicker('appointmentAt', { minTime: '09:00:00', maxTime: '18:00:00', minuteStep: 30, label: 'Appointment', }),];{ "$schema": "https://golemui.com/schemas/form.schema.json", "form": [ { "kind": "input", "type": "dateTimePicker", "path": "appointmentAt", "label": "Appointment", "props": { "minTime": "09:00:00", "maxTime": "18:00:00", "minuteStep": 30 } } ]}Use these props to customize your Date Time Picker widget. It accepts the full set of date props (for the popover calendar) and time props (for the slots), all listed below.
| prop | type | description |
|---|---|---|
allowCustomTime | boolean | Allows typing a time in the popover input; when false (default) times come only from the slot grid |
disabledDateRangeMessage | string | Localizable | Error message shown when a typed date falls inside a disabled range |
disabledRanges | array | Array of { start: string, end?: string } ISO date ranges whose days render disabled |
disabledTimeRangeMessage | string | Localizable | Error message shown when a typed time falls inside a disabled time range |
disabledTimeRanges | array | { start, end, date?, weekdays? } ISO time ranges whose slots render disabled |
hint | string | A description to display below the input fields |
hourFormat | '12' | '24' | Forces 12-hour or 24-hour slot labels and typing mode; when omitted the locale decides |
icon | string | Custom icon class to display inside the input, which appears next to the toggle chevron |
invalidDateMessage | string | Localizable | Error message shown when the typed date does not exist, e.g. February 30 |
maxDate | string | Latest selectable date (ISO date, inclusive); later calendar days render disabled |
maxDateMessage | string | Localizable | Error message shown when a typed date is after maxDate |
maxTime | string | Last selectable slot (ISO time, inclusive). Defaults to 23:59:59 |
maxTimeMessage | string | Localizable | Error message shown when a typed time is after maxTime |
minDate | string | Earliest selectable date (ISO date, inclusive); earlier calendar days render disabled |
minDateMessage | string | Localizable | Error message shown when a typed date is before minDate |
minTime | string | First selectable slot (ISO time, inclusive). Defaults to 00:00:00 |
minTimeMessage | string | Localizable | Error message shown when a typed time is before minTime |
minuteStep | number | Minutes between generated slots, also the arrow-key minute increment when typing. Defaults to 30 |
nextMonthAriaLabel | string | ARIA label for the next month button |
nextMonthIcon | string | Custom CSS class for the “next month” button icon |
noAvailableTimesMessage | string | Localizable | Shown in the slot grid when minTime/maxTime generate no slots. Defaults to No available times |
numberOfMonths | number | Number of months to display side-by-side in the popover. Defaults to 1 |
prevMonthAriaLabel | string | ARIA label for the previous month button |
prevMonthIcon | string | Custom CSS class for the “previous month” button icon |
Use the property hint to add descriptive text.
import { gui } from '@golemui/gui-shared';
export default [ gui.inputs.dateTimePicker('appointmentAt', { hint: 'Pick a day first, then a time slot', minTime: '09:00:00', maxTime: '18:00:00', minuteStep: 30, label: 'Appointment', }),];{ "$schema": "https://golemui.com/schemas/form.schema.json", "form": [ { "kind": "input", "type": "dateTimePicker", "path": "appointmentAt", "label": "Appointment", "props": { "hint": "Pick a day first, then a time slot", "minTime": "09:00:00", "maxTime": "18:00:00", "minuteStep": 30 } } ]}Use the property icon to add an icon, which appears next to the toggle chevron.
import { gui } from '@golemui/gui-shared';
export default [ gui.inputs.dateTimePicker('appointmentAt', { icon: 'calendar_month', minTime: '09:00:00', maxTime: '18:00:00', minuteStep: 30, label: 'Appointment', }),];{ "$schema": "https://golemui.com/schemas/form.schema.json", "form": [ { "kind": "input", "type": "dateTimePicker", "path": "appointmentAt", "label": "Appointment", "props": { "icon": "calendar_month", "minTime": "09:00:00", "maxTime": "18:00:00", "minuteStep": 30 } } ]}Custom Icons
Section titled “Custom Icons”Use prevMonthIcon, nextMonthIcon, prevMonthAriaLabel and nextMonthAriaLabel to customize the popover calendar’s month-navigation buttons.
import { gui } from '@golemui/gui-shared';
export default [ gui.inputs.dateTimePicker('appointmentAt', { hint: 'Open the popover to see the custom month-navigation icons', prevMonthIcon: 'chevron_left', nextMonthIcon: 'chevron_right', prevMonthAriaLabel: 'Go to previous month', nextMonthAriaLabel: 'Go to next month', label: 'Appointment', }),];{ "$schema": "https://golemui.com/schemas/form.schema.json", "form": [ { "kind": "input", "type": "dateTimePicker", "path": "appointmentAt", "label": "Appointment", "props": { "hint": "Open the popover to see the custom month-navigation icons", "prevMonthIcon": "chevron_left", "nextMonthIcon": "chevron_right", "prevMonthAriaLabel": "Go to previous month", "nextMonthAriaLabel": "Go to next month" } } ]}Number of Months
Section titled “Number of Months”Use the property numberOfMonths to display multiple months side-by-side in the popover. The time input and slot grid render on the first panel only.
import { gui } from '@golemui/gui-shared';
export default [ gui.inputs.dateTimePicker('appointmentAt', { hint: 'The popover shows two months side by side', numberOfMonths: 2, label: 'Appointment', }),];{ "$schema": "https://golemui.com/schemas/form.schema.json", "form": [ { "kind": "input", "type": "dateTimePicker", "path": "appointmentAt", "label": "Appointment", "props": { "hint": "The popover shows two months side by side", "numberOfMonths": 2 } } ]}Custom Time
Section titled “Custom Time”Use the property allowCustomTime to let the user type any time directly in the input, in addition to picking a slot. Typed times are still validated against minTime and maxTime; customize (and localize) the messages with minTimeMessage and maxTimeMessage.
import { gui } from '@golemui/gui-shared';
export default [ gui.inputs.dateTimePicker('appointmentAt', { hint: 'Type any time between 9:00 and 18:00 or pick a 30m slot', allowCustomTime: true, minTime: '09:00:00', maxTime: '18:00:00', minuteStep: 30, minTimeMessage: 'Office not open until 9:00', maxTimeMessage: 'Office closed from 18:00', label: 'Appointment', }),];{ "$schema": "https://golemui.com/schemas/form.schema.json", "form": [ { "kind": "input", "type": "dateTimePicker", "path": "appointmentAt", "label": "Appointment", "props": { "hint": "Type any time between 9:00 and 18:00 or pick a 30m slot", "allowCustomTime": true, "minTime": "09:00:00", "maxTime": "18:00:00", "minuteStep": 30, "minTimeMessage": "Office not open until 9:00", "maxTimeMessage": "Office closed from 18:00" } } ]}Hour Format
Section titled “Hour Format”Use the property hourFormat to force '12'-hour (AM/PM) or '24'-hour slot labels and typing mode. When omitted, the user’s locale decides.
import { gui } from '@golemui/gui-shared';
export default [ gui.inputs.dateTimePicker('appointmentAt', { hint: '12-hour slot labels and typing (AM/PM)', hourFormat: '12', minTime: '09:00:00', maxTime: '18:00:00', minuteStep: 30, label: 'Appointment', }),];{ "$schema": "https://golemui.com/schemas/form.schema.json", "form": [ { "kind": "input", "type": "dateTimePicker", "path": "appointmentAt", "label": "Appointment", "props": { "hint": "12-hour slot labels and typing (AM/PM)", "hourFormat": "12", "minTime": "09:00:00", "maxTime": "18:00:00", "minuteStep": 30 } } ]}Disabled Date and Time Ranges
Section titled “Disabled Date and Time Ranges”Use minDate / maxDate and disabledRanges to grey out days, and minTime / maxTime and disabledTimeRanges to grey out time slots. Each disabledTimeRanges entry can be scoped to specific days with date (an ISO date) or weekdays (numbers as returned by Date.prototype.getDay(): 0 = Sunday … 6 = Saturday); an unscoped entry applies every day. Typed values that violate a boundary raise an input error whose messages you can customize (and localize) with the corresponding *Message props (minDateMessage, maxDateMessage, disabledDateRangeMessage, minTimeMessage, maxTimeMessage and disabledTimeRangeMessage).
import { gui } from '@golemui/gui-shared';
export default [ gui.inputs.dateTimePicker('appointmentAt', { hint: 'Weekday lunch break disabled, plus the morning of 2026-02-13', icon: 'calendar_month', allowCustomTime: true, minTime: '09:00:00', maxTime: '18:00:00', minuteStep: 30, minDate: '2026-02-01', maxDate: '2026-07-31', disabledRanges: [ { start: '2026-02-09', end: '2026-02-10', }, { start: '2026-02-17', }, ], disabledTimeRanges: [ { start: '13:00:00', end: '14:00:00', weekdays: [1, 2, 3, 4, 5], }, { start: '09:00:00', end: '10:30:00', date: '2026-02-13', }, ], minDateMessage: 'No appointments before February 2026', maxDateMessage: 'No appointments after July 2026', disabledDateRangeMessage: 'This day is not available', minTimeMessage: 'Office not open until 9:00', maxTimeMessage: 'Office closed from 18:00', disabledTimeRangeMessage: 'This time is not available', label: 'Appointment', defaultValue: '2026-02-16T09:30:00', }),];{ "$schema": "https://golemui.com/schemas/form.schema.json", "form": [ { "kind": "input", "type": "dateTimePicker", "path": "appointmentAt", "label": "Appointment", "defaultValue": "2026-02-16T09:30:00", "props": { "hint": "Weekday lunch break disabled, plus the morning of 2026-02-13", "icon": "calendar_month", "allowCustomTime": true, "minTime": "09:00:00", "maxTime": "18:00:00", "minuteStep": 30, "minDate": "2026-02-01", "maxDate": "2026-07-31", "disabledRanges": [ { "start": "2026-02-09", "end": "2026-02-10" }, { "start": "2026-02-17" } ], "disabledTimeRanges": [ { "start": "13:00:00", "end": "14:00:00", "weekdays": [ 1, 2, 3, 4, 5 ] }, { "start": "09:00:00", "end": "10:30:00", "date": "2026-02-13" } ], "minDateMessage": "No appointments before February 2026", "maxDateMessage": "No appointments after July 2026", "disabledDateRangeMessage": "This day is not available", "minTimeMessage": "Office not open until 9:00", "maxTimeMessage": "Office closed from 18:00", "disabledTimeRangeMessage": "This time is not available" } } ]}No Available Times
Section titled “No Available Times”When minTime and maxTime generate no slots for the chosen day, the popover’s slot grid shows an empty-state message. Use noAvailableTimesMessage to customize (and localize) it (it defaults to No available times).
import { gui } from '@golemui/gui-shared';
export default [ gui.inputs.dateTimePicker('appointmentAt', { hint: 'These bounds generate no slots, so the grid shows the empty-state message', minTime: '18:00:00', maxTime: '09:00:00', noAvailableTimesMessage: 'No slots available for this day', label: 'Appointment', }),];{ "$schema": "https://golemui.com/schemas/form.schema.json", "form": [ { "kind": "input", "type": "dateTimePicker", "path": "appointmentAt", "label": "Appointment", "props": { "hint": "These bounds generate no slots, so the grid shows the empty-state message", "minTime": "18:00:00", "maxTime": "09:00:00", "noAvailableTimesMessage": "No slots available for this day" } } ]}Invalid Date
Section titled “Invalid Date”Use the property invalidDateMessage to customize (and localize) the error shown when the typed 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.dateTimePicker('appointmentAt', { hint: 'Type a date that doesn\'t exist, e.g. February 30', invalidDateMessage: 'Please enter a real calendar date', label: 'Appointment', }),];{ "$schema": "https://golemui.com/schemas/form.schema.json", "form": [ { "kind": "input", "type": "dateTimePicker", "path": "appointmentAt", "label": "Appointment", "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 Pickers can be styled as explained in the Styling Guide. The typed field, the popover calendar, and the time slot grid each have their own styling variables — the calendar and slot variables are listed under the Date Time Calendar CSS variables.
Anatomy
Section titled “Anatomy”This is the anatomy of the Date Time Picker Widget in case you want to use your CSS styles.
<gui-date-time-picker class="gui-date-time-picker gui-field"> <label class="gui-label" for="fieldUid" id="fieldUid_label"> Label <div class="gui-widget-hint" id="fieldUid_hint">Hint</div> </label>
<div role="button" tabindex="-1" class="gui-widget" aria-expanded="false"> <!-- The typing surface is a Date Time Input --> <gui-date-time id="date-input" class="gui-calendar--icon"> <div class="gui-widget"> <div class="gui-widget-input gui-date-time-input" role="group"> <!-- See the Date Time Input anatomy: locale-ordered date and time segments --> </div> <span class="gui-widget-icon calendar_month" data-icon="calendar_month"></span> </div> </gui-date-time>
<span class="gui-date-time-picker__arrow"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 256 256"><path d="..."></path></svg> </span>
<!-- Popover calendar with the embedded time picker --> <gui-date-time-calendar> <!-- See the Date Time Calendar anatomy --> </gui-date-time-calendar> </div></gui-date-time-picker>