Inputs

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

The install command below needs a licence to run; without one it returns 401.

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.

Bring this into your project

Run this command in your project folder. The CLI adds the source and dependencies; then follow the usage example below.

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

New project or installation trouble? Start here →

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
Active edited usageDefault props
<WheelTimePicker/>

The complete example includes the preview layout and data. Install the component first, then paste this file into your project.

Installation

npx webberui@latest add "https://webberui.com/r/wheel-time-picker.en.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
valuestring—Controlled 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) => void—Returns 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: "Time", minute: "Points" }Accessible labels for the hour and minute columns
classNamestring—Forwarded 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