Time picker

<o-time-picker> picks a time by turning a clock: hours first, then minutes.

Tap or drag an hour; let go and the dial turns to minutes.

The dial is an Orbit universe. Hours and minutes are two rings of twelve satellites on orbit-10, and only one shows at a time. The hand is a .vector and the knob a satellite on the same ring; both are turned by one registered custom property, so switching from hours to minutes sweeps them round the dial instead of jumping. The fields above are ordinary elements, for reading and for the keyboard.

24 hours

With hours="24" the dial gets an inner ring for 00 and 13 to 23, like a phone's clock. Without the attribute, the picker follows the hour cycle of the page's language.

Attributes

AttributeDefaultWhat it does
valueemptyThe time, HH:MM in 24 hours. It is also the default a form reset returns to; the attribute follows the picker.
hoursfrom the locale12 (with AM and PM) or 24 (with an inner ring).
minute-step1Minutes snap to multiples of it; minute labels it cannot reach are dimmed.
min / maxEarliest and latest time, HH:MM. Hours and minutes outside are dimmed and cannot be picked. A min after max is a window across midnight.
viewhourshours or minutes: which ring the dial shows. It follows the picker.
labelThe accessible name of the group, read with the time.
fill#4fd1c5Hand, knob and the active field.
nameField name: the picker submits HH:MM, or an empty string. See Forms.
requiredoffThe form is invalid until a time is picked.
disabledoffDimmed, out of the tab order and not submitted. A disabled <fieldset> does the same.
size280pxWidth of the widget; the fields scale with it.
localethe page'sPicks the hour cycle when hours is not set.
themedark, light or glass. See Shared options.

Properties and events

NameWhat it does
value"07:30", or "". Setting it snaps and clamps like the attribute and fires no event.
valueAsNumberMinutes after midnight, or NaN.
viewReads or sets the ring on the dial.
min, maxAs the attributes.
form, labels, defaultValue, validityAs on a native input.
inputFires on every change you make. event.detail.value has the time.
changeFires when you let go of the dial with a different time, and on each key press.
picker.addEventListener('change', (e) => save(e.detail.value))
picker.value = '06:15'

Styling

PropertyDefaultWhat it does
--ok-fill#4fd1c5Hand, knob, pivot and the active field.
--ok-time-face--ok-face, #161b22The dial face.
--ok-text#e8edf2Numbers and fields.
--ok-on-fill#0c0f13The number under the knob.
--ok-focus--ok-fillFocus ring of the fields and buttons.
--ok-font-size8cqminBase font size of the dial, as a share of it.

More examples

Office hours in quarter hours

min, max and minute-step together: only 9:00 to 17:30, every fifteen minutes.

Required, in a form

Light

Accessibility

The picker is a role="group" whose name says the time. The hours and the minutes are each a role="spinbutton" and a tab stop, with aria-valuenow, aria-valuemin, aria-valuemax and aria-valuetext; AM and PM are toggle buttons with aria-pressed. The dial repeats what the fields say, so it is hidden from screen readers.

Up and Down change the focused field: hours round the day, minutes by minute-step round the hour, skipping anything outside min and max. Page Up and Page Down take bigger steps, digits type a value, Left and Right move between fields, and A or P switch the half of the day. Focusing a field turns the dial to it.