WebberUI

Wheel Time Picker

An iOS-style 3D wheel for picking a time: momentum scrolling, snapping, and a perspective arc.

This is a WebberUI Pro component

Free during the launch campaign: sign up or sign in, then hit “Copy install command” in the preview above and it installs straight away — no payment, no credit card. The command below returns 401 while you are signed out.

How to install Pro components →See the plans →

An iOS-style two-column hour/minute 3D wheel: the numbers are laid out along an arc with rotateX (the further away, the more tilted and faded), it supports momentum gliding from both dragging and the mouse wheel, and on release a spring snaps it to the nearest tick. The selected row has a highlight frame, and once focused it can also be nudged with the up/down arrow keys.

Loading preview…
npx shadcn@latest add "https://webberui.com/r/wheel-time-picker.json?t=<install token>"

Playground

Tune the props live — the code snippet updates as you go, so you can dial in the look you want before copying it.

5
40
<WheelTimePicker />

Installation

npx shadcn@latest add "https://webberui.com/r/wheel-time-picker.json?t=<install token>"

Or, once registries are configured in components.json, install it as @webberui/wheel-time-picker.

Usage

import { WheelTimePicker } from "@/components/ui/wheel-time-picker";

<WheelTimePicker
  defaultValue="09:30"
  minuteStep={5}
  onChange={(time) => console.log(time)}
/>

Props

PropTypeDefaultDescription
valuestringControlled time value ("HH:mm"); the wheel turns smoothly to the matching position when it changes externally
defaultValuestring"09:30"Initial value in uncontrolled mode ("HH:mm")
onChange(value: string) => voidReturns the new time string once the wheel snaps into place ("HH:mm")
minuteStepnumber5Interval between minute ticks (1–30); the default produces 00, 05…55
itemHeightnumber40Height of a single row (px), which also determines the radius of the 3D arc
labels{ hour: string; minute: string }{ hour: "時", minute: "分" }Accessible labels for the hour and minute columns
classNamestringForwarded to the outer container

Accessibility

  • Each column is role="spinbutton" with aria-valuemin, aria-valuemax, and aria-valuetext, and once focused it can be nudged tick by tick with the up/down arrow keys
  • The individual numbers on the arc are hidden from assistive technology (aria-hidden) to avoid duplicate reading; the actual value is announced through aria-valuetext
  • When the user has "reduce motion" enabled at the system level, the momentum and spring animations are disabled and it snaps directly into position
  • Mouse dragging, touch, and the scroll wheel are all supported as pointer input, and the default row height of 40px gives a large enough touch target

On this page