suiss/uim · React Native Component

Wheel Picker

A scrolling wheel for picking one value per column, with items that curve away from the center.

Wheel Picker is an open-source mobile component from suiss/uim for React Native and Expo, with SwiftUI and Jetpack Compose versions built from the same design tokens. The @esuiss/uim CLI copies its source into your project, so you own the code.

iOS
Wheel Picker on iOS in light mode

WheelPicker lays out one or more WheelPickerColumn components side by side behind a shared highlight band. Each column is a snapping ScrollView; items above and below the center are scaled, moved and faded with React Native Animated interpolations to look like a rotating wheel.

Use it for times, dates and other values picked from a short, ordered list, often in a sheet or popover.

Installation

$ pnpm dlx @esuiss/uim@latest add wheel-picker

The CLI also adds what it builds on: Text.

Manual

  1. Install the dependencies:
npx expo install cn
  1. Add the pieces it builds on: Text, and the primitives components/primitives/use-render.tsx, components/primitives/wheel-picker.tsx.

  2. Copy the source into components/ui/wheel-picker.tsx:

uniwind/components/ui/wheel-picker.tsx
import { cn } from "cn"
import type * as React from "react"
import { resolveClassName } from "@/components/primitives/use-render"
import * as WheelPickerPrimitive from "@/components/primitives/wheel-picker"
import { Text, TextClassContext } from "@/components/ui/text"

function WheelPicker({
  className,
  children,
  ...props
}: React.ComponentProps<typeof WheelPickerPrimitive.Root>) {
  return (
    <WheelPickerPrimitive.Root
      className={(state) =>
        cn(
          "relative flex-row items-stretch justify-center",
  1. Update the import paths to match your project.

Usage

import { WheelPicker, WheelPickerColumn, WheelPickerItem } from "@/components/ui/wheel-picker"
<View className="w-80 rounded-2xl border border-label/5 bg-surface-raised p-4 shadow-md dark:border-label/10">
  <WheelPicker>
    <WheelPickerColumn accessibilityLabel="Fruit" defaultValue="Lemon">
      {fruits.map((fruit) => (
        <WheelPickerItem key={fruit} value={fruit}>
          {fruit}
        </WheelPickerItem>
      ))}
    </WheelPickerColumn>
  </WheelPicker>
</View>

Give each column a defaultValue, or value with onValueChange, and fill it with WheelPickerItem components that each have a unique value. Plain string or number children are wrapped in single-line Text.

The value is set when scrolling settles or when an item is pressed. Disabled items are skipped: if the wheel stops on one, it moves to the nearest enabled item.

Combine several columns for compound values such as day, hour and minute, and use className on columns and items to control width and alignment. Set itemHeight on WheelPicker to change the row height.

Examples

Disabled items

A time list where booked slots are disabled and skipped.

iOS
Wheel Picker (disabled items) on iOS in light mode

Date time

Controlled day, hour and minute columns combined into one value.

iOS
Wheel Picker (date time) on iOS in light mode

API Reference

WheelPicker

Root row of columns with the selection highlight.

ExtendsReact.ComponentProps<typeof WheelPickerPrimitive.Root>

WheelPickerColumn

Snapping scroll column that holds one value.

ExtendsReact.ComponentProps<typeof WheelPickerPrimitive.Column>

WheelPickerItem

Single row in a column.

ExtendsReact.ComponentProps<typeof WheelPickerPrimitive.Item>

Accessibility

  • Each column has the adjustable role and announces the selected item's label as its value.
  • VoiceOver and TalkBack users swipe up or down to move to the next or previous enabled item.
  • Give each column an accessibilityLabel, such as Hour or Minute.
  • The highlight band is hidden from screen readers.

Notes

  • A selection haptic plays when the value changes, if a haptics adapter is provided through the haptics context.
  • The highlight uses bg-control; items use text-xl text-label with tabular numbers and text-label-tertiary when disabled.
  • Light and dark colors follow the system appearance.