Skip to content
Drivn
4 min read

React Time Picker Component Examples

Copy-paste React Time Picker examples: a default 24-hour picker, a 12-hour AM/PM clock, a picker with seconds, a custom format, and the native input fallback.

A time picker lets a user choose an hour and minute without typing into a free-form field — the right control for booking slots, scheduling reminders, or setting a shift start. The Time Picker component in Drivn is a scrolling column dropdown built on Drivn's own Popover and Input. There is no Radix, no cva, and no date library — just React, cn(), and the components you already installed — so the value is a plain Date object and the whole thing is source you own after npx drivn add time-picker.

The component is controlled: you hold the selected time in React.useState<Date | undefined>() and pass selected and onSelect. Every example below is TypeScript, because Drivn ships TypeScript-only .tsx source installed by the Drivn CLI under @/components/ui/time-picker. When the dropdown opens, each column auto-scrolls the selected value to its centre, and picking a number calls onSelect with a new Date.

The examples cover the default 24-hour picker, a 12-hour clock with an AM/PM column, a picker that adds a seconds column, a custom formatTime for locale-specific display, and TimePicker.Input — the native <input type="time"> fallback for when you want the lightweight browser control instead of the scrolling dropdown.

A default 24-hour time picker

The simplest use is a controlled TimePicker in its default 24-hour mode. Hold the selected time in React.useState<Date | undefined>(), pass selected and onSelect, and the trigger shows a Clock icon with the formatted time or the Pick a time placeholder. Opening the trigger reveals two scrolling columns — hours 0023 and minutes 0059 — each auto-centred on the current value.

The wrapper is marked 'use client' because it holds state with useState. Picking a value calls onSelect with a fresh Date, so the time flows back into your component as a real Date object you can store, format, or submit. This is the right default for most scheduling fields; see the full prop list on the Time Picker reference.

1"use client"
2
3import * as React from "react"
4import { TimePicker } from "@/components/ui/time-picker"
5
6export default function DefaultTimePicker() {
7 const [time, setTime] = React.useState<Date | undefined>()
8
9 return (
10 <TimePicker
11 selected={time}
12 onSelect={setTime}
13 />
14 )
15}

A 12-hour clock with AM/PM

To show a 12-hour clock, pass format="12h". The hours column now runs 0112, and an AM/PM column appears beside the minutes. Internally the component derives the period from whether the hour is 12 or more and converts your AM/PM choice back to a 24-hour Date with its to24 helper, so onSelect still hands you a standard Date regardless of the display format.

This is the format most North American scheduling UIs expect. Because the conversion happens inside the component, you never deal with 12-hour math yourself — you read and write a Date, and the picker handles the AM/PM bookkeeping. Pair it with a Date Picker when you need a full date-and-time field.

1<TimePicker
2 selected={time}
3 onSelect={setTime}
4 format="12h"
5/>

Adding a seconds column

When minute precision is not enough, pass showSeconds to add a third scrolling column for seconds. The values run 0059, matching the minutes column, and selecting a second updates the Date with that exact second. This is the control for timers, precise logging, or any field where the second matters.

The seconds column slots in between minutes and the AM/PM column (in 12-hour mode), and the auto-centre scroll applies to it just like the others. Combine showSeconds with format="12h" and you get hours, minutes, seconds, and AM/PM in one dropdown — every column built from the same Column sub-component, so they all behave identically.

1<TimePicker
2 selected={time}
3 onSelect={setTime}
4 showSeconds
5/>

A custom display format

By default the trigger formats the selected time with toLocaleTimeString using your format and showSeconds settings. To control the displayed string yourself — for a specific locale, a 24-hour rendering, or a shorter label — pass a formatTime function. It receives the selected Date and returns the string shown in the trigger; the scrolling columns are unaffected.

This is how you render a Czech, German, or any locale-specific time in the trigger while keeping the picker logic identical. Because formatTime only changes the trigger label, you can format display one way and still store the underlying Date however your backend expects — the selection and the display are fully decoupled.

1<TimePicker
2 selected={time}
3 onSelect={setTime}
4 formatTime={(d) =>
5 d.toLocaleTimeString("cs-CZ", {
6 hour: "2-digit",
7 minute: "2-digit",
8 })
9 }
10/>

The native input fallback

When you want the lightweight browser time control instead of the scrolling dropdown, use TimePicker.Input. It wraps the native <input type="time"> inside Drivn's Input component, formats the selected Date into an HH:MM value string, and parses changes back into a Date on onSelect. On mobile this gives you the operating system's built-in time UI for free.

The same selected / onSelect contract applies, so swapping between the dropdown and the input is a one-line change — both speak Date. Use the input on dense settings pages or mobile-first forms where the native picker is faster, and the column dropdown where you want the styled, on-brand control. Add a Button beside either to submit the form.

1"use client"
2
3import * as React from "react"
4import { TimePicker } from "@/components/ui/time-picker"
5
6export default function InputTimePicker() {
7 const [time, setTime] = React.useState<Date | undefined>()
8
9 return (
10 <TimePicker.Input
11 selected={time}
12 onSelect={setTime}
13 />
14 )
15}
Get started

Install Drivn in one command

Copy the source into your project and own every line. Zero runtime dependencies, pure React + Tailwind.

npx drivn@latest create

Requires Node 18+. Works with npm, pnpm, and yarn.

Enjoying Drivn?
Star the repo on GitHub to follow new component releases.
Star →

Frequently asked questions

Run npx drivn add time-picker, then import { TimePicker } from "@/components/ui/time-picker". Hold the value in React.useState<Date | undefined>() and pass selected and onSelect. The component is controlled, so the selected time lives in your state as a Date object and the dropdown calls onSelect with a new Date each time the user picks a value.

Pass format="12h". The hours column changes to 01–12 and an AM/PM column appears. The component derives the period from the hour and uses an internal to24 helper to convert your AM/PM choice back to a 24-hour Date, so onSelect always returns a standard Date object regardless of whether you display 12-hour or 24-hour time.

Yes. Pass the showSeconds prop and a third scrolling column for seconds appears, with values from 00 to 59. Selecting a second updates the Date precisely. Without the prop the picker shows only hours and minutes, which is the right default for most scheduling and booking fields where second-level precision is not needed.

Pass a formatTime function. It receives the selected Date and returns the string shown in the trigger, letting you render a specific locale or a custom layout without touching the scrolling columns. The selection logic and the displayed label are decoupled, so you can format display one way and still store the underlying Date however you need.