Zum Inhalt springen
    WingoUI
    KomponentenVorlagenDokuPreiseKI-AgentenBlogChangelog
    1. Startseite
    2. Blog
    3. Mobile UI mit React
    4. React Wheel Picker: iOS-Räder für Uhrzeit und Datum
    Read in English
    1. Blog
    2. Mobile UI mit React
    3. React Wheel Picker: iOS-Räder für Uhrzeit und Datum
    Mobile UI mit React
    Mobile UI mit React

    React Wheel Picker: iOS-Räder für Uhrzeit und Datum

    SR
    Serban Rusu · Gründer von Wingo UI
    9. Okt. 2026 · 8 Min. Lesezeit

    Auf dieser Seite

    0%
    1. Wann ist ein Wheel Picker das richtige Control?
    2. Warum ein Rad auf einem nativen Snap-Scroller bauen?
    3. Wie drehen Maus- und Tastaturnutzer das Rad?
    4. Welche Props braucht das Picker Wheel?
    5. Wie baust du ein React Time Picker Wheel, in das man am Desktop trotzdem tippen kann?
    6. Sollte ein Datum ein Rad oder ein Kalender sein?
    7. Was geht bei einem Wheel Picker auf dem Handy schief?
    8. Wo fängst du an?
    9. Häufige Fragen
      1. Gibt es einen Wheel Picker im iOS-Stil für React-Web-Apps?
      2. Sollte ich input type=time statt eines Wheel Pickers nehmen?
      3. Wie lasse ich einen Wheel Picker in React endlos drehen?
      4. Vibriert ein Web Wheel Picker auf dem iPhone?
      5. Ist das Picker Wheel von Wingo UI kostenlos?

    Kurz gesagt

    Ein React Wheel Picker, der sich nativ anfühlt, überlässt das Scrollen dem Browser: Eine Scroll-Snap-Liste bringt den Schwung und den Gummiband-Effekt des Handys selbst mit, jede Zeile wird in einem Animation Frame aus scrollTop auf einem 3D-Zylinder gedreht, und der Wert wird genau einmal übernommen, wenn das Rad stillsteht. Nimm Räder für Uhrzeiten, Dauern und Geburtsdaten auf dem Handy, behalte am Desktop ein Textfeld und gib Maus-Drag, Mausrad und Tastatur jeweils einen eigenen Weg. Picker Wheel und Time Picker von Wingo UI Pro liefern all das mit, unter 768px mit einem Bottom Sheet.

    Veröffentlicht am 9. Okt. 2026

    Du willst einen React Wheel Picker, weil niemand auf dem Handy 14:30 auf einer Tastatur tippen sollte, die das halbe Formular verdeckt. Einen Kalender 36 Jahre zurückzublättern, bis zum Geburtsdatum, ist noch schlimmer. Schwierig ist das Gefühl beim Drehen: Die React-Wheel-Pakete, die wir uns angesehen haben, ersetzen das Scrollen des Browsers durch ihre eigene Touch-Physik. Dieser Guide baut das Rad auf einem nativen Snap-Scroller, dessen Zeilen auf einem 3D-Zylinder gedreht werden. Danach geht es um Maus und Tastatur, um die Uhrzeit- und Datumsfelder, die darauf aufbauen, und um die Stolperfallen. Wie sich Wheel Picker zwischen Bibliotheken unterscheiden, steht in unserem Vergleich der besten React-Komponentenbibliothek fürs Handy.

    Wann ist ein Wheel Picker das richtige Control?

    Wenn die Liste mittellang bis lang und geordnet ist und man erraten kann, was verdeckt ist: Stunden, Minuten, Dauern, Mengen, ein Geburtsjahr. Apples Human Interface Guidelines zu Pickern (opens in a new tab) empfehlen einen Picker für mittellange bis lange Listen, einen Pull-down-Button für eine recht kurze Auswahl und eine Liste oder Tabelle für sehr große Mengen. Außerdem raten sie zu Minutenschritten, die 60 glatt teilen, etwa Viertelstunden.

    Im Web ergibt das vier Regeln:

    • Zwei bis fünf Optionen: ein Segmented Control, damit jede Option sichtbar ist.
    • 12 Stunden, 60 Minuten, 1 bis 99 Stück, die Jahre seit 1920: ein Rad.
    • Hunderte ungeordnete Namen (Länder, Produkte): ein durchsuchbares Select. Ein Rad springt nur zu einem getippten Anfang.
    • Ein Datum nah an heute (eine Lieferung, eine Buchung): ein Kalender, weil der Wochentag zählt.

    Warum ein Rad auf einem nativen Snap-Scroller bauen?

    Weil sich Wischen, Schwung und der Gummiband-Effekt an den Enden dann genau wie auf dem Rest des Handys anfühlen, und ein Trackpad oder Mausrad das Rad ohne zusätzlichen Code dreht. Eine Suche nach „ios picker web“ im Oktober 2026 mischte ein Mendix-Widget, React-Native-Pakete und Flutters CupertinoPicker unter die Web-Antworten. Die beiden React-DOM-Pakete, die wir gefunden haben, bringen jeweils ihre eigene Physik mit:

    Paket (Stand Oktober 2026)Lizenz, letztes ReleaseWie es sich bewegt
    @ncdai/react-wheel-picker (opens in a new tab) 1.2.3MIT, 23. August 2026eigene Touch-, Maus- und Wheel-Handler; Zeilen auf einem 3D-Zylinder mit CSS-Transforms
    react-mobile-picker (opens in a new tab) 1.2.0MIT, 3. August 2025eigener touchmove-Handler und translate3d; Mausrad standardmäßig aus

    Beide funktionieren. @ncdai/react-wheel-picker, das auch Pfeiltasten, Home / End und Type-ahead beherrscht, ist die bessere Wahl, wenn du ein kostenloses, ungestyltes Rad willst und das Feld selbst baust. Das Scrollgefühl stellst du dort über dragSensitivity und scrollSensitivity ein; ein nativer Scroller bremst so ab wie jede andere Liste auf diesem Handy.

    Das native Rezept hat drei Teile. Die Liste scrollt mit scroll-snap-type: y mandatory, jede Zeile rastet in der Mitte ein, und zwei Zeilen Padding lassen die erste und die letzte Zeile die Mitte erreichen. Ein requestAnimationFrame pro Scroll liest scrollTop und schreibt rotateX und Opacity direkt auf die Zeilen, nie über React-State. Und der Wert wird einmal übernommen, im Stillstand: bei scrollend, das laut MDN (opens in a new tab) ab Chrome 114, Firefox 109 und Safari 26.2 verfügbar ist, mit einem Idle-Timer von 120ms für ältere Safari-Versionen.

    tsx
    "use client";
    import { useEffect, useRef } from "react";
    const ROW = 44; // fünf Zeilen in einem 220px-Fenster
    export function MiniWheel({ options, onSettle }: { options: string[]; onSettle: (value: string) => void }) {
    const listRef = useRef<HTMLDivElement>(null);
    const settleRef = useRef(onSettle);
    useEffect(() => {
    settleRef.current = onSettle;
    });
    useEffect(() => {
    const list = listRef.current;
    if (!list) return;
    const rows = Array.from(list.firstElementChild?.children ?? []) as HTMLElement[];
    let frame = 0;
    let idle: ReturnType<typeof setTimeout> | undefined;
    let last = "";
    // Drehung und Ausblenden gehen direkt auf die Zeilen, nie über React-State
    const paint = () => {
    frame = 0;
    const pos = list.scrollTop / ROW;
    rows.forEach((row, i) => {
    const d = i - pos;
    row.style.transform = `perspective(400px) rotateX(${Math.max(-55, Math.min(55, -d * 20))}deg)`;
    row.style.opacity = String(Math.max(0.35, 1 - Math.min(Math.abs(d), 3) * 0.22));
    });
    };
    // ein Commit, wenn das Rad stillsteht, nie einer pro durchlaufener Zeile
    const settle = () => {
    clearTimeout(idle);
    const value = options[Math.round(list.scrollTop / ROW)];
    if (value !== undefined && value !== last) settleRef.current((last = value));
    };
    const onScroll = () => {
    if (!frame) frame = requestAnimationFrame(paint);
    clearTimeout(idle);
    idle = setTimeout(settle, 120); // Safari vor 26.2 hat kein scrollend
    };
    paint();
    list.addEventListener("scroll", onScroll, { passive: true });
    list.addEventListener("scrollend", settle);
    return () => {
    list.removeEventListener("scroll", onScroll);
    list.removeEventListener("scrollend", settle);
    cancelAnimationFrame(frame);
    clearTimeout(idle);
    };
    }, [options]);
    return (
    <div ref={listRef} className="h-[220px] snap-y snap-mandatory overflow-y-scroll overscroll-contain [scrollbar-width:none]">
    <div className="py-[88px]">
    {options.map((option) => (
    <div key={option} className="flex h-11 snap-center items-center justify-center text-xl tabular-nums">
    {option}
    </div>
    ))}
    </div>
    </div>
    );
    }

    Das ist der Kern des Picker Wheel von Wingo UI. Der Skizze fehlen ein Startwert, deaktivierte Zeilen, das Endlosdrehen, jede Eingabe außer dem Finger und Räder, die unsichtbar gemountet werden.

    Wie drehen Maus- und Tastaturnutzer das Rad?

    Mausrad und Trackpad scrollen es nativ; Ziehen und Tasten brauchen eigenen Code. Im Picker Wheel läuft nur die Maus über Pointer Events: Ab 8 Pixeln Bewegung schaltet sich das Einrasten ab, und scrollTop folgt dem Zeiger. Beim Loslassen setzt eine Inertia-Animation von motion die gemessene Geschwindigkeit fort, und ihr modifyTarget rundet den Landepunkt auf eine Zeile. Ein Klick auf eine sichtbare Zeile lässt sie in die Mitte gleiten.

    Jede Spalte ist ein Tab-Stopp mit role="listbox". ArrowUp und ArrowDown drehen das Rad um eine Zeile, PageUp und PageDown um fünf, Home und End springen an die Enden, und Tippen springt zur nächsten Option, die mit dem Text beginnt („19“, dann „199“ auf einem Jahresrad). ArrowLeft und ArrowRight wechseln die Spalte. aria-activedescendant zeigt auf die zentrierte Option, die aria-selected trägt. Der Fokusring liegt eng um die mittlere Zeile, wo das Ausblenden am Rand ihn nicht verdecken kann.

    Welche Props braucht das Picker Wheel?

    columns (oder options für ein einzelnes Rad), einen Wert und onValueChange. Alles andere hat einen Default:

    tsx
    "use client";
    import { useState } from "react";
    import { PickerWheel, pickerRange } from "@/components/ui/picker-wheel";
    const hours = pickerRange(0, 12);
    const minutes = pickerRange(0, 59, { pad: 2 });
    export function CallDuration() {
    const [duration, setDuration] = useState(["1", "25"]);
    return (
    <PickerWheel
    aria-label="Anrufdauer"
    value={duration}
    // einmal pro Stillstand, mit den Werten aller Spalten und der id der Spalte, die sich bewegt hat
    onValueChange={(value) => setDuration(value)}
    columns={[
    { id: "hours", label: "h", options: hours, align: "end" },
    { id: "minutes", label: "min", options: minutes, align: "start", loop: true },
    ]}
    />
    );
    }

    Die Props, die du kennen solltest:

    • onValueChange feuert einmal pro Stillstand, nie pro durchlaufener Zeile. Du kannst dort also gefahrlos speichern.
    • loop (auf dem Rad oder pro Spalte) lässt 59 wieder zu 00 springen: Die Spalte rendert zusätzliche Kopien und springt im Stillstand unbemerkt zur mittleren. Nur die mittlere Kopie hat role="option".
    • size setzt die Zeilenhöhe auf 36, 44 oder 52px; visibleRows (ungerade, Default 5) macht das Rad bei md 220px hoch; perspective kippt jede Zeile um 20, 10 oder 0 Grad (ios, subtle, flat).
    • Eine deaktivierte Option ist durchgestrichen, und ein Rad, das auf ihr landet, gleitet weiter zur nächsten aktiven Zeile: pickerRange(36, 46, { disabled: (n) => n === 38 }) für eine ausverkaufte Schuhgröße.
    • haptics löst einen Auswahl-Tick aus, wann immer Finger, Maus-Drag oder Mausrad eine neue Zeile in die Mitte bringen, nie bei Tasten. Das funktioniert in Chrome auf Android; warum ein Scroll auf dem iPhone nicht ticken kann, erklärt unser Guide zur Web Vibration API.

    PickerWheelField packt dieselben Räder in ein Formularfeld: unter 768px ein Bottom Sheet mit den Buttons „Done“ und „Cancel“, am Desktop ein Popover, das Änderungen sofort übernimmt.

    Wie baust du ein React Time Picker Wheel, in das man am Desktop trotzdem tippen kann?

    Nimm den Time Picker, der je nach Breite umschaltet. Unter 768px ist das Feld schreibgeschützt mit inputMode="none", damit keine Tastatur aufgeht, und ein Tap öffnet ein Bottom Sheet mit Stunden- und Minutenrad. Ab 768px ist es ein Textfeld, das „1430“, „2:30pm“ oder „2p“ versteht, mit ArrowUp und ArrowDown die Minuten weiterschaltet und per Klick ein Panel mit Spalten öffnet. Der Wert ist immer „HH:mm“ im 24-Stunden-Format:

    tsx
    "use client";
    import { useState } from "react";
    import { TimePicker } from "@/components/ui/time-picker";
    const lunchBreak = (time: string) => time >= "13:00" && time < "14:00";
    export function PickupTime() {
    const [time, setTime] = useState("11:30");
    return (
    <TimePicker
    label="Abholzeit"
    name="pickup"
    locale="en-US"
    min="09:00"
    max="18:00"
    minuteStep={15}
    disabledTimes={lunchBreak}
    value={time}
    onValueChange={setTime}
    />
    );
    }
    Tipp 2:30pm oder 1430 ein und drück Enter, oder klick ins Feld, um die Spalten zu öffnen; in Handybreite öffnet ein Tap die Räder in einem Bottom Sheet, und die Mittagsstunde bleibt in beiden Fällen gesperrt
    $ npx wingo-ui@latest add time-picker
    ProDoku: Time Picker

    Das Sheet bearbeitet einen Entwurf: „Done“ übernimmt ihn, und wer das Sheet wegzieht, behält die alte Uhrzeit. Zeiten außerhalb von min und max oder durch disabledTimes gesperrte Zeiten sind auch auf den Rädern deaktivierte Zeilen.

    Sollte ein Datum ein Rad oder ein Kalender sein?

    Ein Rad für ein Datum, das man auswendig kennt und das weit von heute entfernt liegt, etwa ein Geburtsdatum: drei Wischgesten, statt Jahr um Jahr zurückzublättern. Ein Kalender für Daten nah an heute, bei denen der Wochentag zählt. Deshalb öffnet der Date Picker einen Kalender, auf dem Handy in einem Bottom Sheet.

    Für das Geburtsdatum ist useDateWheel ein React Date Wheel Picker in einem einzigen Hook: Tages-, Monats- und Jahresspalte in der Reihenfolge der Locale (Monat, Tag, Jahr für en-US), Monatsnamen in dieser Sprache, Tage, die zum Monat passen (der 29. Februar nur in Schaltjahren), und Jahre zwischen min und max. Die Werte sind ISO-Daten wie „1990-05-17“.

    Wisch über Monat, Tag oder Jahr, zieh sie mit der Maus oder spring per Tab zum Jahr und tipp 1985: Datum und Alter unter dem Rad aktualisieren sich, sobald es stillsteht
    $ npx wingo-ui@latest add picker-wheel
    ProDoku: Picker Wheel

    Für das Rad auf dem Handy und ein Textfeld am Desktop renderst du beides und schaltest per CSS um, damit das Server-HTML zum ersten Paint passt (der Guide zu Mobile-first React-Komponenten erklärt, warum ein useIsMobile-Check kurz aufblitzen würde). Ein einziger ISO-String versorgt beide:

    tsx
    "use client";
    import { useState } from "react";
    import { DatePicker } from "@/components/ui/date-picker";
    import { PickerWheelField, useDateWheel } from "@/components/ui/picker-wheel";
    import { formatDate, fromISODate, toISODate } from "@/lib/date-utils";
    export function BirthdayField({ initial }: { initial: string }) {
    const [birthday, setBirthday] = useState(initial); // "1990-05-17"
    const [today] = useState(() => new Date());
    const wheel = useDateWheel({ value: birthday, onValueChange: setBirthday, locale: "en-US", min: "1920-01-01", max: toISODate(today) });
    return (
    <>
    {/* Handy: drei Räder in einem Bottom Sheet, Done übernimmt den Wert */}
    <div className="md:hidden">
    <PickerWheelField
    label="Geburtsdatum"
    {...wheel}
    formatValue={() => formatDate(fromISODate(birthday), "en-US", { dateStyle: "long" })}
    />
    </div>
    {/* ab 768px: 05171990 tippen oder den Kalender öffnen */}
    <div className="hidden md:block">
    <DatePicker
    label="Geburtsdatum"
    locale="en-US"
    max={today}
    clearable={false}
    value={fromISODate(birthday)}
    onValueChange={(date) => date && setBirthday(toISODate(date))}
    />
    </div>
    <input type="hidden" name="birthday" value={birthday} />
    </>
    );
    }

    Ein Haken: useDateWheel hält immer ein Datum (heute, wenn du keins übergibst), das Feld ist also nie leer. Das passt zum Bearbeiten eines Profils; ein Pflichtdatum, das leer startet, gehört in den Date Picker.

    Was geht bei einem Wheel Picker auf dem Handy schief?

    Die meisten Bugs kommen aus der Umgebung des Rads. Das Picker Wheel fängt sie ab; baust du dein eigenes, begegnen sie dir:

    • Das Sheet klaut den Drag. Ein Rad an seiner ersten Zeile gibt einen Drag nach unten an den Drawer weiter. Die Spalten tragen data-vaul-no-drag, und overscroll-behavior: contain verhindert, dass ein harter Wisch die Seite scrollt.
    • Ein Rad, das unsichtbar gemountet wird. In einem geschlossenen Sheet hat die Liste keine Höhe, also bewirkt das Setzen von scrollTop nichts. Ein ResizeObserver scrollt zum Wert, sobald die Liste eine Größe hat.
    • Commit pro Zeile. Wer bei jeder durchlaufenen Zeile speichert, flutet die API und löst mitten im Drehen die Validierung aus.
    • Reduzierte Bewegung. Mit prefers-reduced-motion bleiben die Zeilen flach, und programmatische Bewegungen springen, statt zu gleiten.
    • Feedback nur im Tick. Nutzer am Desktop und auf dem iPhone spüren nichts, also müssen die mittlere Zeile und der Feldtext den Wert tragen.

    Wo fängst du an?

    Öffne diese Seite auf deinem Handy und wisch durch die beiden Demos oben. Picker Wheel, Time Picker und Date Picker gehören zu Wingo UI Pro; mit einem Pro-Konto, angemeldet über npx wingo-ui@latest login, kopiert npx wingo-ui@latest add picker-wheel die Komponente und alles, was sie importiert, in dein Projekt. Eine React Wheel Picker Komponente ist nur ein Baustein eines handyfreundlichen Formulars; die anderen Muster findest du unter Mobile UI in React.

    Komponenten in diesem Artikel

    • Picker Wheel

      A React iOS-style picker wheel whose columns spin with momentum and snap on a 3D cylinder.

      Pro
    • Time Picker

      A React time picker to type a time or pick it from columns, with 12 / 24 hours by locale, minute steps, limits and wheels on phones.

      Pro
    • Date Picker

      A React date picker: type a date in your locale or pick it from a calendar, with presets, limits, optional time and a phone sheet.

      Pro

    Häufige Fragen

    Gibt es einen Wheel Picker im iOS-Stil für React-Web-Apps?

    Ja. Stand Oktober 2026 gibt es als Open Source @ncdai/react-wheel-picker (1.2.3, MIT) und react-mobile-picker (1.2.0, MIT), die beide ihre eigene Touch-Physik mitbringen. Das Picker Wheel von Wingo UI (Pro) scrollt nativ und ergänzt ein Formularfeld, das auf dem Handy ein Bottom Sheet öffnet, einen Datums-Hook und haptische Ticks.

    Sollte ich input type=time statt eines Wheel Pickers nehmen?

    Nimm das native Input-Element, wenn Aussehen und Verhalten reichen, denn es kostet nichts und ist von Haus aus barrierefrei. Den Picker, den es öffnet, kannst du nicht gestalten, er unterscheidet sich je nach Browser und OS-Version und kann keine gesperrten Zeiten wie eine Mittagspause zeigen. Genau dann lohnt sich ein eigenes Rad.

    Wie lasse ich einen Wheel Picker in React endlos drehen?

    Rendere die Optionen mehrmals und spring zurück zur mittleren Kopie, sobald das Rad stillsteht. Das sieht identisch aus. Im Picker Wheel von Wingo UI erledigt loop auf dem Rad oder auf einer Spalte genau das, mit mindestens 40 Zeilen auf jeder Seite der mittleren Kopie, damit auch ein harter Wisch nie das Ende erreicht.

    Vibriert ein Web Wheel Picker auf dem iPhone?

    Nein. Safari hat keine Vibration API, und die einzige Web-Haptik des iPhones, der Tick eines nativen Switches, kommt nur bei einem Tap, nie beim Scrollen. In Chrome auf Android tickt das Picker Wheel jedes Mal, wenn eine neue Zeile die Mitte erreicht.

    Ist das Picker Wheel von Wingo UI kostenlos?

    Nein. Picker Wheel, Time Picker und Date Picker sind Pro-Komponenten; Drawer und Field, auf denen sie aufbauen, sind kostenlos. Pro kostet $8 im Monat, $80 im Jahr oder einmalig $150.

    • Mobile UI
    • Wheel Picker
    • Time Picker
    • iOS
    • React

    Teilen

    SR

    Über den Autor

    Serban Rusu

    Gründer von Wingo UI

    Serban Rusu hat Wingo UI gegründet. Er baut die Komponenten, die CLI und den MCP-Server und schreibt über React-UIs für Smartphones und KI-Agents.

    Mehr von Serban
    Weiterlesen

    Ähnliche Artikel

    Alle Artikel
    Komponenten-Guides

    React Time Picker: Tippen, 12 oder 24 Stunden je nach Locale

    Bau einen React Time Picker, der Eingaben wie 1430 oder 2p versteht, 12 oder 24 Stunden nach Locale zeigt, belegte Zeiten sperrt und am Handy iOS-Räder öffnet.

    SRSerban Rusu·19. Okt. 2026·8 Min. Lesezeit
    Mobile UI mit React

    Web Vibration API: Haptik auf Android und iPhone

    Web Vibration API 2026: navigator.vibrate auf Android, der iPhone-Switch-Tick, den iOS 26.5 auf echte Taps begrenzt, und ein React-Helper, der still scheitert.

    SRSerban Rusu·9. Okt. 2026·11 Min. Lesezeit
    Vergleiche und Alternativen

    Mantine vs shadcn 2026: Welche React-UI-Bibliothek passt?

    Mantine vs shadcn im Oktober 2026: npm-Kit mit Formularen und Date Pickern oder Tailwind-Code, der dir gehört? Styling, Tabellen, Smartphone und Next.js.

    SRSerban Rusu·16. Okt. 2026·11 Min. Lesezeit
    Newsletter

    Neue Artikel per E-Mail

    Neue Guides, Tutorials und Vergleiche aus dem Wingo UI Blog, sobald sie erscheinen. Die meisten Artikel sind auf Englisch.

    Kein Spam. Du kannst dich jederzeit abmelden.

    WingoUI

    Animierte, konfigurierbare, mobile-first React-Komponenten und Blöcke. Kopier den Quellcode, pass ihn an und lass deinen Coding-Agenten damit bauen.

    Produkt

    • Komponenten
    • Vorlagen
    • Preise
    • KI-Agenten
    • Theme-Generator

    Ressourcen

    • Doku
    • Blog
    • Changelog
    • Changelog-RSS
    • llms.txt

    Rechtliches

    • AGB
    • Datenschutz
    • Rückerstattung
    • Lizenz
    • Impressum

    Komponenten-Kategorien

    • Buttons & Actions
    • Inputs
    • Forms
    • Navigation
    • Overlays
    • Feedback
    • Data Display
    • Tables & Lists
    • Charts & Stats
    • Layout
    • Media
    • AI Kit
    • Text & Effects
    • Mobile
    • Commerce
    • Marketing Sections
    • Blocks
    • Hooks & Utilities

    © 2026 Wingo UI

    Wingo UI