Timepicker

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";
Usage

This section outlines usage examples and configuration guidance for the components in this package.

Basic usage

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.

HH:MM
<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>
Time input

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.

HH:MM
<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>
Variants

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>
Orientation

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.

HH:MM
<m3e-timepicker variant="auto" orientation="horizontal"></m3e-timepicker>
Modes

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.

HH:MM
<m3e-timepicker mode="input" hide-mode-toggle></m3e-timepicker>
Time selection

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.

HH:MM
<!-- 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);
});
Date string handling

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:

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.

Hour format

The format attribute controls the hour cycle used by the timepicker. It accepts "12" (default), "24", or "auto".

The following example illustrates a 24-hour clock without a meridiem.

HH:MM
<m3e-timepicker format="24"></m3e-timepicker>
Min and max times

Use the min-time and max-time attributes to disable all times in the picker before or after the respective values.

HH:MM
<m3e-timepicker min-time="8:15 AM"  max-time="5:30 PM"></m3e-timepicker>
Blackout times

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.

HH:MM
document.querySelector("#blackout-times").blackoutTimes = (t) => t.hour < 8 || t.hour > 18;
Seconds

Use the show-seconds attribute to display the seconds segment in the timepicker.

HH:MM:SS
<m3e-timepicker show-seconds></m3e-timepicker>
À-la-carte usage

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.

hour = , minute =
<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 ?? ""}`;
});
Accessibility

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.

Native module support

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.

API

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.

m3e-timepicker m3e-timepicker-dial m3e-timepicker-input m3e-timepicker-toggle
On this page Timepicker