Time Picker

Free

12h/24h scroll-column time picker with hour/minute/second wheels, AM/PM selector, Now button and 3 sizes.

</>sv-time-picker timepickerinput
import { SvTimePickerComponent } from '@styloviz/forms';

Demo & usage

Basic usage

Usage example — open the gallery for the full interactive demo.

An interactive demo for this component lives in the gallery.

Open live demo

More examples

24-hour with seconds

example.htmlAngular
<sv-time-picker format="24h" [withSeconds]="true" [(ngModel)]="time" />

Type the time instead of scrolling to it

The panel opens with a text field focused, so the keyboard path to any time is Tab, Enter, type, Enter. It accepts 14:30, 14.30, 1430, 2:30 PM, 2:30pm and the same forms in Arabic-Indic, Bengali or fullwidth digits. Set [typed]="false" to remove the field; the columns remain.

example.htmlAngular
<!-- on by default -->
<sv-time-picker format="24h" [(ngModel)]="time" />

<!-- wheels only -->
<sv-time-picker [typed]="false" [(ngModel)]="time" />

When to use

  • Selecting a time of day with hour/minute (and optional second) precision.
  • You want scroll-column wheels and a "Now" shortcut.
  • Pair with a Date Picker when you need a full timestamp.

Async states

None — this component has nothing to load, so it has no loading, empty or error state to drive.

Inputs

NameTypeDefaultDescription
valuestring (two-way)'09:00'Selected time as `"HH:mm"`, or `"HH:mm:ss"` with `withSeconds`. Two-way.
formatTimePickerFormat'12h'Clock format: 12h or 24h.
sizeTimePickerSize'md'Control size: sm, md or lg.
disabledbooleanfalseDisable the picker.
labelstring''Accessible label for the control.
minstring''Earliest selectable time ("HH:mm"). Earlier cells are disabled.
maxstring''Latest selectable time ("HH:mm"). Later cells are disabled.
withSecondsbooleanfalseInclude a seconds column.
typedbooleantrueOffer a text field inside the panel so the time can be TYPED.
errorMessagestring''Client-side validation message.
serverErrorSvServerErrornullA rejection reported by the server about this value. Self-expiring.

Outputs

EventPayload typeDescription
changedstringEmitted with the new time string when it changes.
valueChangestringEmits the new `value` whenever it changes — the output half of `[(value)]`.

Customization & theming

  • 12-hour or 24-hour mode with optional seconds, plus min/max bounds and a "Now" shortcut.
  • The value is a wall-clock `HH:mm` (or `HH:mm:ss`) string — not an instant, and not zoned. Pair it with the Date Picker's `YYYY-MM-DD` calendar date through `svComposeDateTime` when you need a real timestamp.
  • Three sizes; the trigger shows the selected time with a chevron and is named via `label`.
  • Two-way bind `[(value)]` or a reactive control (CVA); listen to `(changed)`.
  • `typed` (default `true`) puts a text field at the top of the panel and focuses it on open. It parses `14:30`, `14.30`, `1430`, `143015`, `2:30 PM`, `2:30pm` and the same forms written in Arabic-Indic, Bengali, Devanagari or fullwidth digits, plus day-period markers in Arabic, Japanese and Korean. It commits on Enter and on blur — never mid-keystroke, because `1` and `14` are both valid times on the way to `14:30`.

Best practices

  • Do: Match `format` (12h/24h) to the user's locale conventions.
  • Don't: Don't compose a timestamp with `new Date(date + "T" + time)`. The value here is a WALL-CLOCK time and the date picker's is a CALENDAR DATE — neither is an instant — so that expression resolves in the browser's zone, and a booking entered by a London scheduler for a Dublin clinic is stored an hour out with nothing reporting a problem.
  • Do: Use `svComposeDateTime(date, time, zone)` from `@styloviz/core`. Twice a year the composition is not a function: London on 2026-03-29 has no 01:30 (the clocks go 01:00 → 02:00, and `new Date` silently returns 02:30), and on 2026-10-25 it has two. It returns `status: "ok" | "gap" | "ambiguous"` plus both instants when ambiguous, so a booking flow can say "that hour does not exist on this date" rather than move the appointment. The transition is not always an hour — Australia/Lord_Howe shifts by thirty minutes.
  • Do: Only enable `withSeconds` when seconds genuinely matter.
  • Tip: Constrain selectable times with `min`/`max` for booking-style flows.
  • Do: Leave `typed` on. Before it, the open panel was 146 tab stops with `format="24h"` and `withSeconds` — minute 37 was the 61st — because every cell was its own tab stop and there were no arrow keys. That is not a preference; it is the difference between a control a keyboard user can operate and one they cannot.
  • Don't: Don't expect a refused time to be corrected for you. `25:00` stays in the field marked invalid rather than being clamped to `23:59`: clamping looks like acceptance, and the user walks away believing they set a time they did not set. A well-formed time outside `min`/`max` is a different case and IS clamped, because the host asked for that.

Accessibility

  • The trigger is named by `label` (announced with the current value) and exposes `aria-expanded` / `aria-haspopup`.
  • The popover is a non-modal `role="dialog"`; columns are buttons reachable by keyboard, and the selected time updates the value live.
  • Each column is a single tab stop on its selected cell, with Up/Down by one, PageUp/PageDown by five, and Home/End to the ends — clamping at the ends rather than wrapping, and stepping over cells disabled by `min`/`max` rather than landing on one (a disabled button cannot take focus, which would strand focus on the body with the panel still open).
  • A refused typed time sets `aria-invalid` on the field and turns its hint into a `role="alert"` carrying the accepted format, so the correction is announced with the complaint.
  • Implements ControlValueAccessor — works with `[(ngModel)]`, `[formControl]` and `formControlName`; `formControl.disable()` disables the trigger.

Feedback on Time Picker

Spotted a gap in this page, or something that didn't work as described? Comments are GitHub Discussions in the public styloviz/community repo, so posting needs a GitHub account.

Loads giscus.app and GitHub — nothing is fetched until you click.