Skip to content

Date Time Input

Radoslav Karaivanov edited this page Aug 7, 2026 · 8 revisions

Date time input specification

Owned by

Team name: Codex

Developer name: Radoslav Karaivanov

Designer name: TBD

Requires approval from:

  • Radoslav Karaivanov
  • Svilen Dimchevski

Signed off by:

  • Damyan Petev
  • Radoslav Mirchev

Revision history

Version Author Date Notes
1 Ivaylo Barakov 20-Mar-2022 First draft
1.01 Ivaylo Barakov 22-Jul-2022 Edit "Custom display format" section
2 Radoslav Karaivanov 07-Aug-2026 Aligned the specification with the current implementation: min/max, validation slots, blur-commit value semantics, removal of size/igcFocus/igcBlur; restructured to the current specification template

Overview

The igc-date-time-input component is a single-line text editor for date and time values. The editable text is driven by a mask derived from an input format, so the end-user always edits a predictable, positional representation of the value (MM/dd/yyyy, HH:mm:ss, ...), while the value shown when the editor is not focused is rendered through a separate, locale-aware display format.

The component is a form-associated custom element: it participates in native form submission and constraint validation, exposes min/max constraints, and renders validation messages through dedicated slots.

Typical scenarios include:

  • Appointment and booking forms: date and time entry with a minimum of "now" and a maximum of a booking horizon
  • Filtering and reporting: from/to date editors bound to a data source query
  • Audit and log views: precise timestamp entry down to the seconds part
  • Composite editors: the text-entry surface of igc-date-picker and igc-date-range-picker

Key Features

  • Masked editing: the input format is turned into a positional mask with a configurable prompt character for unfilled positions
  • Separate display format: predefined locale styles (short, medium, long, full, and their date/time-only variants) or a custom format string
  • Locale awareness: the default input and display formats are resolved from the active locale and follow runtime localization changes
  • Deferred value commit: typing never mutates the public value; the edit is committed - and igcChange emitted - when the editor is blurred
  • Partial input completion: an incompletely filled mask is completed from defaults on commit, and a mask that cannot resolve to a date clears the value
  • Spinning: increment/decrement the date/time part under the caret through the keyboard, the mouse wheel, or the stepUp/stepDown API, with configurable per-part deltas and optional looping
  • Constraint validation: required, min and max validators plus setCustomValidity, with per-error message slots
  • Form association: submits with the form, resets to defaultValue, and reacts to a disabled ancestor fieldset
  • Themeable: integrates with the theming system of the library through CSS custom properties and shadow parts
  • Accessibility-first: native input semantics, label association and screen reader support

Acceptance criteria

  • The component must derive an editable mask from the inputFormat property and default it from the active locale when the property is not set.
  • The component must support a configurable prompt symbol for the unfilled positions of the mask and static literals inside the format.
  • The component must render the committed value through displayFormat while it is not focused, and through inputFormat while it is focused.
  • The component must support all applicable properties and API of the igc-input element (label, placeholder, prefix/suffix, helper text, outlined appearance, readonly, disabled).
  • The public value must only ever hold a committed value; intermediate editing state must not be observable through it.
  • The component must emit igcInput while the user is editing and igcChange only when a committed value differs from the value the editor was focused with.
  • The component must complete partially entered dates on commit and clear the value when the entered text cannot resolve to a valid date.
  • The component must correctly manage and report its validation state for required, min, max and custom validity, and render the corresponding validation message slots.
  • The component must participate in native form submission, reset and restore.
  • The component must support spinning of the individual date/time parts through keyboard, mouse wheel and public API, honouring spinDelta and spinLoop.
  • The element must be integrated and themeable with the theming mechanism of the library.
  • The element must be WAI-ARIA compliant, using the appropriate semantic elements and ARIA attributes.
  • The component must support RTL layouts without additional configuration.
  • The component must handle edge cases gracefully (invalid formats, out-of-range parts, incomplete input, rapid interactions).

User stories

End-user stories

