Forms

TimePicker

A fully accessible time-only picker with popup spinbuttons (hour/minute/optional second), direct text input, min/max and step support. Follows W3C ARIA Spinbutton pattern. Use for appointment times, business hours, and any time-of-day field. Consistent with DatePicker styling and behavior.

Basic (24-hour)

Default 24-hour format. Value is stored as HH:mm. Type in the field or click the clock to open the popup. Use arrow keys in the popup to change hour and minute; Tab to move between segments.

TimePicker in a Modal

Click the button to open a modal containing a TimePicker. The modal uses scrollBehavior outside so the time popup is not clipped. Useful for scheduling flows.

Date + Time in a small dialog

Both DatePicker and TimePicker side by side in a small modal—e.g. for scheduling. Uses a constrained grid so neither overflows; calendar and time popups use scrollBehavior outside so they are not clipped.

12-hour format

Display and input in 12h with AM/PM. Value is still stored as 24h (e.g. 2:30 PM → 14:30). Type the time and include AM or PM.

Appointment time (15-minute step)

Minute step in 15-minute increments (0, 15, 30, 45). Ideal for appointment slots. When opening the popup, minutes snap to the nearest step.

Business hours (min / max)

Constrain selectable time to a range (e.g. 09:00–17:00). Combined with step for clean slot selection.

With seconds

Include seconds in value and in the popup. Value format is HH:mm:ss. Use for exact timestamps or duration start/end.

Date of Service time with validation

Example: time of service must be within 08:00–18:00. Error is set from outside based on value.

Date formats (24h vs 12h)

Same value displayed in 24h and 12h formats.

Sizes

Choose appropriate sizes based on form density.

Validation states

Shows error and success states for form validation.

Disabled & read-only

Use disabled for unavailable fields and read-only for view-only data.

Clearable with success message

Optional field with clear button and success message when set.

Props

PropTypeDefaultDescription
id stringUnique identifier for the input (auto-generated if not set)
name stringForm field name
label *stringInput label text
value string''Time string (HH:mm or HH:mm:ss, 24h) - bindable
format '12h' | '24h''24h'Display format (12h shows AM/PM)
placeholder stringPlaceholder (defaults to format hint)
required booleanfalseMarks field as required
disabled booleanfalseDisables the input
readonly booleanfalseMakes input read-only
error stringError message to display
hint stringHelper text shown on focus
successMessage stringSuccess message when valid
size 'sm' | 'md' | 'lg''md'Input size
iconLeft SnippetIcon to display on the left
hideLabel booleanfalseHide label visually (still accessible)
class stringAdditional CSS classes for the wrapper
stepMinutes number1Minute step in popup (e.g. 1, 5, 15, 30)
showSeconds booleanfalseInclude seconds in value and popup
minTime stringMinimum time (HH:mm or HH:mm:ss)
maxTime stringMaximum time (HH:mm or HH:mm:ss)
clearable booleanfalseShow clear button
validateOnMount booleanfalseShow validation state immediately
onchange (value: string, time: TimeValue | null) => voidCalled when value changes
onopen () => voidCalled when popup opens
onclose () => voidCalled when popup closes
onclear () => voidCalled when clear button is clicked
testId stringTest ID for e2e testing
alwaysShowFooter booleanfalseWhen true, the message footer is always rendered with reserved space to prevent layout shift when hint/error appears.

Keyboard & popup

Focus the input and press Alt + ↓ to open the time picker. Inside the popup, each segment (hour, minute, optional second) is a spinbutton. Use Tab to move between segments; Enter from a spinbutton applies the time and closes the popup. Escape closes without applying. Focus is trapped in the popup and returns to the trigger when closed.

KeyAction
Alt + ↓Open time picker popup
Tab / Shift+TabMove between segments and buttons (focus trapped in popup)
EnterWhen focus is on a spinbutton: apply time and close. On OK: confirm. On Cancel: close without applying.
EscapeClose popup (focus returns to trigger)
/ Increase / decrease value for focused segment
Home / EndMin / max value for focused segment
Page Up / Page DownLarger step (e.g. +10 / −10 minutes)

Message footer & layout shift

The message footer (hint, error, success) is shown in a reserved area below the input. To avoid layout shift when content appears or changes (e.g. hint on focus, error when validation runs), the footer is rendered whenever the component can show any of that content—even if nothing is visible yet. When there is nothing to display, an invisible placeholder reserves one line of space.

  • Default: Footer is shown when the component has a hint, error, or successMessage. Footer is hidden only when none of these are set.
  • alwaysShowFooter: Set to true to always reserve footer space (e.g. when your app sets hint or error dynamically).

Usage tips

  • • Use stepMinutes (5, 15, 30) for appointment or slot selection to keep values consistent.
  • • Use minTime / maxTime for business hours, operating hours, or allowed windows.
  • • Use format="12h" when your users expect AM/PM; value is still stored in 24h.
  • • Use showSeconds only when exact seconds matter (e.g. timestamps, duration).
  • • Combine with DatePicker for date-time (e.g. appointment date + time).
  • • Use clearable for optional time fields so users can reset easily.
  • • Provide a clear label and hint for context (e.g. "Appointment time", "Business hours 9–5").

Accessibility features

  • WAI-ARIA Spinbutton pattern: Hour, minute, and second segments use role="spinbutton" with aria-valuenow, aria-valuemin, aria-valuemax, aria-valuetext, and aria-labelledby
  • Dialog: Popup uses role="dialog", aria-modal="true", and aria-label="Choose time"
  • Keyboard: Full support for arrows, Home/End, Page Up/Down per segment; Tab/Shift+Tab between segments and buttons; Enter to apply from spinbutton or OK; Escape to close
  • Focus trap: Tab cycles within the popup when open; focus cannot leave the dialog until it is closed
  • Focus restoration: When the popup closes (Escape, OK, Cancel, or outside click), focus returns to the trigger button via the focus trap
  • Focus visible: Spinbuttons and buttons use :focus-visible so the focus ring appears for keyboard users, not on mouse click
  • Live announcements: Open, select, and clear actions are announced to screen readers via a live region
  • Labels: Each spinbutton is labelled (Hour, Minute, Second) via aria-labelledby; Cancel and OK buttons have aria-label
  • Reduced motion: Popup animation is disabled when prefers-reduced-motion: reduce

Value format

The value prop always uses 24-hour format: HH:mm or HH:mm:ss when showSeconds is true. Empty string when no value. The format prop only affects how the time is displayed (12h with AM/PM vs 24h).