React Date Range Picker mit Presets und Bottom Sheet

Ein React Date Range Picker steht über fast jedem Report, jeder Analytics-Seite und jedem Buchungsformular, und dabei schleichen sich leicht kleine Fehler ein. Typische Probleme: Der Report lädt nach dem ersten Klick neu, weil sich der Zeitraum geändert hat. Es gibt keine Presets, also klickt jeder durch die Monate bis zum letzten Quartal. Das Popover ist auf dem Handy ein gequetschtes Raster aus zwei Monaten, und für jemanden in Berlin beginnt die Woche am Sonntag. Dieser Guide zeigt, was ein Picker für Reports braucht, welche Props zählen und wie der Date Range Picker von Wingo UI Desktop, Handys und Locales behandelt.
Was sollte ein React Date Range Picker für Reports können?
Fünf Dinge, grob danach sortiert, wie oft ihr Fehlen auffällt:
- Presets zuerst. Die meisten Zeiträume in Reports sind relativ: die letzten 7 Tage, dieser Monat, das letzte Quartal. Eine Liste neben dem Kalender macht aus einem Dutzend Klicks einen.
- Zwei Monate am Desktop. Zeiträume gehen oft über eine Monatsgrenze, und zwei Monate nebeneinander zeigen beide Enden, ohne zu blättern.
- Ein Entwurf, dann Apply. Der erste Klick setzt den Start, der Bereich folgt dem Zeiger als Vorschau, und der zweite Klick setzt das Ende. Nichts landet in deinem State, bevor jemand Apply drückt. Cancel, Escape oder ein Klick daneben verwerfen den Entwurf.
- Ein Layout fürs Handy. Ein Monat in voller Breite in einem Bottom Sheet, mit Apply in Reichweite des Daumens.
- Wochen und Labels nach Locale. Der erste Wochentag, die Monatsnamen und der Text des Zeitraums folgen der Locale deiner Nutzer.
So schneiden die üblichen Optionen ab, Stand Oktober 2026:
Das Beispiel von shadcn/ui ist kostenlos und MIT-lizenziert, und du setzt es selbst aus Popover und Calendar zusammen. Auf der Calendar-Seite (opens in a new tab) gibt es zwar ein Presets-Beispiel, aber es wählt einzelne Tage (Today, Tomorrow, In a week). Presets für Zeiträume schreibst du also weiterhin selbst. Laut README wird react-date-range nicht mehr gepflegt, das GitHub-Repository ist archiviert, und das letzte npm-Release stammt von April 2024. Die Lizenzseite von MUI ordnet den Date Range Picker dem kostenpflichtigen Pro-Plan zu. Der Picker von Wingo UI ist eine Pro-Komponente, deren Quellcode in dein Projekt kopiert wird.
Wenn du schon MUI nutzt, ist dessen Range Picker eine solide Wahl. Wenn du shadcn/ui nutzt und nur am Desktop einen einfachen Zeitraum brauchst, ist das Beispiel für den shadcn date range picker kostenlos und klein. Der Rest dieses Guides dreht sich um den Report-Fall.
Wie sieht der Date Range Picker von Wingo UI aus?
Wer nach „react date range picker tailwind“ sucht, sollte Pakete mit eigenem Stylesheet meiden: react-date-range verlangt, dass du ein Haupt-Stylesheet und ein Theme-Stylesheet importierst und sie dann überschreibst. Der Picker von Wingo UI ist mit Klassen aus Tailwind CSS v4 gestylt, auf denselben semantischen Tokens wie der Rest deiner App, und folgt deshalb deinem Theme im Light und Dark Mode. Die Demo unten ist ein Umsatzreport. Öffne das Feld Period, probier ein Preset, wähl dann zwei Tage von Hand und schau, wie die Zusammenfassung unter dem Kalender die Tage zählt, bevor du Apply drückst.
$ npx wingo-ui@latest add date-range-pickerFür einen Report reichen ein Wert, ein Setter und max auf heute, damit niemand einen Zeitraum in der Zukunft wählt:
DateRange ist { from: Date | null; to: Date | null }. onValueChange feuert bei Apply, beim Leeren oder, mit confirm={false}, sobald beide Enden gewählt sind. Es feuert nie mit einem halb gewählten Entwurf, du kannst deine Abfrage also direkt darin starten.
Wie baust du einen React Date Range Picker mit Presets?
presets ist standardmäßig true und zeigt Last 7 days, Last 30 days, This month, Last month, This quarter, Last quarter und This year. Für einen React Date Range Picker mit Presets nach deinen eigenen Regeln übergibst du eine Liste. Eingebaute Schlüssel und eigene Zeiträume lassen sich frei mischen, und ein eigener value darf eine Funktion sein. Dann wird er beim Öffnen des Panels berechnet statt beim Laden der Seite:
Die übrigen eingebauten Schlüssel sind today, yesterday, last90Days, thisWeek, lastWeek, thisMonth, thisQuarter und lastYear. Presets, die über min oder max hinausgehen, werden passend gekürzt. Presets, die ganz außerhalb liegen oder länger als maxDays sind, werden deaktiviert statt ausgeblendet, damit die Liste nie springt.
Welche Props zählen für Buchungen und lange Zeiträume?
Reports und Buchungen brauchen unterschiedliche Regeln. Dieselbe Komponente deckt beide ab:
minDaysundmaxDayszählen beide Enden mit. Ein Mindestaufenthalt von zwei Nächten istminDays={3}. Enden, die die Regel verletzen würden, sind beim Wählen des Endes nicht verfügbar, und Presets, die länger alsmaxDayssind, werden deaktiviert.disablednimmttrue, um das ganze Feld zu sperren, oder einen Matcher für Tage: einDate, eine Liste,{ from, to },{ before },{ after },{ dayOfWeek: [0, 6] }oder eine Funktion. Gebuchte Nächte sind eine Liste von Daten.excludeDisabled(Standardtrue) verhindert, dass ein Zeitraum über einen gesperrten Tag reicht. Genau das braucht eine Buchung.labels.nightsstellt die Zusammenfassung von Tagen auf Nächte um. Aus einem Aufenthalt über 4 Tage werden so 3 Nächte.numberOfMonthsist standardmäßig 2 und kann 1 oder 3 sein. Auf dem Handy ist es immer einer.
Wie funktioniert der Date Range Picker auf dem Handy?
Beim Thema Date Range Picker mobile scheitern Layouts meist an derselben Stelle: Ein Popover mit zwei Monaten läuft auf einem 390px breiten Screen über oder schrumpft die Tageszellen unter eine bequeme Tippgröße, und es öffnet sich weit weg vom Daumen. Unter 768px öffnet das Feld von Wingo UI stattdessen ein Bottom Sheet. Das Sheet zeigt die Presets als Reihe von Chips, zwei Zellen für Start und Ende (das Ende, das du gerade wählst, ist umrandet), einen Monat, den du per Wischen wechselst, und Apply und Cancel fixiert über dem Home-Indikator. Wer das Sheet nach unten zieht, bricht ab, genau wie Escape am Desktop. In der Standardgröße md ist das Feld auf Touchscreens 44px hoch.
responsive (Standard true) steuert den Wechsel, und sheetTitle benennt das Sheet. Brauchst du überall ein Popover, etwa in einem Admin-Tool nur für den Desktop, setz responsive={false}. Denselben Wechsel von Popover zu Sheet für jeden Dialog zeigt unser Tutorial zum responsiven shadcn-Dialog, und einen kompletten Report-Screen rund um den Picker findest du im Next.js-Admin-Dashboard-Tutorial.
Wie funktionieren Wochen und Labels nach Locale?
locale bestimmt Monats- und Wochentagsnamen, Ziffern, den Text im Feld und den ersten Wochentag. Lässt du weekStartsOn auf dem Standard -1, folgt die Woche der Locale: Sonntag für en-US, Montag für en-GB oder ro-RO. Die Komponente liest die Wocheninfo aus Intl.Locale, wo der Browser sie anbietet, und fällt sonst auf eine eingebaute Tabelle zurück. Mit weekStartsOn={1} erzwingst du Montag, egal bei welcher Locale.
Der Text des Zeitraums nutzt formatRange von Intl.DateTimeFormat. Der 1. bis 30. Oktober erscheint in en-US also als „Oct 1 – 30, 2026“, ohne dass du einen Formatter schreibst. Die Teile änderst du mit displayFormat, zum Beispiel { day: "numeric", month: "short" } für ein Buchungs-Widget, das nie über einen Jahreswechsel geht.
Jeder Text im Panel ist ebenfalls ein Prop: labels.apply, labels.cancel, labels.clear, labels.start, labels.end und labels.duration für die Zusammenfassung.
Der zugrunde liegende Calendar funktioniert auch allein mit mode="range", wenn du das Raster direkt auf der Seite statt in einem Feld willst. In dieser Demo ist die Locale en-GB, die Woche beginnt also am Montag.
$ npx wingo-ui@latest add calendarLässt sich der Date Range Picker per Tastatur bedienen?
Ja. Enter, Leertaste oder ArrowDown auf dem Feld öffnen das Panel und setzen den Fokus in den Kalender. Die Pfeiltasten bewegen dich um einen Tag oder eine Woche, Home und End springen an Anfang und Ende der Woche, PageUp und PageDown wechseln den Monat (mit Shift das Jahr), und Enter wählt erst den Start und dann das Ende. Mit Tab erreichst du Cancel und Apply, mit Shift+Tab die Presets, zwischen denen du mit den Pfeiltasten wechselst. Ctrl+Enter, auf dem Mac Cmd+Enter, übernimmt von überall im Panel, und Escape bricht ab und gibt den Fokus ans Feld zurück.
Mit label, description und error bekommt das Feld denselben Aufbau wie jedes andere Eingabefeld von Wingo UI: ein verknüpftes Label, aria-describedby für den Hilfetext und aria-invalid mit einer animierten Fehlermeldung.
Welche Stolpersteine tauchen in Produktion auf?
- Zeitzonen in Formularen.
date.toISOString()rechnet in UTC um. Mitternacht am 13. Oktober in Berlin wird so zu2026-10-12T22:00:00.000Z, und dein Server liest den falschen Tag. Sende lokale Daten. Mitname="period"rendert der Picker die versteckten Felderperiod.fromundperiod.toals lokale ISO-Daten wie2026-10-13. - Inklusive Enden. „Last 7 days“ endet heute und schließt heute ein. Fragst du eine Datenbank mit einer Timestamp-Spalte ab, vergleich mit dem Beginn des Tages nach
to, sonst verlierst du alles, was am letzten Tag nach Mitternacht passiert ist. - Presets, die beim Import berechnet werden. Ein
new Date()auf Modulebene veraltet in einem Tab, der über Nacht offen bleibt. Nutze für eigene Presets einen Funktionswert. - Eine Abfrage bei jedem Klick. Ohne Apply-Schritt startet schon die Wahl des Starts deinen Report mit einem offenen Zeitraum. Lass
confirmbei allem an, was langsamer ist als ein Filter im Client.
Hier die Formularversion, bei der eine Server Action die versteckten Felder liest. Sie prüft das Format beider Daten, denn eine Anfrage kann dein Formular umgehen, und behält sie als Kalenderdaten, damit die Zeitzone des Servers sie nie verschiebt:
Wann ist ein einfacher Date Picker die bessere Wahl?
Wenn es um einen einzigen Tag geht: ein Fälligkeitsdatum, einen Geburtstag, ein Lieferfenster. Mit dem Date Picker tippt man ein Datum im Format der eigenen Locale oder wählt es im Kalender, mit Presets, Grenzen und optionaler Uhrzeit, und auch er öffnet auf dem Handy ein Sheet. Den Range Picker nimmst du nur, wenn beide Enden zählen. Geht es um eine Uhrzeit, hilft der Guide zum React Time Picker, und für Abrechnungszeiträume oder Berichte nach Monat der Guide zum React Month Picker.
Mehr Deep Dives zu einzelnen Komponenten findest du in den Komponenten-Guides. Wie die Datumsfelder zum Rest eines Formulars passen, zeigt unser Guide zu React-Formularkomponenten.
Wie installierst du ihn?
Führ npx wingo-ui@latest add date-range-picker aus. Der Befehl kopiert den Picker mit dem Calendar, dem Drawer für das Sheet auf dem Handy, dem Field und den Datums-Helfern, die er importiert, und installiert die nötigen npm-Pakete wie date-fns, motion und @radix-ui/react-popover. Der Date Range Picker gehört zu Wingo UI Pro, melde dich also zuerst mit npx wingo-ui@latest login an.
Häufige Fragen
Wie füge ich einem React Date Range Picker Presets hinzu?
Zeig neben dem Kalender eine Liste von Zeiträumen und füll beide Enden, sobald jemand einen Eintrag wählt. Im Date Range Picker von Wingo UI ist presets standardmäßig true (Last 7 days, Last 30 days, This month, Last month, This quarter, Last quarter, This year), oder du übergibst eine Liste, die eingebaute Schlüssel wie "yearToDate" mit eigenen { label, value }-Einträgen mischt.
Hat shadcn/ui einen Date Range Picker?
Auf der Date-Picker-Seite gibt es ein Range-Picker-Beispiel, das aus Popover und Calendar zusammengesetzt ist; die Seite sagt selbst, dass es keine DatePicker-Root-Komponente gibt. Stand Oktober 2026 zeigt die Seite keine Presets, keinen Schritt mit Apply und Cancel und keinen Drawer fürs Handy, das baust du also selbst.
Soll ein Date Range Picker sofort übernehmen oder einen Apply-Button haben?
Nimm Apply, wenn jede Änderung eine teure Abfrage auslöst, etwa einen Report oder einen Export. Dann lassen sich beide Enden und ein Preset wählen, ohne drei Ladevorgänge auszulösen. Bei einem günstigen clientseitigen Filter übernimmst du sofort; in Wingo UI ist das confirm={false}.
Wie sollte ein Date Range Picker auf dem Handy funktionieren?
Öffne ein Bottom Sheet statt eines Popovers, zeig einen Monat in voller Breite mit großen Tageszellen und pack die Presets in eine scrollbare Reihe von Chips. Zeig Zellen für Start und Ende, damit klar ist, welches Ende gerade gewählt wird, und fixier Apply und Cancel über dem Home-Indikator.
Wie sende ich den Zeitraum in einem Formular ohne Zeitzonenfehler?
Sende lokale Kalenderdaten wie 2026-10-13, nie toISOString(), denn das rechnet in UTC um und kann den Tag verschieben. Mit name="period" rendert der Picker von Wingo UI die versteckten Felder period.from und period.to mit lokalen ISO-Daten.
- Date Picker
- Formulare
- React
- Mobile UI


