TimeField
Type a time or pick one from a list, in the 12 or 24 hour clock.
SourcePackage @weft-js/warp
Preview
tsx
import { Stack, TimeField } from '@weft-js/warp'import type { IsoDate } from '@weft-js/warp'export function Clock() { return ( <Stack gap="group"> <TimeField label="12-hour" today={TODAY} defaultValue="14:30" hourCycle="h12" /> <TimeField label="24-hour" today={TODAY} defaultValue="14:30" hourCycle="h23" /> <TimeField label="With seconds" today={TODAY} defaultValue="14:30:15" hourCycle="h23" seconds /> </Stack> )}const TODAY: IsoDate = '2026-11-02'Installation
npm install @weft-js/warpUsage
tsx
import { TimeField } from '@weft-js/warp'<Stack gap="group"> <TimeField label="12-hour" today={TODAY} defaultValue="14:30" hourCycle="h12" /> <TimeField label="24-hour" today={TODAY} defaultValue="14:30" hourCycle="h23" /> <TimeField label="With seconds" today={TODAY} defaultValue="14:30:15" hourCycle="h23" seconds /></Stack>Only some times
slots replaces the list with the times you allow.
tsx
import { TimeField } from '@weft-js/warp'import type { IsoDate, IsoTime } from '@weft-js/warp'export function Slots() { return ( <TimeField label="Onboarding call" hint="Only the times Priya is free" today={TODAY} defaultValue="11:00" slots={SLOTS} /> )}const TODAY: IsoDate = '2026-11-02'const SLOTS: IsoTime[] = ['09:00', '09:30', '11:00', '14:00', '15:30', '16:00']Office hours
min, max and step shape the list.
tsx
import { TimeField } from '@weft-js/warp'import type { IsoDate } from '@weft-js/warp'export function Hours() { return ( <TimeField label="Deploy window opens" hint="Office hours" today={TODAY} defaultValue="10:00" min="08:00" max="18:00" step={60} /> )}const min = 60_000const TODAY: IsoDate = '2026-11-02'When the clocks change
With date and timeZone, a time that happens twice or not at all gets a hint.
tsx
import { TimeField } from '@weft-js/warp'import type { IsoDate } from '@weft-js/warp'export function ClocksChange() { return ( <TimeField label="Nightly backup" today={TODAY} defaultValue="01:30" date="2026-11-01" timeZone="America/New_York" /> )}const TODAY: IsoDate = '2026-11-02'Quiet hours
Use step to set how many minutes apart the times are, here 30.
tsx
import { state } from '@weft-js/core'import { Row, Stack, Text, TimeField } from '@weft-js/warp'import type { IsoDate, IsoTime } from '@weft-js/warp'export function QuietHours() { const from = state<IsoTime | null>('22:00') const to = state<IsoTime | null>('07:30') return ( <Stack gap="related"> <Row gap="related" wrap={false}> <TimeField label="Quiet from" today={TODAY} value={from} step={30} /> <TimeField label="Until" today={TODAY} value={to} step={30} /> </Row> <Text subtle role="caption">No alerts from {from.value ?? '…'} to {to.value ?? '…'}, except failed deploys.</Text> </Stack> )}const TODAY: IsoDate = '2026-11-02'Accessibility
- Up/Down
- Changes the hour or minute
- Arrowsinthelist
- Move through the times
- Enter
- Picks the time
- Escape
- Closes the list
API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
label | string | — | The accessible name, drawn as the floating border label (or above, classic). Required. |
hint | unknown | — | One line of help under the control. |
error | unknown | — | Shown instead of the hint; marks the field invalid. |
icon | IconRef | — | Leading icon: it sweeps with the border. |
prefix | unknown | — | Text or an element inside the field before the value, such as $. |
suffix | unknown | — | Text or an element inside the field after the value, such as kg. |
variant | "floating" | "classic" | — | floating (default, or the app's warp({ fields })) · classic: the label above. |
appearance | "line" | — | line: only a bottom line under the value, no box or fill. The boxed field otherwise. |
size | "sm" | "md" | "lg" | 'md' | Control size. md by default. |
clearable | boolean | false | A clear button (shown once there is a value). |
counter | number | — | Maximum length, shown as a counter. |
id | string | — | The element id. One is made for you if you leave it out. |
disabled | boolean | false | Turns it off, and takes it out of the tab order. |
readonly | boolean | false | Shows the value and lets it be selected and copied, but not changed. |
required | boolean | false | The form will not submit without it. |
name | string | — | The name it posts under in a form. |
locale | string | — | The language and region used to format values. |
today | string | — | Pins "today" (server render, tests); the browser's clock otherwise. |
presentation | Presentation | — | auto opens a popover, or a sheet when the viewport is under 600px wide; popover and sheet force one. |
value | IsoTime | State<IsoTime | null> | null | — | The current value, when you own the state. |
defaultValue | IsoTime | null | — | The starting value, when the component owns the state. |
open | boolean | State<boolean> | — | A state box that holds whether it is open. |
defaultOpen | boolean | false | Starts open, when the component keeps its own open state. |
hourCycle | "auto" | "h12" | "h23" | — | h12 shows AM and PM, h23 a 24-hour clock, auto the locale's. |
step | number | 15 | Minutes between listed times. |
seconds | boolean | false | Adds a seconds segment. |
min | IsoTime | — | The lowest allowed value. |
max | IsoTime | — | The highest allowed value. |
slots | IsoTime[] | — | The exact times to list. |
date | `${number}-${number}-${number}` | — | Only for the daylight saving hint. |
timeZone | string | — | Only for the daylight saving hint. |
| Event | Type | Default | Description |
|---|---|---|---|
onInput | ((e: InputEvent & { currentTarget: HTMLInputElement & HTMLTextAreaElemen… | — | Called on each keystroke. |
onValueChange | ((v: IsoTime | null, reason: ChangeReason) => void) | — | Called with each new value, and whether a pointer, a key or code made the change. |
onOpenChange | ((o: boolean) => void) | — | Called with true when it opens and false when it closes. |