As an end-user, I expect to be able to:

  • see a date/time value formatted in a readable, locale-appropriate way when I am not editing it.
  • see the positions I still have to fill clearly indicated by prompt characters when I start editing.
  • see a placeholder text when the editor is empty, suggesting what I am expected to type.
  • type a date and/or time value directly, with literals inserted for me as I go.
  • paste, or drag-and-drop, a date from elsewhere into the editor.
  • increment or decrement the date/time part my caret is in, using the keyboard or the mouse wheel.
  • insert the current date and time with a single keyboard shortcut.
  • have a partially typed date completed for me instead of being rejected outright.
  • be told when the value I entered is required, too early, or too late.

Developer stories

As a developer, I expect to be able to:

  • define the editable mask through an inputFormat and have it default to the current locale when I do not.
  • use the input format as the placeholder when I have not set one.
  • specify the prompt character used for the unfilled positions of the mask.
  • set the displayFormat either to one of the predefined styles - short, medium, long, full and their date/time-only variants - or to a custom format string.
  • configure the editor as editable, readonly or disabled.
  • set an initial value, and a defaultValue the editor resets to on form reset.
  • bind the value as a Date object or as an ISO string.
  • rely on value reflecting only committed values, so that a two-way binding never clobbers a half-typed mask.
  • observe the value as it is being typed through igcInput, and the committed value through igcChange.
  • set min and max values which control the validity of the editor.
  • mark the editor as required and provide my own messages for each validation failure.
  • specify the step - spinDelta - by which each date/time part is incremented/decremented, and whether spinning wraps around at the boundaries (spinLoop).
  • expect the editor to complete partially entered dates and to clear invalid input on commit.
  • submit the value as part of a native form and have it reset correctly.

Functionality

A date time input is a text field that lets the user set and edit a date and time value, controlled and filtered by a mask derived from the input format. Label, placeholder, helper text, prefix/suffix content and the validation visual states follow the conventions of the other input-like components of the library.

End-user experience

Visual structure

  • A single-line text field with an optional floating or static label, depending on the theme in use.
  • Optional prefix and suffix content - typically icons or spin buttons - rendered on either side of the text.
  • Optional helper text below the field, replaced by the relevant validation message when the editor is invalid.
  • The placeholder, when not explicitly set, is the input format itself (for example MM/dd/yyyy), so an empty editor advertises what it expects.

Editing

  • Unfocused: the committed value is rendered through displayFormat, so it can be considerably more verbose than what the user types (for example Sunday, July 17, 2022).
  • On focus: the text flips to the input format. An empty editor shows the empty mask (__/__/____) and selects it, so that typing immediately starts filling the first part.
  • While typing: only the mask positions accept input; literals are skipped over automatically and unfilled positions keep showing the prompt character.
  • On blur: the edit is committed. A partially filled mask is completed from defaults (year 2000, month January, day 1, time parts 0), and a mask that cannot resolve to a valid date - for example 02/30/2023 - clears the value.

Spinning

  • Keyboard: Arrow Up/Arrow Down increment/decrement the part the caret is currently in, keeping the caret in place.
  • Mouse wheel: while the editor is focused, scrolling spins the part under the caret. The page does not scroll while the editor is focused.
  • Boundaries: with spinLoop enabled - the default - a part wraps around at its boundary (minutes go from 59 to 00); otherwise it stays clamped at the boundary.

Feedback and accessibility

  • Focus indicator: the field shows the theme's focus styling; the inner native input is the focus target.
  • Screen readers: the editor is a native text input with an associated label, so its value, label, description and invalid state are announced natively.
  • Validation: the invalid state is applied after the editor has been interacted with, and the matching validation message slot replaces the helper text.

Developer experience

The igc-date-time-input component is designed for ease of integration with a declarative API that mirrors the rest of the input-like components in the library.

Basic initialization

The simplest editor requires no configuration at all - the input format, display format and placeholder are all derived from the active locale:

<igc-date-time-input label="Appointment"></igc-date-time-input>

Add content around the text through the prefix, suffix and helper-text slots:

<igc-date-time-input label="Appointment" outlined>
  <igc-icon slot="prefix" name="calendar"></igc-icon>
  <span slot="helper-text">Pick a date and a time</span>
</igc-date-time-input>

