Time picker
A time field that understands what people type, offers a list of times at a fixed step and follows the locale's 12 or 24 hour clock.
npx prodular-ui add time-pickerStart and end
15 minute steps between 7 AM and 8 PM. The end is checked against the start.
Month end review with Kestrel Health, 45 minutes.
"use client"
import * as React from "react"
import { Field, FieldDescription, FieldLabel } from "@/components/ui/field"import { TimePicker } from "@/components/ui/time-picker"
const minutes = (t: string) => Number(t.slice(0, 2)) * 60 + Number(t.slice(3))
export default function TimePickerSchedule() { const [start, setStart] = React.useState<string | null>("09:30") const [end, setEnd] = React.useState<string | null>("10:15") const backwards = start && end ? minutes(end) <= minutes(start) : false const length = start && end && !backwards ? minutes(end) - minutes(start) : null
return ( <div className="grid w-full max-w-md gap-4 sm:grid-cols-2"> <Field> <FieldLabel>Starts</FieldLabel> <TimePicker value={start} onValueChange={setStart} step={15} min="07:00" max="20:00" hourCycle={12} locale="en-US" /> </Field> <Field invalid={backwards}> <FieldLabel>Ends</FieldLabel> <TimePicker value={end} onValueChange={setEnd} step={15} min="07:00" max="20:00" hourCycle={12} locale="en-US" aria-invalid={backwards} /> </Field> <FieldDescription className={backwards ? "text-destructive-subtle-foreground sm:col-span-2" : "tabular-nums sm:col-span-2"}> {backwards ? "The review has to end after it starts." : length ? `Month end review with Kestrel Health, ${length} minutes.` : "Pick both times."} </FieldDescription> </div> )}24 hour clock
The locale decides the clock. Arrow keys step by 30 minutes while the list is closed.
Uses 24 hour time from the en-GB locale. Type 1830, 6:30 pm or use the arrow keys to step by 30 minutes.
"use client"
import * as React from "react"
import { Field, FieldDescription, FieldLabel } from "@/components/ui/field"import { TimePicker } from "@/components/ui/time-picker"
export default function TimePickerTwentyFour() { const [time, setTime] = React.useState<string | null>("18:00") return ( <Field className="w-full max-w-56"> <FieldLabel>Daily payout run</FieldLabel> <TimePicker value={time} onValueChange={setTime} step={30} locale="en-GB" /> <FieldDescription> Uses 24 hour time from the en-GB locale. Type 1830, 6:30 pm or use the arrow keys to step by 30 minutes. </FieldDescription> </Field> )}Anatomy
<Field> <FieldLabel>Starts</FieldLabel> <TimePicker value={start} onValueChange={setStart} step={15} min="07:00" max="20:00" /></Field>Guidance
Use it when
- Picking a time of day: meetings, schedules, cut-offs, reminders.
- step to match how precise the time needs to be: 15 or 30 minutes for meetings, 5 for reminders.
Avoid
- Durations like 45 minutes. Use Number input with a unit.
- A time that always comes with a date. Put a Calendar and the Time picker side by side in one Field group.
Rules for AI agents
Published in llms-full.txt, the registry and the MCP server, so coding agents follow them when they build with this component.
- Store and pass the value as 24 hour "HH:mm". Only the display follows the locale.
- Pass the user's locale, and hourCycle only when the product overrides it.
- Set min and max for business hours; typed times outside them are marked invalid instead of being clamped silently.
- For a start and end pair, check end after start yourself and show the message in FieldDescription with aria-invalid on the end field.
- Time zones are not part of the value. Show the zone next to the field when it is not the user's own.
API
TimePicker
| Prop | Type | Default | Description |
|---|---|---|---|
| value / defaultValue / onValueChange | string | null | 24 hour "HH:mm". Null when empty. | |
| step | number | 15 | Minutes between listed times, and the arrow key step. |
| min / max | "HH:mm" | "00:00" / "23:59" | The range offered and accepted. |
| hourCycle | 12 | 24 | Defaults to the locale. | |
| locale | string | Formats the display, for example en-US or en-GB. | |
| name | string | Renders a hidden input with the HH:mm value for form posts. |
parseTime
| Prop | Type | Default | Description |
|---|---|---|---|
| (text, hourCycle) | number | null | The parser the field uses, returning minutes after midnight. |
Installation
The Prodular UI CLI adds the source to components/ui with everything it depends on. In a project that already uses shadcn/ui, the shadcn CLI installs it from the Prodular registry too. See Installation for the first setup.
npx prodular-ui add time-picker# or, with the registry in components.jsonnpx shadcn@latest add @prodular/time-picker