# Wheel picker

> iOS-style scroll wheel with 3D rows, snapping and keyboard support.

Component · Pro · https://lodeui.com/components/wheel-picker

## When to use

- Picking times, dates and quantities on touch screens.
- Short ordered lists where scrolling feels natural.

## When not to use

- Long lists people search: use a combobox.
- Desktop forms where typing is faster.

## Installation

```bash
npx shadcn@latest add @lode/wheel-picker
```

Pro: needs a Lode API key and the `@lode` registry in components.json. See https://lodeui.com/docs/cli.

## Usage

```tsx title="example.tsx"
import * as React from "react";
import { WheelPicker } from "@/components/ui/wheel-picker";

const hours = Array.from({ length: 12 }, (_, i) => ({ value: String(i + 1), label: String(i + 1) }));

export function HourPicker() {
  const [hour, setHour] = React.useState("9");
  return <WheelPicker aria-label="Hour" options={hours} value={hour} onValueChange={setHour} />;
}
```

## API reference

### WheelPicker

A snapping scroll list drawn as a 3D wheel; the centered row is the value.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| options | `readonly { value: T; label: string }[]` | – | Rows in order. |
| value / defaultValue / onValueChange | `T` | – | Controlled or uncontrolled; fires after scrolling settles. |
| itemHeight / visibleCount | `number` | `36 / 5` | Row height and rows shown (odd). |
| aria-label | `string` | – | Required: names the wheel. |

## Keyboard interactions

| Keys | Action |
| --- | --- |
| ↑ / ↓ | Previous or next option |
| Page Up / Page Down | Five at a time |
| Home / End | First or last |

## Accessibility

- A listbox using aria-activedescendant; the centered option is aria-selected.
- Each wheel needs its own label (Hour, Minute…).

## Motion

- Rows tilt and fade with distance from the center; scroll snapping settles each flick; keys scroll smoothly.

## Responsive behavior

- Native scrolling, so flicks feel right on touch; combine several wheels in a flex row.

## Performance

- Transforms are recalculated from scroll position; fine for lists up to a few hundred rows.

## Notes for AI

- onValueChange fires after scrolling stops (110ms), not on every row passed.

## Related

- [Select](https://lodeui.com/components/select) — A pill trigger with a springy menu, typeahead, and full keyboard support.
- [Number field](https://lodeui.com/components/number-field) — A stepper you can press, hold, scrub, or type into. Push past a limit and it pushes back.
- [Date range picker](https://lodeui.com/components/date-range-picker) — Pick a start and an end on a calendar that previews the range as you move.
