Skip to main content
Urbicon UI

TimeInputbeta

A field for entering a time of day: hour, minute and optional seconds cells, stepped with the Arrow keys and shown in 12- or 24-hour. The bound value is a 24-hour string (HH:MM, or HH:MM:SS with seconds), and null while any segment is empty.

Playground

Time
Format
Size Style variant
Variant Style variant
Tier Style variant
Intent Style variant
<TimeInput />

01 Examples

Display format vs. bound value

format="12h" adds an AM/PM segment and withSeconds adds a seconds segment, but both change only what the field shows. The bound value stays a 24-hour string: 14:15 displays as 02:15 PM and still binds as 14:15. It is null while any segment is empty — mid-entry as well as for an untouched field.
Start

Value: 09:30

Meeting
AM

Value (24h): 14:15

Duration

Value: 13:45:30

<script>
  import { TimeInput } from '@urbicon-ui/blocks';
  let startTime = $state('09:30');
  let meetingTime = $state('14:15');
  let preciseTime = $state('13:45:30');
</script>
<TimeInput label="Start" bind:value={startTime} />
<TimeInput label="Meeting" format="12h" bind:value={meetingTime} />
<TimeInput label="Duration" withSeconds bind:value={preciseTime} />

Range bounds

Type 06:00 and click away: values below min or above max clamp back into range on blur, and onValueChange fires with the corrected time. There is no out-of-range state — if 19:30 must be rejected rather than moved, validate before you offer the field.
Appointment
Office hours

Value: 09:00

<script>
  let officeTime = $state('09:00');
</script>
<TimeInput
  label="Appointment"
  min="08:00"
  max="18:00"
  helper="Office hours"
  bind:value={officeTime}
/>

Error state

Pass error to colour the field danger, override the helper, and mark the segments aria-invalid; the message is announced via role="alert".
Time

Value:

<script>
  let errorTime = $state(null);
</script>
<TimeInput label="Time" error="Please pick a time" bind:value={errorTime} />

02 Date + Time

TimeInput is the form family's time field: Calendar, DatePicker and DateRangePicker are for dates, TimeInput for the time of day. It edits only the time, so for a full timestamp pair it with a DatePicker as two separate fields. Each keeps its own value — an ISO date from the picker, an HH:MM string from the time field — and you join them yourself, as the example below does. What you get is a local wall-clock time, not a point in time: turning 2026-08-15T14:30 into an instant needs a time zone, and that decision stays with you.

Date and time in one row

Both fields default to full width, so a row needs w-auto on each — without it they stack at every width. flex-wrap then breaks the row when the container gets too narrow for both, which this docs column does at 1024 px.
Time

Date: 2026-08-15 · Time: 14:30 · Joined: 2026-08-15T14:30

<script>
  import { DatePicker, TimeInput } from '@urbicon-ui/blocks';

  let apptDate = $state('2026-08-15');
  let apptTime = $state('14:30');

  // A local wall-clock string. Give it a time zone before it becomes an instant.
  const startsAt = $derived(apptDate && apptTime ? `${apptDate}T${apptTime}` : null);
</script>

<div class="flex flex-wrap items-end gap-3">
  <DatePicker label="Date" class="w-auto" bind:value={apptDate} />
  <TimeInput label="Time" class="w-auto" bind:value={apptTime} />
</div>

03 Customization

For a reusable look, register a named preset on <BlocksProvider>; for individual parts, use slotClasses. The slots are wrapper (what class also targets), label, field, icon (replace the clock with your own snippet via the icon prop), segment, separator, meridiem, and message. For a full ground-up restyle, set unstyled to drop every default class and rebuild from the slots.

showIcon={false} hides the leading clock icon, and fullWidth stretches the field to fill its container instead of hugging its content.

Boarding-pass segments via slotClasses

Each segment gets its own box, so the field reads as three fields rather than one.
Departure
<TimeInput
  label="Departure"
  bind:value={departure}
  slotClasses={{
    field: 'gap-1 border-transparent bg-transparent px-0',
    segment: 'rounded-modify border border-border-default bg-surface-subtle px-2 py-1 font-mono',
    separator: 'text-text-tertiary'
  }}
/>

04 Accessibility

Group semantics

The field is a role="group" named by its label (or aria-label).

Per-segment naming

Each segment (hour, minute, and, when present, second) carries its own aria-label.

Keyboard

Arrow Up / Down moves the focused segment by one and wraps inside it — 59 goes to 00 without carrying the hour. Arrow Left / Right moves between segments; typing digits auto-advances to the next. min and max do not limit stepping; they apply on blur.

The AM/PM segment

The AM/PM segment toggles by click, the Arrow keys, Enter / Space, or the A / P keys.

Clamping

Out-of-range values clamp to min / max when the field loses focus.

Errors are announced

The error message is announced via role="alert".

05 API Reference

28 props
28 props
Prop
Type
Default
Description

06 Types

Local type definitions used by this component.

5 types
Name
Kind
Category
Used by
Description

07 Installation

Import

import { TimeInput } from '@urbicon-ui/blocks';