TimeField

A React time picker - a segmented HH:mm input with full keyboard control. For forms, bookings and schedules.

TimeField playground

0900
Display only - the committed value stays canonical 24h 'HH:mm' either way.

Install TimeField

1. New project? One command installs the package and wires everything - see Installation:

bash
pnpm dlx zyncat-ui init

2. Import the component - it loads its own stylesheet:

tsx
import { TimeField } from '@zyncat/ui/time-field';

Usage

tsx
import { TimeField } from '@zyncat/ui/time-field';
 
<TimeField label="Broadcast time" value={time} onChange={setTime} />

Compose TimeField in your application. No Tailwind or external styling library is required; every value resolves from Zyncat UI's token vocabulary.

TimeField props

TimeField

PropTypeDefaultDescription
valuestring | null—Controlled value, canonical 'HH:mm' (24h).
defaultValuestring | nullnullUncontrolled initial value, 'HH:mm' (24h). Use instead of `value`.
onChange(value: string) => void—Fires live - the instant both segments exist.
labelstring—Field label rendered above the box; also the segments' `aria-label` fallback.
format'24h' | '12h'—Display only; storage stays 24h. Default '24h'.
minuteStepnumber—↑/↓ step granularity in minutes (typing is exact). Default 5.
minstring—Lower bound 'HH:mm' - saturates, never errors.
maxstring—Upper bound 'HH:mm' - saturates, never errors.
requiredbooleanfalseAsterisk on the label.
invalidbooleanfalseDanger border + message color (.zc-fld.zc-is-error).
messagestring—Helper / error text under the field.
disabledbooleanfalseDisable the field.
size'sm' | 'md' | 'lg''md'Control height, type and padding - the same scale as `TextField`, so a form row can hold one size throughout.
classNamestring—Extra class on the field shell root.
...htmlAttributesHTMLAttributes<HTMLDivElement> & DataAttributes—Standard <div> attributes (style, data-*, aria-*, ...) forwarded to the field shell root.
activateOnActivateOn'pointerdown'Whether the trigger, the day cells and the panel controls fire on `pointerdown` (snappier) or wait for `click`. (Not used by TimeField, which is inline.)
animationDisableableAnimation—Popover open/close timing - motion tokens only, or `null` to disable. (Not used by TimeField, which is inline.)

Frequently asked questions

Import it per subpath and give it a label and a value: import { TimeField } from '@zyncat/ui/time-field', then <TimeField label="Send at" value={time} onChange={setTime} />. Unlike a popover-based date picker, TimeField is inline - two segments for hours and minutes (a third AM/PM segment appears when format="12h") sitting directly in the field - and onChange fires the instant both segments are filled, no separate confirm step. It's a client component, so it drops straight into the Next.js App Router; pass defaultValue instead of value to run it uncontrolled.

No. The format prop only changes how the field displays and lets you type the hour - 1 to 12 plus an AM/PM segment, or 0 to 23 - the value committed through onChange, and value, defaultValue, min and max themselves, are always the canonical 24-hour 'HH:mm' string. '14:30' is '14:30' whether the field is showing "2:30 PM" or "14:30".

Pass min and/or max as 'HH:mm', both inclusive: <TimeField min="09:00" max="17:00" /> keeps every pick inside a business day. The bounds saturate rather than reject - typing or arrowing past an edge clamps straight to min or max instead of refusing the keystroke, so the field can never commit a time outside the window.

Yes - each segment is a real role="spinbutton". Type digits and the hour segment auto-advances to minutes once the entry is unambiguous, Arrow Up/Down step the hour by 1 and the minute by minuteStep, Backspace clears a segment, and Left/Right or the colon key move between segments. Pasting a time like "2:30pm" or "14:30" fills every segment in one go.

Set minuteStep (default 5) - it governs the Up/Down arrow increment on the minute segment, so minuteStep={15} steps 00, 15, 30, 45. Typing stays exact to the minute regardless of the step, so a keyboard or paste entry can still land on any minute from 00 to 59.

The native time input's look and interaction vary by browser and OS, and it can't be themed. TimeField is a styled, segmented HH:mm control built from ordinary system tokens - --accent, --danger, --font-code, --ring-accent - so it matches the rest of a Zyncat UI form and behaves identically everywhere, with zero runtime dependencies beyond React 19 as a peer.

Set in Geist & Newsreader — animated by the house engineZyncat UI · Rev 0.11 · MIT · Built by Tabsir Ahammed · Source on GitHub