Time Picker
Type a localized time in editable hour, minute and optional second blocks, or open native time choices. Valid edits update immediately. Hour choices follow the locale and hour-cycle override. Unavailable choices are disabled, including overnight bounds. Native forms submit one canonical time, and native time entry remains available before JavaScript.
Type or choose a time
Type within the time blocks, paste an ISO time, or open the clock action for localized choices. Valid edits update immediately.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-form-field/ui-form-field.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-time-picker/ui-time-picker.html"
>
<ui-form-field>
<label
slot="label"
for="appointment-time"
>Appointment time</label>
<ui-time-picker
input-id="appointment-time"
name="appointment"
value="14:30"
locale="en-US"
></ui-time-picker>
<small
slot="help"
>Choose a time between 12:00 AM and 11:59 PM.</small>
</ui-form-field><script setup>
import { UiFormField, UiTimePicker } from "@threadlabs/looma";
</script>
<template>
<UiFormField>
<template #label>
<label
for="appointment-time"
>Appointment time</label>
</template>
<UiTimePicker
input-id="appointment-time"
name="appointment"
value="14:30"
locale="en-US"
/>
<template #help>
<small>Choose a time between 12:00 AM and 11:59 PM.</small>
</template>
</UiFormField>
</template>import { UiFormField, UiTimePicker } from "@threadlabs/looma";
export default function Example() {
return <UiFormField
slots={{
label: <label
htmlFor="appointment-time"
>Appointment time</label>,
help: <small>Choose a time between 12:00 AM and 11:59 PM.</small>,
}}
>
<UiTimePicker
inputId="appointment-time"
name="appointment"
value="14:30"
locale="en-US"
/>
</UiFormField>;
}/** @jsxImportSource preact */
import { UiFormField, UiTimePicker } from "@threadlabs/looma";
export default function Example() {
return <UiFormField
slots={{
label: <label
htmlFor="appointment-time"
>Appointment time</label>,
help: <small>Choose a time between 12:00 AM and 11:59 PM.</small>,
}}
>
<UiTimePicker
inputId="appointment-time"
name="appointment"
value="14:30"
locale="en-US"
/>
</UiFormField>;
}<script>
import { UiFormField, UiTimePicker } from "@threadlabs/looma";
</script>
{#snippet label()}
<label
for="appointment-time"
>Appointment time</label>
{/snippet}
{#snippet help()}
<small>Choose a time between 12:00 AM and 11:59 PM.</small>
{/snippet}
<UiFormField
slots={{ label, help }}
>
<UiTimePicker
inputId="appointment-time"
name="appointment"
value="14:30"
locale="en-US"
/>
</UiFormField>import { Component } from "@angular/core";
import { UiFormField, UiTimePicker } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiFormField, UiTimePicker],
template: `
<div
ui-form-field
>
<ng-container ngProjectAs="[slot='label']">
<label
for="appointment-time"
>Appointment time</label>
</ng-container>
<span
ui-time-picker
[inputId]="'appointment-time'"
[name]="'appointment'"
[value]="'14:30'"
[locale]="'en-US'"
></span>
<ng-container ngProjectAs="[slot='help']">
<small>Choose a time between 12:00 AM and 11:59 PM.</small>
</ng-container>
</div>
`,
})
export default class Example {}Overnight bounds and seconds
A maximum before the minimum wraps midnight. Existing fractions stay intact while the picker edits hours, minutes and seconds.
Code
<link
rel="component"
href="@threadlabs/looma/components/ui-form-field/ui-form-field.html"
>
<link
rel="component"
href="@threadlabs/looma/components/ui-time-picker/ui-time-picker.html"
>
<ui-form-field>
<label
slot="label"
for="overnight-time"
>Time</label>
<ui-time-picker
input-id="overnight-time"
name="time"
value="23:15:30.125"
min="21:00"
max="03:00"
granularity="second"
locale="en-US"
></ui-time-picker>
<small
slot="help"
>Available from 9:00 PM through 3:00 AM.</small>
</ui-form-field><script setup>
import { UiFormField, UiTimePicker } from "@threadlabs/looma";
</script>
<template>
<UiFormField>
<template #label>
<label
for="overnight-time"
>Time</label>
</template>
<UiTimePicker
input-id="overnight-time"
name="time"
value="23:15:30.125"
min="21:00"
max="03:00"
granularity="second"
locale="en-US"
/>
<template #help>
<small>Available from 9:00 PM through 3:00 AM.</small>
</template>
</UiFormField>
</template>import { UiFormField, UiTimePicker } from "@threadlabs/looma";
export default function Example() {
return <UiFormField
slots={{
label: <label
htmlFor="overnight-time"
>Time</label>,
help: <small>Available from 9:00 PM through 3:00 AM.</small>,
}}
>
<UiTimePicker
inputId="overnight-time"
name="time"
value="23:15:30.125"
min="21:00"
max="03:00"
granularity="second"
locale="en-US"
/>
</UiFormField>;
}/** @jsxImportSource preact */
import { UiFormField, UiTimePicker } from "@threadlabs/looma";
export default function Example() {
return <UiFormField
slots={{
label: <label
htmlFor="overnight-time"
>Time</label>,
help: <small>Available from 9:00 PM through 3:00 AM.</small>,
}}
>
<UiTimePicker
inputId="overnight-time"
name="time"
value="23:15:30.125"
min="21:00"
max="03:00"
granularity="second"
locale="en-US"
/>
</UiFormField>;
}<script>
import { UiFormField, UiTimePicker } from "@threadlabs/looma";
</script>
{#snippet label()}
<label
for="overnight-time"
>Time</label>
{/snippet}
{#snippet help()}
<small>Available from 9:00 PM through 3:00 AM.</small>
{/snippet}
<UiFormField
slots={{ label, help }}
>
<UiTimePicker
inputId="overnight-time"
name="time"
value="23:15:30.125"
min="21:00"
max="03:00"
granularity="second"
locale="en-US"
/>
</UiFormField>import { Component } from "@angular/core";
import { UiFormField, UiTimePicker } from "@threadlabs/looma";
@Component({
selector: "example-view",
standalone: true,
imports: [UiFormField, UiTimePicker],
template: `
<div
ui-form-field
>
<ng-container ngProjectAs="[slot='label']">
<label
for="overnight-time"
>Time</label>
</ng-container>
<span
ui-time-picker
[inputId]="'overnight-time'"
[name]="'time'"
[value]="'23:15:30.125'"
[min]="'21:00'"
[max]="'03:00'"
[granularity]="'second'"
[locale]="'en-US'"
></span>
<ng-container ngProjectAs="[slot='help']">
<small>Available from 9:00 PM through 3:00 AM.</small>
</ng-container>
</div>
`,
})
export default class Example {}API
Package: @threadlabs/looma · Native root: span
Attributes
| Name | Description | Property | Type | Default | Allowed values |
|---|---|---|---|---|---|
disabled | Prevents editing/opening and omits native submission. | disabled | boolean | false | — |
form | Optional external form ID. | form | string | | — |
granularity | Smallest displayed time unit. Existing seconds and fractions are preserved. | granularity | keyword | minute | minute, second |
hour-cycle | Hour cycle for the field and picker choices; omission follows the locale. | hourCycle | keyword | — | h11, h12, h23, h24 |
hour-label | Visible hour editor label. | hourLabel | string | Hour | — |
input-id | ID of the active native input for an authored label. | inputId | string | | — |
invalid | External invalid appearance supplied by the application, independent of parsed validity. | invalid | boolean | false | — |
label | Optional accessible field name; prefer an authored visible label. | label | string | | — |
locale | Intl locale for typed time and display. ISO time paste is always accepted. | locale | string | en-US | — |
max | Inclusive latest permitted time, in canonical ISO time format. | max | string | | — |
min | Inclusive earliest time. Bounds may wrap midnight when max precedes min. | min | string | | — |
minute-label | Visible minute editor label. | minuteLabel | string | Minute | — |
name | Native form field name for the canonical time. | name | string | | — |
picker-label | Accessible name of the trigger and picker dialog. | pickerLabel | string | Choose time | — |
placeholder | Optional hint inside the empty field. | placeholder | string | | — |
readonly | Prevents editing/opening while retaining selection and submission. | readonly | boolean | false | — |
required | Requires a complete time. | required | boolean | false | — |
second-label | Visible second editor label. | secondLabel | string | Second | — |
size | Shared field and trigger size. | size | keyword | md | sm, md, lg |
value | Initial canonical time, replaced when changed externally. Reset restores this external value. | value | string | | — |
Framework props
| Name | Type | Default | Allowed values |
|---|---|---|---|
disabled | boolean | false | — |
form | string | | — |
granularity | "minute" | "second" | minute | minute, second |
hourCycle | "h11" | "h12" | "h23" | "h24" | — | h11, h12, h23, h24 |
hourLabel | string | Hour | — |
inputId | string | | — |
invalid | boolean | false | — |
label | string | | — |
locale | string | en-US | — |
max | string | | — |
min | string | | — |
minuteLabel | string | Minute | — |
name | string | | — |
pickerLabel | string | Choose time | — |
placeholder | string | | — |
readonly | boolean | false | — |
required | boolean | false | — |
secondLabel | string | Second | — |
size | "sm" | "md" | "lg" | md | sm, md, lg |
value | string | | — |
Events
| Name | Detail | Description |
|---|---|---|
change | object
| Emitted when a toggleable control changes checked state. |
close | object
| Emitted when the component transitions to a closed state. |
input | object
| Emitted with the declared detail payload. |
open | object
| Emitted when the component transitions to an open state. |
query-change | object
| Emitted with the declared detail payload. |
validation-change | object
| Emitted with the declared detail payload. |
Slots
No slots.
Design tokens
Set shared theme properties on a theme boundary. Component hooks apply only to their owning component.
Component tokens
No component tokens.
Shared tokens
No shared tokens.