Date-time input
<gui-date-time> is a date and time field typed part by part: the day, month and year of a
Date input, then the hour, minute and AM/PM of a
Time input, in one field. Its value is a local ISO date-time,
such as 2026-10-05T18:45:00. To pick it from a calendar and a list of times too, use the
Date-time picker.
import { GuiDateTime } from '@golemui/gui-components/react';import '@golemui/gui-components/index.css';
export function DateTimeBasic() { return <GuiDateTime label="Departure" />;}import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';import '@golemui/gui-components/date-time-input';
@Component({ selector: 'app-date-time-basic', schemas: [CUSTOM_ELEMENTS_SCHEMA], template: `<gui-date-time label="Departure"></gui-date-time>`,})export class DateTimeBasicComponent {}<script setup lang="ts">import '@golemui/gui-components/date-time-input';import '@golemui/gui-components/index.css';</script>
<template> <gui-date-time label="Departure"></gui-date-time></template>import { LitElement, html } from 'lit';import { customElement } from 'lit/decorators.js';import '@golemui/gui-components/date-time-input';import '@golemui/gui-components/index.css';
@customElement('date-time-basic')export class DateTimeBasic extends LitElement { protected override createRenderRoot() { return this; }
override render() { return html`<gui-date-time label="Departure"></gui-date-time>`; }}<gui-date-time label="Departure"></gui-date-time>The element’s entry point is @golemui/gui-components/date-time-input, which registers
<gui-date-time> and nothing else. To install the package and load the stylesheet, see
Installation.
The @golemui/gui-components/react components have typed props and an on* prop for each event. React 18 or later.
import { useState } from 'react';import { GuiDateTime } from '@golemui/gui-components/react';import '@golemui/gui-components/index.css';
export function DepartureField() { const [departure, setDeparture] = useState('');
return ( <GuiDateTime label="Departure" name="departure" value={departure} onGuiChange={(event) => setDeparture(event.detail.value ?? '')} /> );}Add CUSTOM_ELEMENTS_SCHEMA to the component that uses the tags, and the stylesheet to styles in angular.json.
import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';import type { GuiEventMap, GuiDateTimeEvents } from '@golemui/gui-components';import '@golemui/gui-components/date-time-input';
type ChangeEvent = GuiEventMap<typeof GuiDateTimeEvents>['gui-change'];
@Component({ selector: 'app-departure-field', schemas: [CUSTOM_ELEMENTS_SCHEMA], template: ` <gui-date-time label="Departure" name="departure" [value]="departure" (gui-change)="onChange($event)" ></gui-date-time> `,})export class DepartureFieldComponent { departure = '';
onChange(event: Event) { this.departure = (event as ChangeEvent).detail.value ?? ''; }}"styles": ["node_modules/@golemui/gui-components/lib/styles/index.css"]Tell Vue's compiler that gui-* tags are custom elements, and add the typings once for typed props and @gui-* handlers.
<script setup lang="ts">import { ref } from 'vue';import '@golemui/gui-components/date-time-input';import '@golemui/gui-components/index.css';
const departure = ref('');</script>
<template> <gui-date-time label="Departure" name="departure" :value="departure" @gui-change="departure = $event.detail.value ?? ''" /></template>vue({ template: { compilerOptions: { isCustomElement: (tag) => tag.startsWith('gui-') } },});import type {} from '@golemui/gui-components/vue';The page's stylesheet styles the gui-* elements, so it only reaches them outside a shadow root. Render the host component into the light DOM too, as below, or load the stylesheet into its shadow root.
import { LitElement, html } from 'lit';import { customElement, state } from 'lit/decorators.js';import '@golemui/gui-components/date-time-input';import '@golemui/gui-components/index.css';
@customElement('departure-field')export class DepartureField extends LitElement { @state() private departure = '';
protected override createRenderRoot() { return this; }
override render() { return html` <gui-date-time label="Departure" name="departure" .value=${this.departure} @gui-change=${(event: CustomEvent) => (this.departure = event.detail.value)} ></gui-date-time> `; }}With any bundler, such as Vite. Import the element once, anywhere, and use the tag in your markup.
<gui-date-time label="Departure" name="departure"></gui-date-time>
<script type="module" src="./main.js"></script>import '@golemui/gui-components/date-time-input';import '@golemui/gui-components/index.css';
const element = document.querySelector('gui-date-time');
element.addEventListener('gui-change', (event) => { console.log(event.detail.value);});Properties
| Property | Type | Default | Description |
|---|---|---|---|
localeId
attribute locale-id | string | – | BCP 47 locale for formatting and parsing, such as en-US or es. |
showErrors
attribute show-errors | boolean | true | Whether the element renders its own error list. Elements that embed it turn it off and show the errors themselves. |
showHint
attribute show-hint | boolean | true | Whether the element renders its hint. Elements that embed it turn it off and show the hint themselves: aria-describedby still points at the hint by its id. |
icon | string | '' | Icon class name shown inside the control, for example from an icon font. |
dayAriaLabel
attribute day-aria-label | string | – | Accessible name of the day part. An empty value keeps the default. |
monthAriaLabel
attribute month-aria-label | string | – | Accessible name of the month part. An empty value keeps the default. |
yearAriaLabel
attribute year-aria-label | string | – | Accessible name of the year part. An empty value keeps the default. |
hourAriaLabel
attribute hour-aria-label | string | – | Accessible name of the hour part. An empty value keeps the default. |
minuteAriaLabel
attribute minute-aria-label | string | – | Accessible name of the minute part. An empty value keeps the default. |
dayPeriodAriaLabel
attribute day-period-aria-label | string | – | Accessible name of the AM/PM part. An empty value keeps the default. |
hourFormat
attribute hour-format | HourFormat | – | 12- or 24-hour clock. Defaults to the locale's. |
minuteStep
attribute minute-step | number | 1 | Minutes between the times offered in the list. |
invalidDateMessage
attribute invalid-date-message | string | – | Error for a complete but impossible date, such as February 31. |
value | string | – | The date and time, as an ISO date-time (YYYY-MM-DDTHH:mm:ss). |
minDate
attribute min-date | string | – | Earliest selectable date, as an ISO date (YYYY-MM-DD). |
maxDate
attribute max-date | string | – | Latest selectable date, as an ISO date (YYYY-MM-DD). |
minTime
attribute min-time | string | – | Earliest selectable time, as an ISO time (HH:mm:ss). |
maxTime
attribute max-time | string | – | Latest selectable time, as an ISO time (HH:mm:ss). |
minDateMessage
attribute min-date-message | string | – | Error for a date before minDate. |
maxDateMessage
attribute max-date-message | string | – | Error for a date after maxDate. |
minTimeMessage
attribute min-time-message | string | – | Error for a time before minTime. |
maxTimeMessage
attribute max-time-message | string | – | Error for a time after maxTime. |
incompleteMessage
attribute incomplete-message | string | – | Error when focus leaves a partly filled value. |
uid | string | – | The id of the element's control. The ids of its label, hint and errors derive from it. Optional: when it is not set, the element generates one from its tag name and a page-wide counter, e.g. gui-textinput-3. Generated ids depend on creation order, so a server-rendered element must set uid or its ids will not match after hydration. |
Form control properties
Every field has these, from the base class of the form controls.
| Property | Type | Default | Description |
|---|---|---|---|
name | string | – | The name the value is submitted under. Without it the element stays out of its form. Reflected, like a native control's: the form reads a single value's name from the attribute. |
label | string | – | The visible label, which also names the control for assistive technology. Without one the control has no accessible name; the date, time, range, tags and file fields warn about it in development builds. |
hint | string | – | Help text shown under the label and announced as the control's description. |
errors | string[] | [] | Error messages to show, typically from your own validation. They show as soon as they are set, unless touched is false. |
touched | boolean | – | Whether the user has interacted with the control. Leave it unset unless you validate on interaction: false holds errors back until it becomes true. |
required | boolean | false | The control needs a value: it is marked as required and, with a name, blocks submission. |
readOnly
attribute readonly | boolean | – | The value can be read and focused but not changed. |
disabled | boolean | – | Disabled by its own attribute or by a disabled <fieldset> around it. Setting the property sets the attribute, like a native control's. |
form read-only, no attribute | HTMLFormElement | null | – | The <form> the element belongs to, if any. |
validity read-only, no attribute | ValidityState | – | The element's validity, like a native control's. |
validationMessage read-only, no attribute | string | – | The message the browser shows for an invalid value. |
Methods
| Method | Description |
|---|---|
checkValidity(): boolean | – |
reportValidity(): boolean | – |
Events
Every event bubbles and is composed, so you can listen on any ancestor.
| Event | Description |
|---|---|
gui-input | The user changed the value. detail.value is the new value. |
gui-change | The user committed the value. detail.value is the committed value. |
gui-blur | Focus left the control. |
gui-focus | One of the parts of the field received focus. |
gui-input-error | The element rejected what the user entered, such as an impossible date or a value out of bounds. detail.message is the error; show it through errors. |
gui-parts-change | The typed parts changed before they form a complete value, for a host that mirrors them. |
Examples
Section titled “Examples”Value and events
Section titled “Value and events”value takes a local ISO date-time, YYYY-MM-DDTHH:mm:ss, with no time zone, on a 24-hour clock
whatever the field shows. A typed value always has 00 seconds. The element fires gui-input and
then gui-change as soon as every part is filled, with the date-time in event.detail.value.
When the user clears a part, the value becomes empty and both events fire with null.
Value: 2026-11-30T09:30:00
import { useState } from 'react';import { GuiDateTime } from '@golemui/gui-components/react';import '@golemui/gui-components/index.css';
export function DateTimeValue() { const [value, setValue] = useState<string | undefined>('2026-11-30T09:30:00');
return ( <> <GuiDateTime id="date-time-launch" label="Launch" value={value} onGuiChange={(event) => setValue(event.detail.value)} /> <p role="status">Value: {value}</p> </> );}import { Component, CUSTOM_ELEMENTS_SCHEMA, signal } from '@angular/core';import type { GuiDateTimeEvents, GuiEventMap } from '@golemui/gui-components';import '@golemui/gui-components/date-time-input';
type DateTimeEvent<K extends keyof typeof GuiDateTimeEvents> = GuiEventMap< typeof GuiDateTimeEvents>[K];
@Component({ selector: 'app-date-time-value', schemas: [CUSTOM_ELEMENTS_SCHEMA], template: ` <gui-date-time id="date-time-launch" label="Launch" [value]="value()" (gui-change)="onChange($event)" ></gui-date-time> <p id="date-time-launch-value" role="status">Value: {{ value() }}</p> `,})export class DateTimeValueComponent { value = signal<string | undefined>('2026-11-30T09:30:00');
onChange(event: Event) { this.value.set((event as DateTimeEvent<'gui-change'>).detail.value); }}<script setup lang="ts">import { ref } from 'vue';import '@golemui/gui-components/date-time-input';import '@golemui/gui-components/index.css';
const value = ref<string | undefined>('2026-11-30T09:30:00');</script>
<template> <gui-date-time id="date-time-launch" label="Launch" :value="value" @gui-change="value = $event.detail.value" ></gui-date-time> <p id="date-time-launch-value" role="status">Value: {{ value }}</p></template>import { LitElement, html } from 'lit';import { customElement, state } from 'lit/decorators.js';import type { GuiDateTimeEvents, GuiEventMap } from '@golemui/gui-components';import '@golemui/gui-components/date-time-input';import '@golemui/gui-components/index.css';
type DateTimeEvent<K extends keyof typeof GuiDateTimeEvents> = GuiEventMap< typeof GuiDateTimeEvents>[K];
@customElement('date-time-value')export class DateTimeValue extends LitElement { @state() private value: string | undefined = '2026-11-30T09:30:00';
protected override createRenderRoot() { return this; }
private onChange(event: DateTimeEvent<'gui-change'>) { this.value = event.detail.value; }
override render() { return html` <gui-date-time id="date-time-launch" label="Launch" .value=${this.value} @gui-change=${this.onChange} ></gui-date-time> <p role="status">Value: ${this.value}</p> `; }}<gui-date-time id="date-time-launch" label="Launch" value="2026-11-30T09:30:00"></gui-date-time><p id="date-time-launch-value" role="status">Value: 2026-11-30T09:30:00</p>
<script type="module"> const launch = document.querySelector('#date-time-launch');
launch.addEventListener('gui-change', (event) => { document.querySelector('#date-time-launch-value').textContent = `Value: ${event.detail.value}`; });</script>Locale and clock
Section titled “Locale and clock”locale-id takes a BCP 47 locale, such as en-US or en-GB. It sets the order of the date
parts, the separators, the clock and the AM/PM labels. hour-format, 12 or 24, sets the clock
whatever the locale. Without either, the field follows English: month, day, year, and a 12-hour
clock.
import { GuiDateTime } from '@golemui/gui-components/react';import '@golemui/gui-components/index.css';
export function DateTimeLocale() { return ( <div className="gui-grid gui-grid--row"> <div className="gui-grid__cell"> <GuiDateTime label="United States" localeId="en-US" value="2026-07-04T18:45:00" /> </div> <div className="gui-grid__cell"> <GuiDateTime label="United Kingdom" localeId="en-GB" value="2026-07-04T18:45:00" /> </div> </div> );}import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';import '@golemui/gui-components/date-time-input';
@Component({ selector: 'app-date-time-locale', schemas: [CUSTOM_ELEMENTS_SCHEMA], template: ` <div class="gui-grid gui-grid--row"> <div class="gui-grid__cell"> <gui-date-time label="United States" locale-id="en-US" value="2026-07-04T18:45:00" ></gui-date-time> </div> <div class="gui-grid__cell"> <gui-date-time label="United Kingdom" locale-id="en-GB" value="2026-07-04T18:45:00" ></gui-date-time> </div> </div> `,})export class DateTimeLocaleComponent {}<script setup lang="ts">import '@golemui/gui-components/date-time-input';import '@golemui/gui-components/index.css';</script>
<template> <div class="gui-grid gui-grid--row"> <div class="gui-grid__cell"> <gui-date-time label="United States" locale-id="en-US" value="2026-07-04T18:45:00" ></gui-date-time> </div> <div class="gui-grid__cell"> <gui-date-time label="United Kingdom" locale-id="en-GB" value="2026-07-04T18:45:00" ></gui-date-time> </div> </div></template>import { LitElement, html } from 'lit';import { customElement } from 'lit/decorators.js';import '@golemui/gui-components/date-time-input';import '@golemui/gui-components/index.css';
@customElement('date-time-locale')export class DateTimeLocale extends LitElement { protected override createRenderRoot() { return this; }
override render() { return html` <div class="gui-grid gui-grid--row"> <div class="gui-grid__cell"> <gui-date-time label="United States" locale-id="en-US" value="2026-07-04T18:45:00" ></gui-date-time> </div> <div class="gui-grid__cell"> <gui-date-time label="United Kingdom" locale-id="en-GB" value="2026-07-04T18:45:00" ></gui-date-time> </div> </div> `; }}<div class="gui-grid gui-grid--row"> <div class="gui-grid__cell"> <gui-date-time label="United States" locale-id="en-US" value="2026-07-04T18:45:00"></gui-date-time> </div> <div class="gui-grid__cell"> <gui-date-time label="United Kingdom" locale-id="en-GB" value="2026-07-04T18:45:00"></gui-date-time> </div></div>minute-step sets how many minutes the arrow keys add to the minute part, as on the
Time input.
Bounds
Section titled “Bounds”min-date and max-date bound the day, and min-time and max-time the time on every day. All
four are inclusive, the dates as ISO dates and the times as ISO times. A value outside them is
still entered: the element keeps it, marks it as invalid for its form and fires gui-input-error
with the reason. Show it with errors, as below. Type a time after 6:00 PM to see it.
import { useState } from 'react';import { GuiDateTime } from '@golemui/gui-components/react';import '@golemui/gui-components/index.css';
export function DateTimeBounds() { const [errors, setErrors] = useState<string[]>([]);
return ( <GuiDateTime id="date-time-viewing" label="Viewing" hint="Any day in 2027, between 10:00 AM and 6:00 PM." minDate="2027-01-01" maxDate="2027-12-31" minTime="10:00:00" maxTime="18:00:00" errors={errors} // The element reports what it rejects; show it with errors. onGuiInputError={(event) => setErrors([event.detail.message])} onGuiInput={() => setErrors([])} /> );}import { Component, CUSTOM_ELEMENTS_SCHEMA, signal } from '@angular/core';import type { GuiDateTimeEvents, GuiEventMap } from '@golemui/gui-components';import '@golemui/gui-components/date-time-input';
type DateTimeEvent<K extends keyof typeof GuiDateTimeEvents> = GuiEventMap< typeof GuiDateTimeEvents>[K];
@Component({ selector: 'app-date-time-bounds', schemas: [CUSTOM_ELEMENTS_SCHEMA], template: ` <gui-date-time id="date-time-viewing" label="Viewing" hint="Any day in 2027, between 10:00 AM and 6:00 PM." min-date="2027-01-01" max-date="2027-12-31" min-time="10:00:00" max-time="18:00:00" [errors]="errors()" (gui-input-error)="onInputError($event)" (gui-input)="errors.set([])" ></gui-date-time> `,})export class DateTimeBoundsComponent { errors = signal<string[]>([]);
// The element reports what it rejects; show it with errors. onInputError(event: Event) { this.errors.set([ (event as DateTimeEvent<'gui-input-error'>).detail.message, ]); }}<script setup lang="ts">import { ref } from 'vue';import '@golemui/gui-components/date-time-input';import '@golemui/gui-components/index.css';
const errors = ref<string[]>([]);</script>
<template> <!-- The element reports what it rejects; show it with errors. --> <gui-date-time id="date-time-viewing" label="Viewing" hint="Any day in 2027, between 10:00 AM and 6:00 PM." min-date="2027-01-01" max-date="2027-12-31" min-time="10:00:00" max-time="18:00:00" :errors.prop="errors" @gui-input-error="errors = [$event.detail.message]" @gui-input="errors = []" ></gui-date-time></template>import { LitElement, html } from 'lit';import { customElement, state } from 'lit/decorators.js';import type { GuiDateTimeEvents, GuiEventMap } from '@golemui/gui-components';import '@golemui/gui-components/date-time-input';import '@golemui/gui-components/index.css';
type DateTimeEvent<K extends keyof typeof GuiDateTimeEvents> = GuiEventMap< typeof GuiDateTimeEvents>[K];
@customElement('date-time-bounds')export class DateTimeBounds extends LitElement { @state() private errors: string[] = [];
protected override createRenderRoot() { return this; }
// The element reports what it rejects; show it with errors. private onInputError(event: DateTimeEvent<'gui-input-error'>) { this.errors = [event.detail.message]; }
private onInput() { this.errors = []; }
override render() { return html` <gui-date-time id="date-time-viewing" label="Viewing" hint="Any day in 2027, between 10:00 AM and 6:00 PM." min-date="2027-01-01" max-date="2027-12-31" min-time="10:00:00" max-time="18:00:00" .errors=${this.errors} @gui-input-error=${this.onInputError} @gui-input=${this.onInput} ></gui-date-time> `; }}<gui-date-time id="date-time-viewing" label="Viewing" hint="Any day in 2027, between 10:00 AM and 6:00 PM." min-date="2027-01-01" max-date="2027-12-31" min-time="10:00:00" max-time="18:00:00"></gui-date-time>
<script type="module"> const viewing = document.querySelector('#date-time-viewing');
// The element reports what it rejects; show it with errors. viewing.addEventListener('gui-input-error', (event) => { viewing.errors = [event.detail.message]; }); viewing.addEventListener('gui-input', () => { viewing.errors = []; });</script>gui-input-error also fires for an impossible date, such as February 31, and when focus leaves a
partly filled field. Replace the English messages with min-date-message, max-date-message,
min-time-message, max-time-message, invalid-date-message and incomplete-message, or
translate them for every element as in i18n.
disabled, readonly and icon work as on the
Date input.
In a form
Section titled “In a form”With a name, <gui-date-time> submits its ISO date-time under that name, such as
startsAt=2026-11-30T09:30:00, and nothing while it is empty. These block a submit:
required, while the field is empty;- a day before
min-dateor aftermax-date; - a time before
min-timeor aftermax-time; - an impossible date, such as February 31.
Submit the empty field, then try a time after 20:00.
import { useState } from 'react';import { GuiButton, GuiDateTime } from '@golemui/gui-components/react';import '@golemui/gui-components/index.css';
export function DateTimeNativeForm() { const [result, setResult] = useState('');
return ( <form id="date-time-form" onSubmit={(event) => { event.preventDefault(); const data = Object.fromEntries(new FormData(event.currentTarget)); setResult(`Submitted ${JSON.stringify(data)}`); }} > <div className="gui-grid gui-grid--row"> <div className="gui-grid__cell gui-grid__cell--span-3"> <GuiDateTime label="Starts" name="startsAt" localeId="en-GB" minTime="08:00:00" maxTime="20:00:00" required /> </div> <div className="gui-grid__cell"> <GuiButton type="submit" label="Schedule" /> </div> </div> <p role="status">{result}</p> </form> );}import { Component, CUSTOM_ELEMENTS_SCHEMA, signal } from '@angular/core';import '@golemui/gui-components/button';import '@golemui/gui-components/date-time-input';
@Component({ selector: 'app-date-time-native-form', schemas: [CUSTOM_ELEMENTS_SCHEMA], template: ` <form id="date-time-form" #form (submit)="onSubmit($event, form)"> <div class="gui-grid gui-grid--row"> <div class="gui-grid__cell gui-grid__cell--span-3"> <gui-date-time label="Starts" name="startsAt" locale-id="en-GB" min-time="08:00:00" max-time="20:00:00" required ></gui-date-time> </div> <div class="gui-grid__cell"> <gui-button type="submit" label="Schedule"></gui-button> </div> </div> <p id="date-time-form-result" role="status">{{ result() }}</p> </form> `,})export class DateTimeNativeFormComponent { result = signal('');
onSubmit(event: Event, form: HTMLFormElement) { event.preventDefault(); const data = Object.fromEntries(new FormData(form)); this.result.set(`Submitted ${JSON.stringify(data)}`); }}<script setup lang="ts">import { ref, useTemplateRef } from 'vue';import '@golemui/gui-components/button';import '@golemui/gui-components/date-time-input';import '@golemui/gui-components/index.css';
const form = useTemplateRef('form');const result = ref('');
function onSubmit() { if (!form.value) return; const data = Object.fromEntries(new FormData(form.value)); result.value = `Submitted ${JSON.stringify(data)}`;}</script>
<template> <form id="date-time-form" ref="form" @submit.prevent="onSubmit"> <div class="gui-grid gui-grid--row"> <div class="gui-grid__cell gui-grid__cell--span-3"> <gui-date-time label="Starts" name="startsAt" locale-id="en-GB" min-time="08:00:00" max-time="20:00:00" :required="true" ></gui-date-time> </div> <div class="gui-grid__cell"> <gui-button type="submit" label="Schedule"></gui-button> </div> </div> <p id="date-time-form-result" role="status">{{ result }}</p> </form></template>import { LitElement, html } from 'lit';import { customElement, query, state } from 'lit/decorators.js';import '@golemui/gui-components/button';import '@golemui/gui-components/date-time-input';import '@golemui/gui-components/index.css';
@customElement('date-time-native-form')export class DateTimeNativeForm extends LitElement { @query('form') private form!: HTMLFormElement; @state() private data?: Record<string, FormDataEntryValue>;
protected override createRenderRoot() { return this; }
private onSubmit(event: SubmitEvent) { event.preventDefault(); this.data = Object.fromEntries(new FormData(this.form)); }
override render() { return html` <form id="date-time-form" @submit=${this.onSubmit}> <div class="gui-grid gui-grid--row"> <div class="gui-grid__cell gui-grid__cell--span-3"> <gui-date-time label="Starts" name="startsAt" locale-id="en-GB" min-time="08:00:00" max-time="20:00:00" required ></gui-date-time> </div> <div class="gui-grid__cell"> <gui-button type="submit" label="Schedule"></gui-button> </div> </div> <p role="status"> ${this.data && `Submitted ${JSON.stringify(this.data)}`} </p> </form> `; }}<form id="date-time-form"> <div class="gui-grid gui-grid--row"> <div class="gui-grid__cell gui-grid__cell--span-3"> <gui-date-time label="Starts" name="startsAt" locale-id="en-GB" min-time="08:00:00" max-time="20:00:00" required ></gui-date-time> </div> <div class="gui-grid__cell"> <gui-button type="submit" label="Schedule"></gui-button> </div> </div> <p id="date-time-form-result" role="status"></p></form>
<script type="module"> const form = document.querySelector('#date-time-form');
form.addEventListener('submit', (event) => { event.preventDefault(); const data = Object.fromEntries(new FormData(form)); document.querySelector('#date-time-form-result').textContent = `Submitted ${JSON.stringify(data)}`; });</script>How the elements submit, validate and reset is in Native forms.
Styling
Section titled “Styling”Anatomy
Section titled “Anatomy”<gui-date-time> renders into the light DOM, so you can style every part with plain CSS. These
are the parts and their public classes, here with en-US parts:
<gui-date-time class="gui-field"> <span class="gui-label" id="departure_label"> <span class="gui-label__text">Departure</span> </span> <div class="gui-widget"> <div role="group" id="departure" class="gui-widget-input gui-parts gui-parts-ring gui-date-time-input" aria-labelledby="departure_label" > <div class="gui-parts__touch-target gui-date-time-input__touch-target"> <input type="text" inputmode="numeric" role="spinbutton" class="gui-parts__part gui-date-time-input__part" data-type="month" maxlength="2" placeholder="mm" tabindex="0" aria-label="Month" aria-valuemin="1" aria-valuemax="12" aria-valuenow="10" /> <div class="gui-parts__visual-underline gui-date-time-input__visual-underline" ></div> </div> <span class="gui-date-time-input__separator">/</span> <!-- The day and the year (with gui-parts__year gui-date-time-input__year) --> <span class="gui-date-time-input__separator">, </span> <div dir="ltr" class="gui-parts__time-cluster gui-date-time-input__time-cluster" > <!-- The hour, a ":" separator and the minute --> </div> <span class="gui-date-time-input__separator"> </span> <div class="gui-parts__touch-target gui-date-time-input__touch-target"> <button type="button" class="gui-parts__part gui-parts__dayperiod gui-date-time-input__part gui-date-time-input__dayperiod" data-type="dayPeriod" tabindex="-1" aria-label="AM/PM" > AM </button> <div class="gui-parts__visual-underline gui-date-time-input__visual-underline" ></div> </div> </div> </div></gui-date-time>The classes are those of the Date input and the
Time input, with the block gui-date-time-input:
gui-date-time-input__part, __touch-target, __year, __separator, __time-cluster,
__dayperiod and __visual-underline, next to the shared gui-parts classes. The ids derive
from uid, or from a generated id when you don’t set one.
Tokens
Section titled “Tokens”The field reads the same design tokens as the Date input.
Set them on :root to change every field, or on any element to change the fields inside it.
/* Taller date-time fields in one form only. */.schedule gui-date-time { --gui-widget-size: 48px;}To restyle beyond the tokens, see Overriding styles; for dark mode and the Clay theme, see Themes and dark mode.
Accessibility
Section titled “Accessibility”- Name. The parts sit in a group that the
labelnames. Without a label the group has no name, and development builds log a warning. - Parts. The parts are spin buttons named
Day,Month,Year,HourandMinute, and the AM/PM toggle a button namedAM/PM. Rename them withday-aria-label,month-aria-label,year-aria-label,hour-aria-label,minute-aria-labelandday-period-aria-label, or translate them for every element under the keysday,month,year,hour,minuteanddayPeriod. - One tab stop. Only the first part is in the tab order. The arrow keys move between the parts.
- Description and errors. The
hintdescribes the group, and errors mark it witharia-invalidandaria-errormessage, as on the Date input.
The keys are those of the Date input and the Time input:
| Key | Action |
|---|---|
| Tab | Moves focus to the first part, and out of the field. |
| 0 to 9 | Type the part. A full part moves focus to the next part that is still empty. |
| ↑ / ↓ | Add or subtract one, or minute-step minutes. On the AM/PM toggle, switch it. |
| Space | On the AM/PM toggle, switches it. |
| ← / → | Move to the part on the left or right, in the order you see them. |
| Backspace / Delete | Delete digits. Leaving a part empty clears the value. |
What every element shares, such as translating the browser messages, is in Accessibility.