Input format

The inputFormat property is the mask the end-user edits. Every supported format character contributes an editable position; anything else is treated as a literal and skipped over while typing.

Format Description
d Day of the month, single position.
dd Day of the month with an explicitly set leading zero.
M Month, single position.
MM Month with an explicitly set leading zero.
yy Short (two digit) year format. Values below 50 resolve to the 2000s.
yyyy Full year format. Any year format other than yy is normalized to yyyy.
h Hours in 12-hour format, single position.
hh Hours in 12-hour format with an explicitly set leading zero.
H Hours in 24-hour format, single position.
HH Hours in 24-hour format with an explicitly set leading zero.
m Minutes, single position.
mm Minutes with an explicitly set leading zero.
s Seconds, single position.
ss Seconds with an explicitly set leading zero.
t AM/PM section for 12-hour format.
tt AM/PM section for 12-hour format.
<!-- Date only -->
<igc-date-time-input input-format="dd.MM.yyyy"></igc-date-time-input>

<!-- Time only, with seconds -->
<igc-date-time-input input-format="HH:mm:ss"></igc-date-time-input>

<!-- Date and 12-hour time -->
<igc-date-time-input input-format="MM/dd/yyyy hh:mm tt"></igc-date-time-input>

Setting prompt changes the character used for the positions that are not filled in yet:

<igc-date-time-input input-format="dd/MM/yyyy" prompt="*"></igc-date-time-input>

Which parts the format contains also determines how min/max are compared - a time-only editor is validated on its time portion only, and a date-only editor on its date portion only.

Display format

While the editor is not focused, the committed value is rendered through displayFormat. It accepts one of the predefined styles below - all examples are given in the en-US locale - or a custom format string. When displayFormat is not set, it falls back to inputFormat, and then to the locale's default date-time format.

Option Example
short 7/17/22, 12:00 AM
medium Jul 17, 2022, 12:00:00 AM
long July 17, 2022 at 12:00:00 AM GMT+3
full Sunday, July 17, 2022 at 12:00:00 AM Eastern European Summer Time
shortDate 7/17/22
mediumDate Jul 17, 2022
longDate July 17, 2022
fullDate Sunday, July 17, 2022
shortTime 12:00 AM
mediumTime 12:00:00 AM
longTime 12:00:00 AM GMT+3
fullTime 12:00:00 AM Eastern European Summer Time

A custom display format is built from the following symbols:

Type Format Description Example
Day of month d Minimum digits 7, 17
dd Zero padded 07, 17
Month M Minimum digits 3, 10
MM Zero padded 03, 10
MMM Abbreviated Oct
MMMM Wide October
MMMMM Narrow O
Year y Numeric 2022
yy Two digit 22
yyy Numeric 2022
yyyy Numeric 2022
Hour 1-12 h Minimum digits 1, 12
hh Zero padded 01, 12
Hour 0-23 H Minimum digits 1, 23
HH Zero padded 01, 23
Minute m Minimum digits 1, 59
mm Zero padded 01, 59
Second s Minimum digits 1, 59
ss Zero padded 01, 59
Time period t Abbreviated AM, PM
tt Abbreviated AM, PM
ttt Short noon
tttt Long noon
ttttt Narrow n

Note: Many locales use the same time period string irrespective of the format specified. The time period also only has an effect when a 12-hour clock is used.

<igc-date-time-input
  locale="fr"
  input-format="dd/MM/yyyy"
  display-format="fullDate"
></igc-date-time-input>

Value and commit semantics

The public value only ever holds a committed value. While the user is typing, the intermediate state lives in the masked text; the parsed result reaches value - together with an igcChange event - when the edit is committed on blur.

const input = document.querySelector("igc-date-time-input")!;

// Observe the value as it is being typed - the detail is an ISO string, or
// `undefined` while the mask is still incomplete.
input.addEventListener("igcInput", ({ detail }) => {
  console.log("typing:", detail);
});

// Observe committed values only. Fired on blur, and only when the committed
// value differs from the one the editor was focused with.
input.addEventListener("igcChange", ({ detail }) => {
  console.log("committed:", detail); // Date | null
});

