Skip to main content
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

Regardless of how the field is displayed, the submitted value is always in 24-hour HH:MM format (the native <input type="time"> standard).

Note: Whether the field reads as AM/PM or as 24 hours is decided entirely by the browser and the operating system locale — HTML has no attribute that overrides it, so neither does WireKit. The format prop records which reading your interface is written for; it does not change what the control shows. If a specific display is a hard requirement, render the time as text next to the field and keep the input for editing.

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). It reaches the native control, so it governs both what the field accepts and how far ArrowUp / ArrowDown move the focused segment. Left unset, the browser's own default of one minute applies.

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
    label="Start time"
    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') }}" defer></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
help string|null null An explanation of the field, shown in a tooltip from a question mark beside the label and read as the field's description. Needs a label to stand beside. See Help beside the label
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|DateTimeInterface|null null Initial time in HH:MM format, or a date object, which is written as its time of day
min string|DateTimeInterface|null null Earliest accepted time (HH:MM or a date object)
max string|DateTimeInterface|null null Latest accepted time (HH:MM or a date object)
format string '24h' '24h' or '12h' — records the reading your interface is written for; the browser and OS locale decide what is shown
step int|null null Step interval in seconds, passed to the native step attribute
size string 'md' 'sm', 'md', 'lg'
disabled bool false Disabled state
required bool false Required field
scope string|null null Scoped personalization key
announceError bool|null null Render the error message in an aria-live="polite" region so a validation error that appears after render reaches a screen reader. Precedence: this prop, then the parent <x-wirekit::form :announce-errors>, then config('wirekit.a11y.announce_error'). Set false when the page runs its own live region.

Slots

Slot Description
labelAfter Markup after the label and its help question mark, in the same row and outside both, such as a badge that says a setting is not decided yet. See A Mark After the Label.

Accessibility

  • Native <input type="time"> — full browser a11y and keyboard support
  • aria-invalid="true" and aria-describedby set on error
  • required passes straight through to the native input, which is what announces the field as required — no aria-required is added, because on a native control the attribute would only restate what the element already exposes
  • 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).
  • Don't bind a date object. Livewire sends a Carbon property, or a property that holds a date, to the browser as a full timestamp, which <input type="time"> drops, so the field stays empty. Bind a string property that holds ->format('H:i') and convert it when you save. In debug mode the component logs a warning for a binding to a date object.

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'],
],

Further Reading

Updated in WireKit v2.66.0 (2026-10-13)

Was this page helpful?

Thank you for your feedback!

Voting requires cookies or local storage. What we store