Skip to main content
WireKit
Copy for LLM

Time Picker

The <x-wirekit::time-picker> component is a styled wrapper around the native <input type="time">. It uses the browser's built-in time selection UI for zero dependencies and automatic localization.

Basic Usage

Basic Time Picker

12-Hour Format

12-Hour Display

The format prop controls the visual display. Regardless of format, the submitted value is always in 24-hour HH:MM format (the native <input type="time"> standard).

Note: The 12-hour vs 24-hour display is ultimately controlled by the browser and OS locale. The format prop provides a hint but browsers may override it.

With Step (Minutes Interval)

15-Minute Intervals

Available in 15-minute intervals

The step attribute is in seconds. Common values: 60 (1 min), 300 (5 min), 900 (15 min), 1800 (30 min), 3600 (1 hour).

Size Variants

Three Sizes

Error State

Time picker with an error message

Please select a valid time.

With Hint

Hint Text

We will notify you at this time daily.

Width

Like all WireKit form components, the time picker fills its container (w-full). Time fields are typically narrow — constrain the width via the parent element:

<div class="max-w-[10rem]">
    <x-wirekit::time-picker label="Start time" name="start_time" />
</div>

See Input — Width for more layout examples (grid columns, mixed widths).

Why Native?

The native <input type="time"> provides:

  • Zero dependencies — no JavaScript time picker library to ship
  • Automatic localization — the browser renders AM/PM or 24-hour based on OS locale
  • Full accessibility — arrow keys, spinners, and keyboard input work out of the box
  • Mobile keyboards — native time wheels on iOS, spinners on Android
  • Consistent value format — always HH:MM regardless of display

Optimistic UI

Pass the name of the Livewire method this component should call and the change appears immediately, then confirms or undoes itself when the server answers:

<x-wirekit::time-picker
    name="start"
    :value="$start"
    optimistic="setStart"
/>

Load wirekit-optimistic.js alongside whichever bundle you already use — it is a separate file so applications that do not use it pay nothing for it:

@wirekitScripts
<script src="{{ asset('vendor/wirekit/wirekit-optimistic.js') }}"></script>

Try it

The demo below runs the real path: the change shows immediately, the outline says it is provisional, and the server's answer either confirms it silently or takes it back.

Optimistic time — accepted, refused, and a slow answer

The <livewire:demos.…> wrapper above exists only on this site — it supplies the demo methods so the page can show a real round trip. The block under it is what you write.

The same shape as the other native form controls: the browser has already changed the value by the time any handler runs, so what this adds is the confirmation, the undo, and the announcement.

What a screen reader hears is the same for every component that supports this, and it is written out in full — one hedged announcement at the change, silence on confirmation, one more only if the server refuses, and focus that never moves — in Optimistic UI — the announcement contract. That page is also where the boundary is stated: this covers mutations, not sorting, filtering or pagination.

Props

Prop Type Default Description
optimistic string|null null Livewire method to call, showing the new value before the server confirms it. See Optimistic UI.
optimisticArgs array [] Extra arguments appended to the optimistic action call, after the new value — the row this control belongs to.
label string|null null Label text above the input
hint string|null null Help text below the input
error string|null null Error message (also reads from $errors)
name string|null null Form field name
id string|null auto-generated Element id
value string|null null Initial time in HH:MM format
format string '24h' '24h' or '12h' (display hint)
step int|null null Step interval in seconds
size string 'md' 'sm', 'md', 'lg'
disabled bool false Disabled state
required bool false Required field
scope string|null null Scoped personalization key

Accessibility

  • Native <input type="time"> — full browser a11y and keyboard support
  • aria-invalid="true" and aria-describedby set on error
  • aria-required="true" when required
  • Hint text linked via aria-describedby
  • Focus ring visible via focus-visible styling
  • Arrow keys increment/decrement hours and minutes (native behavior)
  • The value is always submitted in ISO HH:MM format regardless of locale display

Keyboard Interaction

Key Action
Tab Move focus into the time input
Type HH:MM characters Set the value directly
ArrowUp / ArrowDown Step the focused field by ±1

Pitfalls

  • Don't use time-picker for durations. Native <input type="time"> represents a clock time, not "2 hours 30 minutes". For durations use two <x-wirekit::number-input> (hours / minutes).

Design Tokens

Token Purpose
--color-wk-bg-input Input background
--color-wk-border-strong Default border color
--color-wk-border-error Border color on error
--color-wk-text Input text color
--color-wk-text-placeholder Placeholder text color
--color-wk-ring Focus ring color
--size-wk-sm / md / lg Input height per size variant
--radius-wk-md Border radius
--padding-wk-x-md Horizontal padding
--text-wk-md Font size
--transition-wk-duration Focus/error transition speed
--opacity-wk-disabled Dimmed state when disabled

Customization

Override defaults in config/wirekit.php:

'components' => [
    'time-picker' => ['size' => 'md', 'format' => '24h'],
],

Further Reading

Was this page helpful?

Voting requires cookies or local storage. What we store