This is what makes the component safe to two-way bind: a host re-rendering with the value it last received from igcChange will not reset a half-typed mask. Assigning a genuinely different value while the user is typing still wins and replaces the mask.

The value accepts a Date, an ISO string, or null:

<igc-date-time-input value="2026-08-07T14:30:00"></igc-date-time-input>
input.value = new Date(2026, 7, 7, 14, 30);
input.value = "2026-08-07T14:30:00";
input.value = null; // clears the editor

Commit is lenient by design:

  • A partially filled mask is completed from defaults - year 2000, month January, day 1 and zeroed time parts - so typing 07/__/____ commits as July 1st, 2000.
  • A mask that resolves to an invalid date - 02/30/2023, 13/01/2023 - commits as null.
  • clear() empties the mask and sets the value to null.

Constraint validation

min and max bound the valid range; required makes an empty editor invalid. Both accept a Date or an ISO string. Validation messages are rendered through the per-error slots, replacing the helper text while the editor is invalid.

<igc-date-time-input
  label="Delivery slot"
  required
  min="2026-08-01T09:00:00"
  max="2026-08-31T18:00:00"
  input-format="dd/MM/yyyy HH:mm"
>
  <span slot="helper-text">Working hours in August only</span>
  <span slot="value-missing">Please pick a delivery slot</span>
  <span slot="range-underflow">The slot is before the delivery window</span>
  <span slot="range-overflow">The slot is after the delivery window</span>
</igc-date-time-input>

Custom constraints are applied through setCustomValidity, and reported through the custom-error slot:

input.addEventListener("igcChange", ({ detail }) => {
  const isWeekend = detail ? [0, 6].includes(detail.getDay()) : false;
  input.setCustomValidity(isWeekend ? "Weekends are not available" : "");
});

Configuring spin behavior

spinDelta sets a per-part step; every part defaults to 1. spinLoop - enabled by default - controls whether a part wraps around at its boundary or clamps to it.

input.spinDelta = { date: 7, minutes: 15 };
input.spinLoop = false;

Programmatic control

const input = document.querySelector("igc-date-time-input")!;

// Step the part currently under the caret, or - when not focused - the
// day part, falling back to the hours part and then to the first part
// present in the format.
input.stepUp();
input.stepDown();

// Step an explicit part, optionally with a one-off delta. The part does not
// have to be present in the input format.
input.stepUp(DatePart.Minutes, 15);
input.stepDown(DatePart.Year);

// Selection and text manipulation
input.focus();
input.select();
input.setSelectionRange(0, 2);
input.setRangeText("12", 0, 2);

// Clear the editor
input.clear();

stepUp/stepDown on an empty editor initialize the value to the current date and time.

Form integration

The component is a form-associated custom element, so it needs no wrapper component to participate in a form:

<form>
  <igc-date-time-input name="appointment" required></igc-date-time-input>
  <button type="submit">Submit</button>
  <button type="reset">Reset</button>
</form>
  • The value is submitted under name as an ISO string; an empty editor is not submitted.
  • Enter inside the editor submits the owning form, unless the editor is invalid.
  • A form reset restores defaultValue. Setting the value attribute sets the default value, while assigning the value property does not.
  • A disabled ancestor fieldset disables the editor.
// Reset target, independent of the current value
input.defaultValue = new Date(2026, 0, 1);

Composition inside other components

igc-date-time-input is the text-entry surface of the composite date editors of the library - igc-date-picker and igc-date-range-picker - which forward their own label elements to the inner native input so that label association keeps working across the shadow boundary. Applications are expected to use those components when a calendar drop-down is needed, and igc-date-time-input directly when only a masked editor is.

Localization

The component has no static text of its own, so nothing needs to be translated. Everything locale-dependent is derived from the active locale:

  • inputFormat defaults to the locale's date-time input pattern, so the order of the day, month and year parts follows the locale.
  • placeholder defaults to the resolved input format.
  • displayFormat falls back to the locale's default date-time format, and the predefined styles as well as the month, weekday and time period names are rendered through the locale's data.

