Drivn vs shadcn/ui — Time Picker Compared
Drivn ships a first-party Time Picker; shadcn/ui has none. Compare the scrolling column picker, 12h/24h formats, and the native input fallback side by side.
This comparison starts with the honest fact that frames everything below: shadcn/ui has no first-party Time Picker. Its registry ships a Date Picker built from Calendar plus Popover, but for time you are expected to compose your own from an Input type="time", a few Select dropdowns, or a community block. Drivn ships a dedicated Time Picker — npx drivn add time-picker drops a complete, scrolling column picker into your project. So this is not a feature-by-feature toss-up; it is a "Drivn gives you the component, shadcn gives you the parts" story.
Drivn's Time Picker lives at packages/drivn/src/registry/components/time-picker.ts. It is built on Drivn's own Popover and Input — no Radix, no cva, no date library — with every class in one const styles object. It gives you scrolling hour/minute/second columns that auto-center the selected value, a format prop for 12h or 24h, an optional seconds column, and a TimePicker.Input fallback that wraps the native <input type="time">. This page walks each capability with verbatim source from the Drivn registry, and is honest about where the shadcn compose-it-yourself approach is the better fit.
Side-by-side comparison
| Feature | Drivn | shadcn/ui |
|---|---|---|
| First-party Time Picker | Yes — dedicated component | No — compose from Input/Select/Popover |
| Install command | npx drivn add time-picker | No registry item — build it yourself |
| Runtime UI dependencies | Own Popover + Input — zero npm UI packages | Radix Popover/Select if you compose one |
| Clock format | format prop — '12h' | '24h' | Build the toggle yourself |
| Seconds column | showSeconds prop | Build the column yourself |
| Scroll-to-selected | Yes — auto-centers on open | Build the scroll logic yourself |
| Native input fallback | TimePicker.Input — input type="time" | Use a plain Input type="time" |
| Styling pattern | Single const styles object | Inline cn() per composed element |
| Value type | Date object via selected / onSelect | Whatever your composition returns |
| License | MIT | MIT |
shadcn has no first-party Time Picker
The starting point of any honest comparison: there is no npx shadcn add time-picker. shadcn/ui ships a Date Picker recipe — Calendar inside a Popover — but time selection is left to you. The shadcn docs and community point you at three routes: a native <input type="time"> styled with the Input classes, a row of Select dropdowns for hours and minutes, or a third-party block you paste in. All three work, but all three are assembly, not installation.
Drivn closes that gap with a single command. npx drivn add time-picker installs a complete component under @/components/ui/time-picker that you then own and can edit. It is built on Drivn's Popover and Input, so it pulls in no new dependency you did not already have. The result is the usual Drivn trade flipped in Drivn's favour here: instead of choosing and wiring parts, you get a working picker on first install and edit from there.
1 import { TimePicker } from "@/components/ui/time-picker" 2 3 const [time, setTime] = React.useState<Date | undefined>() 4 5 <TimePicker 6 selected={time} 7 onSelect={setTime} 8 />
The scrolling column picker that auto-centers
The core of the Drivn Time Picker is its Column sub-component: a scrollable list of hour, minute, and (optionally) second values. The detail that makes it feel finished is the React.useEffect that scrolls the selected value into the centre of its column when the popover opens — it reads the [data-selected] element's offset and sets scrollTop so the active number sits mid-column rather than at the top. If you composed a time picker from shadcn Select dropdowns you would get a usable result, but not this scroll-to-selected behaviour without writing the same effect yourself.
Each cell is a button that pads its value with padStart(2, "0") and flips to the active styling — bg-foreground text-background — when it matches the current selection. This is verbatim from the Drivn registry; the whole column, scroll logic included, is a few lines you can read and re-style in place.
1 // packages/drivn/src/registry/components/time-picker.ts — verbatim 2 const ref = React.useRef<HTMLDivElement>(null) 3 React.useEffect(() => { 4 const col = ref.current 5 const el = col?.querySelector('[data-selected]') as HTMLElement | null 6 if (!col || !el) return 7 col.scrollTop = el.offsetTop - col.offsetTop - col.clientHeight / 2 + el.clientHeight / 2 8 }, [selected])
12h, 24h, and seconds from one prop each
Drivn's Time Picker handles the format permutations through props instead of separate components. The format prop takes '12h' or '24h' (default 24h); in 12h mode the root computes h12 = h % 12 || 12, derives the AM/PM period from h >= 12, and renders a period column with a to24 helper that maps the 12-hour value back to a 24-hour Date. The showSeconds prop adds a third scrolling column. The hours array itself is built inline from the format, so there is no branching component tree to maintain.
Reproducing this on a shadcn composition means wiring the 12h/24h toggle, the AM/PM state, and the seconds column by hand and keeping them in sync with a single Date. Drivn folds all of it into the one component you installed. The public API stays small — you flip a prop, not a sub-tree — which is the same defaults-driven approach you see across Drivn vs shadcn comparisons.
1 // packages/drivn/src/registry/components/time-picker.ts — verbatim 2 const is12 = format === '12h' 3 const h = selected?.getHours() 4 const period = h !== undefined ? (h >= 12 ? 'PM' : 'AM') : undefined 5 const h12 = h !== undefined ? (h % 12 || 12) : undefined 6 const hours = is12 ? Array.from({ length: 12 }, (_, i) => i + 1) : Array.from({ length: 24 }, (_, i) => i)
Where the shadcn approach wins: native input and simplicity
Being fair to the compose-it-yourself route: for many forms a plain <input type="time"> is genuinely enough, and that is the lightest possible answer — no popover, no columns, native mobile pickers for free. Drivn does not argue against this; it ships the same option as TimePicker.Input, a wrapper around the native time input that formats the Date to an HH:MM value string. If all you need is a quick time field on a settings page, the input fallback is the right call on either library.
The shadcn approach also wins when your design demands something the column picker is not — a stepper, a slot-machine wheel, fixed 15-minute intervals. Building from parts means you build exactly what the design asks for and nothing more. Drivn's answer is that you still own the installed source, so you can strip the columns down or swap the layout after install — but if your needs are far from a column picker, starting from shadcn primitives can be the shorter path.
1 import { TimePicker } from "@/components/ui/time-picker" 2 3 const [time, setTime] = React.useState<Date | undefined>() 4 5 <TimePicker.Input 6 selected={time} 7 onSelect={setTime} 8 />
Install Drivn in one command
Copy the source into your project and own every line. Zero runtime dependencies, pure React + Tailwind.
npx drivn@latest createRequires Node 18+. Works with npm, pnpm, and yarn.
Frequently asked questions
No. shadcn/ui ships a Date Picker recipe built from Calendar and Popover, but it has no first-party Time Picker in its registry. For time selection you compose your own from a native input type="time", a set of Select dropdowns, or a community block. Drivn, by contrast, ships a dedicated Time Picker you install with npx drivn add time-picker.
Drivn's Time Picker is built on its own Popover and Input components plus React and the cn() helper — no Radix, no cva, and no date library. The trigger uses a Clock icon from lucide-react, and the dropdown renders scrolling hour, minute, and optional second columns inside the Popover content. Everything is held in one const styles object you can edit after install.
Through the format prop, which takes "12h" or "24h" and defaults to "24h". In 12h mode the component computes h12 as h % 12 || 12, derives the AM/PM period from whether the hour is 12 or more, and shows an AM/PM column. A to24 helper converts the chosen 12-hour value back into a 24-hour Date so onSelect always receives a real Date object.
Yes. Pass the showSeconds prop and a third scrolling column appears for seconds, alongside the hours and minutes. The values column is built from Array.from({ length: 60 }), so it covers 0 through 59. Without the prop the picker shows only hours and minutes, which is the right default for most scheduling and form use cases.
Yes — TimePicker.Input wraps the native input type="time" inside Drivn's Input component. It formats the selected Date into an HH:MM string and parses changes back into a Date on onSelect. Use it when you want the lightweight native picker, including the built-in mobile time UI, instead of the scrolling column dropdown.
Because you get a working, scrolling column picker on first install instead of wiring Select dropdowns, AM/PM state, and scroll-to-selected logic yourself. Drivn still hands you the full source to edit, so you own it exactly as you would a shadcn composition. If your design needs something far from a column picker, composing from shadcn primitives can be shorter — but for a standard time field, Drivn is the faster route.

