The m3e-timepicker component presents a temporary surface for selecting time using dial and
keyboard modes. It supports hour and minute selection across 12-hour and 24-hour formats, enforces minimum and
maximum constraints, and adapts between docked and modal layouts based on available space.
import "@m3e/web/timepicker";
This section outlines usage examples and configuration guidance for the components in this package.
Use the m3e-timepicker-toggle to open a m3e-timepicker. This component should be
nested inside a clickable element and be associated with a picker by setting the for attribute to the id of
the picker to open.
<m3e-form-field variant="outlined">
<label slot="label" for="field">Time Field</label>
<input autocomplete="off" id="field" />
<m3e-icon-button slot="suffix">
<m3e-icon name="schedule"></m3e-icon>
<m3e-timepicker-toggle for="timepicker"></m3e-timepicker-toggle>
</m3e-icon-button>
<span slot="hint">HH:MM</span>
</m3e-form-field>
<m3e-timepicker id="timepicker" variant="auto"></m3e-timepicker>
The m3e-date-input can also provide a segmented time field when configured with
type="time". It integrates directly with m3e-timepicker and can be used in place of
a standard input when you want built-in parsing, formatting, and precise segment editing.
The examples on this page use a standard input to demonstrate the full
m3e-timepicker API. When using m3e-date-input with type="time", many of
these props are not required because the input manages the value and the picker simply writes the selected
time back to the field.
See Date Input for details.
<m3e-form-field variant="outlined">
<label slot="label" for="field">Time Picker</label>
<m3e-date-input id="field" type="time"></m3e-date-input>
<m3e-icon-button aria-label="Open time picker" slot="suffix">
<m3e-icon name="schedule"></m3e-icon>
<m3e-timepicker-toggle for="timepicker"></m3e-timepicker-toggle>
</m3e-icon-button>
<span slot="hint">HH:MM</span>
</m3e-form-field>
<m3e-timepicker id="timepicker" for="field"></m3e-timepicker>
The m3e-timepicker supports three appearance variants: docked (default),
modal, and auto. Use the variant attribute to control how the picker is
presented. When set to auto, the picker automatically selects the appropriate appearance based on
the current screen size.
All examples in this page use variant="auto".
<m3e-timepicker variant="auto"></m3e-timepicker>
The m3e-timepicker supports three orientations: vertical (default),
horizontal, and auto. Use the orientation attribute to control how the
picker is orientated. When set to auto, the picker automatically selects the appropriate
orientation based on the current screen size.
Typically, orientation="auto" should be pared with variant="auto" so that the picker
will swap between orientation and variant depending on viewport constraints.
<m3e-timepicker variant="auto" orientation="horizontal"></m3e-timepicker>
The m3e-timepicker supports two modes, dial (default), and input. Use
the mode attribute to set the default mode. Use the hide-mode-toggle attribute to
hide the button used to toggle between modes.
The following example illustrates the use of mode="input" and hide-mode-toggle to
force the timepicker to open in keyboard entry mode while preventing the user from switching back to the dial.
<m3e-timepicker mode="input" hide-mode-toggle></m3e-timepicker>
Use the date attribute to set the currently selected time.
The OK button becomes enabled whenever the picker holds a complete, valid time, including cases where the
initial value was already valid and the user made no changes. Both the hour and minute fields must contain
valid, non-null values for the picker to construct a time; incomplete or invalid states keep the OK button
disabled. Clicking OK commits the current time to date and emits a change event. If
date is null, today's date is used.
Clicking Cancel dismisses the picker without committing any value. The current date and time
remain unchanged, and no change event is emitted. Cancel is always a non-committing action,
regardless of whether the selection was complete, valid, or modified.
<!-- Form field omitted for brevity --> <m3e-timepicker id="timepicker" date="2026-07-13T23:30:00Z"></m3e-datepicker>
const picker = document.querySelector("#timepicker");
const field = document.querySelector("#field");
field.value = toLocaleTimeString(picker.date);
picker.addEventListener("change", () => {
field.value = toLocaleTimeString(picker.date);
});
Different browsers interpret date strings in inconsistent ways, especially when the string resembles an ISO
date but does not include a time or timezone. To ensure predictable behavior across environments,
m3e-timepicker uses a consistent, standards-aligned parsing model instead of relying on the
browser's built-in Date.parse() rules.
When m3e-timepicker receives a date string, it automatically detects whether the value matches
one of the ISO-8601 formats that can be parsed safely and unambiguously:
yyyy-MM-dd — local date (no time, no timezone)yyyy-MM-ddTHH:mm:ss — local date and timeyyyy-MM-ddTHH:mm:ssZ — UTC date and timeyyyy-MM-ddTHH:mm:ss±HH:mm — date and time with an explicit timezone offset
Strings in these formats are converted into local Date objects without unexpected timezone
shifts. This prevents issues such as date-only values drifting into the previous or next day when interpreted
as UTC. If a string does not follow one of these ISO-compatible patterns, parsing may be ambiguous or
unsupported. For the most reliable results, use one of the formats above.
The format attribute controls the hour cycle used by the timepicker. It accepts
"12" (default), "24", or "auto".
"12" — forces a 12-hour clock with an AM/PM meridiem."24" — forces a 24-hour clock without a meridiem."auto" — selects 12-hour or 24-hour based on the user's locale.The following example illustrates a 24-hour clock without a meridiem.
<m3e-timepicker format="24"></m3e-timepicker>
Use the min-time and max-time attributes to disable all times in the picker before
or after the respective values.
<m3e-timepicker min-time="8:15 AM" max-time="5:30 PM"></m3e-timepicker>
In addition to min-time and max-time constraints, the
blackoutTimes property lets you provide a function that determines whether a given time is
disabled and cannot be selected. The function receives a TimeParts object containing the
hour, minute, and secondvalues for the time being evaluated.
document.querySelector("#blackout-times").blackoutTimes = (t) => t.hour < 8 || t.hour > 18;
Use the show-seconds attribute to display the seconds segment in the timepicker.
<m3e-timepicker show-seconds></m3e-timepicker>
The package includes the m3e-timepicker-input and m3e-timepicker-dial components,
allowing you to use them in custom layouts or independently of m3e-timepicker.
The for attribute can be used on m3e-timepicker-input to reference a
m3e-timepicker-dial by ID. When present, the input automatically synchronizes its properties to
the referenced dial, keeping both components in sync without requiring manual event wiring.
<m3e-timepicker-input id="input" for="dial"></m3e-timepicker-input> <m3e-timepicker-dial id="dial"></m3e-timepicker-dial> <span id="inputValue"></span>
document.querySelector("#input").addEventListener("change", (e) => {
const picker = e.target;
document.querySelector("#inputValue").innerText =
`hour = ${picker.hour ?? ""}, minute = ${picker.minute ?? ""}`;
});
Timepickers are given ARIA role="dialog" to identify the picker surface as a discrete interactive
region that opens above the page and requires user attention. When the picker is shown in its modal variant,
it also sets aria-modal="true" to indicate that the rest of the page is inert and that focus is
trapped within the dialog until it is dismissed. In docked mode, the picker omits
aria-modal entirely, since the surrounding page remains interactive and the surface behaves like
an anchored popover rather than a blocking dialog.
Timepicker toggles add aria-haspopup="dialog" to its parenting element indicating to assistive
technologies that activating the control will open a dialog.
The @m3e/web package uses
JavaScript Modules. To use it directly in a browser without a bundler, use a module script similar to the following.
<script type="module" src="/node_modules/@m3e/web/dist/timepicker.js"></script>
In addition, you must use an import map to include dependencies.
<script type="importmap">
{
"imports": {
"tslib": "https://cdn.jsdelivr.net/npm/tslib@2.8.1/+esm",
"lit": "https://cdn.jsdelivr.net/npm/lit@3.3.0/+esm",
"lit/": "https://cdn.jsdelivr.net/npm/lit@3.3.0/",
"lit-html": "https://cdn.jsdelivr.net/npm/lit-html@3.3.0/+esm",
"lit-html/directive.js": "https://cdn.jsdelivr.net/npm/lit-html@3.3.0/directive.js",
"lit-html/directives/if-defined.js": "https://cdn.jsdelivr.net/npm/lit-html@3.3.0/directives/if-defined.js",
"lit-html/directives/class-map.js": "https://cdn.jsdelivr.net/npm/lit-html@3.3.0/directives/class-map.js",
"@lit/reactive-element": "https://cdn.jsdelivr.net/npm/@lit/reactive-element@2.0.4/+esm",
"@lit/reactive-element/": "https://cdn.jsdelivr.net/npm/@lit/reactive-element@2.0.4/",
"@m3e/web/core": "/node_modules/@m3e/web/dist/core.js",
"@m3e/web/core/a11y": "/node_modules/@m3e/web/dist/core-a11y.js"
"@m3e/web/core/anchoring": "/node_modules/@m3e/web/dist/core-anchoring.js",
"@m3e/web/core/bidi": "/node_modules/@m3e/web/dist/core-bidi.js",
"@m3e/web/core/layout": "/node_modules/@m3e/web/dist/core-layout.js"
"@m3e/web/button": "/node_modules/@m3e/web/dist/button.js",
"@m3e/web/icon-button": "/node_modules/@m3e/web/dist/icon-button.js",
}
}
</script>
For production builds, use the minified files to ensure optimal load performance.
The @m3e/web package includes a
Custom Elements Manifest
(custom-elements.json), which documents the properties, attributes, slots, events and CSS custom
properties of each component.
You can explore the API below, or integrate the manifest into your own tooling.