The locale property overrides the locale for a single editor; when it is not set, the editor follows the library's global locale. A runtime change of the global locale or of the localization resources re-resolves the default mask and re-renders the displayed value.

<igc-date-time-input locale="ja"></igc-date-time-input>

Validation messages are provided by the application through the validation message slots and are therefore localized by the application.

Keyboard interactions

Key combination Result
/ Moves the caret one position to the left/right.
Home / End Moves the caret to the beginning/end of the editor.
Ctrl / Cmd + Moves the caret to the beginning of the current date/time section, or of the previous one.
Ctrl / Cmd + Moves the caret to the end of the current date/time section, or of the next one.
Increments the date/time part the caret is in.
Decrements the date/time part the caret is in.
Ctrl / Cmd + ; Sets the current date and time as the value of the editor.
Enter Submits the owning form, if any and if the editor is valid.

All of the above are no-ops when the editor is readonly. Modified arrow presses other than the ones listed - for example Alt + - are ignored so that they stay available to composing components.

API

Properties and attributes

Property Attribute Reflected Type Default Description
value value No Date | string | null null The committed value of the input. Accepts a Date or an ISO string; always returns a Date or null.
defaultValue - - Date | string | null null The value the input reverts to on form reset. Also set by the value attribute.
inputFormat input-format No string locale The date/time pattern applied on the input. Defaults to the locale's date-time input format.
displayFormat display-format No string - Format used to display the value when the input is not focused. Falls back to inputFormat, then to the locale.
prompt prompt No string _ The prompt symbol used for the unfilled positions of the mask.
placeholder placeholder No string mask The placeholder text of the control. Defaults to the resolved input format.
label label No string - The label for the control.
locale locale No string global The locale used to resolve the default formats and to format the display value. Falls back to the library's global locale (en).
min min No Date | string | null null The minimum value required for the input to remain valid.
max max No Date | string | null null The maximum value required for the input to remain valid.
spinDelta - - DatePartDeltas | undefined - Per-part delta values applied on step actions. Every part defaults to 1.
spinLoop spin-loop No boolean true Whether spinning wraps around at the boundary of the currently spun part.
outlined outlined Yes boolean false Whether the control has an outlined appearance.
readOnly readonly Yes boolean false Makes the control a readonly field.
disabled disabled Yes boolean false The disabled state of the component.
required required Yes boolean false Makes the component a required field for validation.
invalid invalid No boolean false Sets the control into invalid state (visual state only).
name name Yes string - The name of the control, submitted with the form data.
form - - HTMLFormElement | null - Read-only. The form this element is associated with.
validity - - ValidityState - Read-only. The validity states of the element.
validationMessage - - string - Read-only. The validation message of the element.
willValidate - - boolean - Read-only. Whether the element is a candidate for constraint validation.

spinDelta is a DatePartDeltas object with the optional numeric keys date, month, year, hours, minutes and seconds.

Methods

Name Type signature Description
stepUp (datePart?: DatePart, delta?: number): void Increments a date/time portion.
stepDown (datePart?: DatePart, delta?: number): void Decrements a date/time portion.
clear (): void Clears the input element of user input.
select (): void Selects all the text inside the input.
focus (options?: FocusOptions): void Sets focus on the control.
blur (): void Removes focus from the control.
setSelectionRange (start: number, end: number, direction?: SelectionRangeDirection): void Sets the text selection range of the control.
setRangeText (replacement: string, start?: number, end?: number, selectMode?: RangeTextSelectMode): void Replaces the selected text in the control and re-applies the mask.
setCustomValidity (message: string): void Sets a custom validation message. As long as message is not empty, the control is invalid.
checkValidity (): boolean Checks the validity of the control and emits the invalid event if it is invalid.
reportValidity (): boolean Checks the validity of the control and shows the browser message if it is invalid.

DatePart is an enum with the members Date, Month, Year, Hours, Minutes, Seconds and AmPm.

Events

Name Cancellable Detail Description
igcInput false string | undefined Fired while the user is editing - typing, spinning, or Ctrl + ;. The detail is the ISO string of the value currently in the editor, or undefined while the mask cannot resolve to a date.
igcChange false Date | null Fired when an edit is committed on blur and the committed value differs from the one the editor was focused with.
invalid true - Fired when the control is found invalid during a validation cycle.

