Zum Inhalt springen
    WingoUI
    KomponentenVorlagenDokuPreiseKI-AgentenBlogChangelog
    1. Startseite
    2. Blog
    3. Komponenten-Guides
    4. React Date Range Picker mit Presets und Bottom Sheet
    Read in English
    1. Blog
    2. Komponenten-Guides
    3. React Date Range Picker mit Presets und Bottom Sheet
    Komponenten-Guides
    Komponenten-Guides

    React Date Range Picker mit Presets und Bottom Sheet

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

    Auf dieser Seite

    0%
    1. Was sollte ein React Date Range Picker für Reports können?
    2. Wie sieht der Date Range Picker von Wingo UI aus?
    3. Wie baust du einen React Date Range Picker mit Presets?
    4. Welche Props zählen für Buchungen und lange Zeiträume?
    5. Wie funktioniert der Date Range Picker auf dem Handy?
    6. Wie funktionieren Wochen und Labels nach Locale?
    7. Lässt sich der Date Range Picker per Tastatur bedienen?
    8. Welche Stolpersteine tauchen in Produktion auf?
    9. Wann ist ein einfacher Date Picker die bessere Wahl?
    10. Wie installierst du ihn?
    11. Häufige Fragen
      1. Wie füge ich einem React Date Range Picker Presets hinzu?
      2. Hat shadcn/ui einen Date Range Picker?
      3. Soll ein Date Range Picker sofort übernehmen oder einen Apply-Button haben?
      4. Wie sollte ein Date Range Picker auf dem Handy funktionieren?
      5. Wie sende ich den Zeitraum in einem Formular ohne Zeitzonenfehler?

    Kurz gesagt

    Ein guter React Date Range Picker für Reports zeigt am Desktop Presets wie „Last 7 days“ neben zwei Monaten, hebt den Bereich schon beim Wählen des Endes als Vorschau hervor und ändert den Wert erst bei Apply, damit ein halb gewählter Zeitraum nie deine Abfrage erreicht. Auf dem Handy öffnet er ein Bottom Sheet mit einem Monat, Preset-Chips und Apply über dem Home-Indikator, und überall richtet sich der erste Wochentag nach der Locale. Der Date Range Picker von Wingo UI erledigt all das in einer Komponente, mit minDays, maxDays und gesperrten Tagen für Buchungen.

    Veröffentlicht am 13. Okt. 2026

    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:

    1. 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.
    2. Zwei Monate am Desktop. Zeiträume gehen oft über eine Monatsgrenze, und zwei Monate nebeneinander zeigen beide Enden, ohne zu blättern.
    3. 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.
    4. Ein Layout fürs Handy. Ein Monat in voller Breite in einem Bottom Sheet, mit Apply in Reichweite des Daumens.
    5. 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:

    OptionPresetsApply / CancelLayout fürs Handy
    shadcn/ui Range-Picker-Beispiel (opens in a new tab)nicht gezeigtnicht gezeigtnicht gezeigt
    react-date-range (opens in a new tab) 2.0.1ja (staticRanges)nicht erwähntauf der TODO-Liste
    MUI X (opens in a new tab) Date Range Pickerjajaja
    Date Range Picker von Wingo UIjajaBottom Sheet

    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.

    Öffne das Feld Period, wähl Last 30 days oder zwei Tage von Hand und drück Apply: Die Summen ändern sich erst bei Apply. Drückst du stattdessen Escape, ändert sich nichts.
    $ npx wingo-ui@latest add date-range-picker
    ProDoku: Date Range Picker

    Für einen Report reichen ein Wert, ein Setter und max auf heute, damit niemand einen Zeitraum in der Zukunft wählt:

    tsx
    "use client";
    import { useState } from "react";
    import { DateRangePicker, type DateRange } from "@/components/ui/date-range-picker";
    export function SalesReportFilter() {
    const [range, setRange] = useState<DateRange>({ from: null, to: null });
    return (
    <DateRangePicker
    label="Zeitraum"
    locale="en-US"
    placeholder="Zeitraum wählen"
    max={new Date()}
    value={range}
    onValueChange={setRange}
    />
    );
    }

    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:

    tsx
    import { addDays, nextSaturday, startOfDay } from "date-fns";
    import { DateRangePicker } from "@/components/ui/date-range-picker";
    export function CampaignPeriod() {
    return (
    <DateRangePicker
    label="Kampagne"
    locale="en-US"
    presets={[
    "last7Days",
    "lastMonth",
    "yearToDate",
    {
    label: "Nächste 30 Tage",
    value: () => {
    const today = startOfDay(new Date());
    return { from: today, to: addDays(today, 29) };
    },
    },
    {
    label: "Dieses Wochenende",
    value: () => {
    const saturday = nextSaturday(startOfDay(new Date()));
    return { from: saturday, to: addDays(saturday, 1) };
    },
    },
    ]}
    presetLabels={{ yearToDate: "Seit Jahresbeginn" }}
    />
    );
    }

    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:

    • minDays und maxDays zählen beide Enden mit. Ein Mindestaufenthalt von zwei Nächten ist minDays={3}. Enden, die die Regel verletzen würden, sind beim Wählen des Endes nicht verfügbar, und Presets, die länger als maxDays sind, werden deaktiviert.
    • disabled nimmt true, um das ganze Feld zu sperren, oder einen Matcher für Tage: ein Date, eine Liste, { from, to }, { before }, { after }, { dayOfWeek: [0, 6] } oder eine Funktion. Gebuchte Nächte sind eine Liste von Daten.
    • excludeDisabled (Standard true) verhindert, dass ein Zeitraum über einen gesperrten Tag reicht. Genau das braucht eine Buchung.
    • labels.nights stellt die Zusammenfassung von Tagen auf Nächte um. Aus einem Aufenthalt über 4 Tage werden so 3 Nächte.
    • numberOfMonths ist standardmäßig 2 und kann 1 oder 3 sein. Auf dem Handy ist es immer einer.
    tsx
    "use client";
    import { useState } from "react";
    import { addDays, startOfDay } from "date-fns";
    import { DateRangePicker, type DateRange } from "@/components/ui/date-range-picker";
    const today = startOfDay(new Date());
    const booked = [addDays(today, 10), addDays(today, 11), addDays(today, 16)];
    const nights = (n: number) => `${n} ${n === 1 ? "Nacht" : "Nächte"}`;
    export function StayPicker() {
    const [stay, setStay] = useState<DateRange>({ from: null, to: null });
    return (
    <DateRangePicker
    label="Anreise bis Abreise"
    locale="en-US"
    placeholder="Wähl deine Nächte"
    min={today}
    disabled={booked}
    minDays={3}
    presets={false}
    numberOfMonths={1}
    description="Mindestens 2 Nächte. Durchgestrichene Nächte sind gebucht."
    labels={{ nights }}
    calendarProps={{ strikeDisabled: true }}
    value={stay}
    onValueChange={setStay}
    />
    );
    }

    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.

    Wähl im eingebetteten Calendar im Range-Modus einen Start und ein Ende. Mit der Locale en-GB beginnt jede Woche am Montag.
    $ npx wingo-ui@latest add calendar
    ProDoku: Calendar

    Lä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 zu 2026-10-12T22:00:00.000Z, und dein Server liest den falschen Tag. Sende lokale Daten. Mit name="period" rendert der Picker die versteckten Felder period.from und period.to als lokale ISO-Daten wie 2026-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 confirm bei 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:

    tsx
    import { DateRangePicker } from "@/components/ui/date-range-picker";
    import { Button } from "@/components/ui/button";
    const ISO_DATE = /^\d{4}-\d{2}-\d{2}$/;
    async function exportOrders(formData: FormData) {
    "use server";
    const from = String(formData.get("period.from") ?? "");
    const to = String(formData.get("period.to") ?? "");
    if (!ISO_DATE.test(from) || !ISO_DATE.test(to)) return;
    // führ deine Abfrage mit exklusivem Ende aus, z. B. in Postgres:
    // where created_at >= $1::date and created_at < $2::date + 1
    console.log("export orders", { from, to });
    }
    export function ExportForm() {
    return (
    <form action={exportOrders} className="flex flex-col gap-4">
    <DateRangePicker label="Zeitraum" name="period" locale="en-US" max={new Date()} />
    <Button type="submit">CSV exportieren</Button>
    </form>
    );
    }

    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.

    Komponenten in diesem Artikel

    • Date Range Picker

      A React date range picker for reports and bookings: two months with presets on desktop, a one-month bottom sheet on phones.

      Pro
    • Calendar

      A React calendar to pick one day, several days or a range, with disabled days, event dots, several months and a quick month / year jump.

      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

    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

    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 Kalender mit Terminen: Monat, Woche, Tag

    Ein React Kalender mit Terminen: Monats-, Wochen-, Tages- und Agenda-Ansicht, Verschieben per Drag, Rollback beim Speichern und Agenda-Liste am Smartphone.

    SRSerban Rusu·19. Okt. 2026·10 Min. Lesezeit
    Komponenten-Guides

    React Month Picker: Monate, Quartale und Zeiträume

    Ein React Month Picker für Abrechnung und Reports: Wähl einen Monat, ein Quartal oder einen Zeitraum im Jahresraster, mit Presets, Limits und Bottom Sheet.

    SRSerban Rusu·19. Okt. 2026·8 Min. Lesezeit
    Komponenten-Guides

    shadcn Registry: Fremde Komponenten sicher einbinden

    So nutzt du die shadcn Registry einer fremden Bibliothek in shadcn/ui: Namespaces, Auth-Header, Vorschau per Dry Run und die Dateien, die dabei kollidieren.

    SRSerban Rusu·13. Okt. 2026·8 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