The native focus and blur events bubble out of the component; there are no igcFocus/igcBlur counterparts.

Slots

Name Description
prefix Renders content before the input.
suffix Renders content after the input.
helper-text Renders content below the input.
value-missing Renders content when the required validation fails.
range-overflow Renders content when the max validation fails.
range-underflow Renders content when the min validation fails.
custom-error Renders content when setCustomValidity(message) is set.
invalid Renders content when the component is in invalid state.

CSS Shadow parts

Part Description
container The main wrapper that holds all main input elements.
input The native input element.
label The native label element.
prefix The prefix wrapper.
suffix The suffix wrapper.
helper-text The helper text wrapper.

Assumptions and limitations

  • The component does not expose a type attribute, since the underlying element is always an input of type text.
  • Undo/redo of the masked text is not supported.
  • The value is a local Date; time zones are not modelled. A display format including a time zone renders the runtime's time zone.
  • The input format is positional. Variable-width tokens that are valid in a display format - MMM, MMMM, ttt - are not supported as input format tokens.
  • Any year token other than yy is normalized to yyyy for editing purposes.
  • Two-digit years below 50 resolve to the 2000s; 50 and above resolve to the 1900s.
  • A single-character token - d, M, h - yields a single editable position; use the doubled token when a zero-padded, two-position section is required.
  • The mask and prompt members are inherited from the shared masked-editor behavior. Only prompt is supported here - inputFormat is the supported way of setting the pattern.
  • Only one date/time value is edited per component; ranges are covered by igc-date-range-picker.

Test scenarios

Rendering and Initialization

  1. Default rendering

    • The component renders a native text input with the default mask, prompt and placeholder for the active locale
    • value is null and no validation styling is applied
    • Label, helper text, prefix and suffix content render in their respective slots
  2. Initial value

    • Setting the value attribute to an ISO string initializes the value and the displayed text
    • Setting the value property to a Date initializes the value and the displayed text
    • Setting a value with a time portion only is handled correctly
    • An invalid initial value resolves to null

Input Format and Mask

  1. Format resolution

    • inputFormat defaults to the locale's date-time format when not set
    • Changing locale updates the resolved input format, with and without a value present
    • A runtime localization resource change updates the resolved input format, with and without a value present
    • Setting inputFormat explicitly overrides the locale default
    • The placeholder follows the resolved input format while it has not been explicitly set
  2. Mask editing

    • The mask exposes one editable position per format character and skips literals while typing
    • Unfilled positions render the prompt character, and changing prompt re-renders them
    • The mask is re-applied according to inputFormat on focus when a value is already set
    • Out-of-range sections keep the mask editable and resolve on commit
    • Formats containing seconds and AM/PM sections are handled correctly

Display Format

  1. Predefined and custom formats
    • The value is rendered through displayFormat while the input is not focused
    • Switching between the predefined date-time, date-only and time-only styles renders the expected text
    • A custom display format string renders the expected text
    • displayFormat falls back to inputFormat, and then to the locale default, when not set
    • The text flips to the input format on focus and back to the display format on blur

Value and Commit Semantics

  1. Uncommitted edits

    • Typing does not mutate value, neither for a partial nor for a complete mask
    • igcInput exposes the typed value as an ISO string while value stays put
    • Re-applying an equal value while typing does not reset the mask
    • A genuinely different value assigned while typing replaces the mask
  2. Commit on blur

    • A complete mask commits its value on blur and emits a single igcChange carrying it
    • An incomplete mask is completed from defaults on commit and emits igcChange
    • A mask that resolves to an invalid date commits null
    • No igcChange is emitted when the committed value equals the value the input was focused with
    • No igcChange is emitted when the control is readonly
    • A value assigned programmatically while focused is treated as a committed change
  3. Clearing

    • clear() empties the mask and sets value to null
    • Assigning null clears the value and the displayed text

Spin Functionality

  1. stepUp/stepDown

    • Step the part under the caret when focused, and the default part when not
    • Initialize a new date when the value is empty
    • Accept an explicit DatePart, including one not present in the input format
    • Accept a one-off delta argument
    • Respect spinDelta per part
    • Respect spinLoop at the boundaries of each part
    • Do not move the caret away from the part being spun
  2. Mouse wheel

    • Scrolling spins the part under the caret while the input is focused
    • Scrolling is a no-op when the input is not focused
    • Scrolling is a no-op when the input is readonly

Keyboard Navigation

  1. Caret movement

    • Arrow left/right move the caret one position
    • Ctrl/Cmd + arrow left/right jump to the beginning/end of the adjacent date/time section
    • Clicking positions the caret inside the corresponding section
  2. Keyboard spinning and shortcuts

    • Arrow up/down step the part under the caret and emit igcInput
    • Arrow up/down are a no-op when the input is readonly
    • Alt + arrow up/down are a no-op
    • Ctrl/Cmd + ; sets the current date and time as the value

Paste and Drag-and-Drop

  1. Text transfer
    • setRangeText() replaces the selected text and re-applies the mask
    • Dragging text over an unfocused input flips it to the editable mask
    • Dragging away from an unfocused input restores the display value
    • Dropping text onto the input applies and commits it without a blur

Validation

  1. Constraints

    • required invalidates an empty editor and validates a filled one
    • min invalidates values before it, for both Date and ISO string bindings
    • max invalidates values after it, for both Date and ISO string bindings
    • A time-only format is validated on the time portion, and a date-only format on the date portion
    • setCustomValidity() invalidates the editor while the message is not empty
    • checkValidity() and reportValidity() report the expected result and emit invalid when appropriate
    • Validation styling is applied only after the editor has been interacted with
  2. Validation message slots

    • value-missing, range-underflow, range-overflow and custom-error content renders for the corresponding failure
    • invalid slot content renders while the editor is invalid
    • Validation messages replace the helper text and are cleared when the editor becomes valid
    • Validation messages persist after a failed form submission

Form Integration

  1. Submission and reset
    • The element is form associated
    • An empty editor is not submitted
    • A filled editor is submitted under its name
    • Enter submits the owning form, and does not submit while the editor is invalid
    • A form reset restores defaultValue
    • Setting the value attribute updates the default value used on reset
    • defaultValue participates in required, min and max validation
    • The editor reflects a disabled ancestor fieldset

Localization

  1. Locale-driven behavior
    • Month, weekday and time period names follow the locale
    • Changing locale re-renders the displayed value
    • A runtime resource change re-renders both the mask and the displayed value

Accessibility

  1. Semantics
    • The inner element is a native text input reachable through Tab
    • label is associated with the inner input, and labels forwarded by a composite host take precedence
    • Helper text is referenced through aria-describedby
    • The invalid state is exposed to assistive technology
    • disabled and readonly are propagated to the inner input

RTL Support

  1. Right-to-Left
    • The editor renders and edits correctly in an RTL context
    • Caret navigation and section jumps behave correctly in RTL

Edge Cases

  1. Invalid configuration and rapid interaction
    • An input format with no supported format characters degrades gracefully
    • Invalid min/max values are ignored rather than throwing
    • min greater than max behaves predictably
    • Rapid typing, spinning and focus changes do not desynchronize the mask from the value
    • Leap years and month-length changes are handled when spinning the year and month parts
    • Spinning the AM/PM part does not roll the date over

Accessibility

ARIA roles and properties

The editable surface is a native <input type="text">, so the majority of the semantics come for free:

  • the inner input is labelled by the component's label, or by the label elements forwarded by a composite host, through aria-labelledby.
  • when helper text or a validation message is rendered, the inner input references it through aria-describedby.
  • the disabled and readonly states are set on the inner input, so they are exposed natively.
  • the invalid state is exposed through the element's ElementInternals validity, so assistive technology is notified of a failed constraint.
  • the component sets delegatesFocus, so focusing the host focuses the inner input.

Keyboard support

Already covered by the relevant section of the specification.

Right to Left support

The date time input should work in a Right-to-Left context without additional setup or configuration.

Clone this wiki locally