React Date Picker Component Examples
Drop-in React Date Picker examples: single date, range, year dropdown, custom format, and locale. Built on react-day-picker with one prop-driven import.
A date input lives in nearly every product workflow that touches scheduling — booking, billing dates, analytics filters, deadlines, expiry. The DatePicker component in Drivn is the popover-wrapped variant of Calendar: a triggered button that opens a calendar grid, formats the selected day, and dismisses on outside click or Escape. Use it any time the calendar should be hidden behind a button, not rendered inline.
This page collects the patterns that come up in shipped UIs. Each example is copy-paste ready and uses the same @/components/ui/date-picker import path the Drivn CLI installs under, so the snippets compile the moment you run npx drivn add date-picker. The full component source ships into your repo, so any edit beyond what the props expose is a local change rather than a theme override.
If you need the calendar grid rendered inline — without a trigger — use Calendar directly. The Calendar examples page covers that case. The DatePicker examples below stay focused on the trigger pattern: single date, date range with DatePicker.Range, year and month dropdown for far-from-today values, custom formatting via the formatDate prop, and locale support that updates the trigger label and the calendar caption together.
Single-date selection
The default DatePicker renders a button trigger with a CalendarDays icon and the placeholder text. Click the button and a calendar grid opens below. Pass selected as Date | undefined and onSelect as the setter — react-day-picker handles day clicks via the wrapped Calendar, and the popover dismisses automatically once a date is picked.
Because the DatePicker source lives in your repo after install, swapping the trigger styling or adding an extra aria-label is a local edit. The minimum viable integration is below: a controlled useState<Date | undefined> bound to the component, no wrapper div needed.
1 import { useState } from "react" 2 import { DatePicker } from "@/components/ui/date-picker" 3 4 export default function Page() { 5 const [date, setDate] = useState<Date | undefined>() 6 7 return ( 8 <DatePicker 9 selected={date} 10 onSelect={setDate} 11 /> 12 ) 13 }
Range selection with DatePicker.Range
DatePicker.Range is mounted on the same root via dot notation. The selected prop narrows to DateRange | undefined, where DateRange = { from: Date; to?: Date }, re-exported from react-day-picker. The first click sets from, the second click sets to, and the trigger label formats as Apr 1 – Apr 7. The popover stays open between clicks and only closes when the range completes, so the user does not have to reopen the trigger to set the second date.
This pattern fits booking flows, leave requests, reporting period filters, and any UI where two related dates need to be picked together. For the inline (non-popover) version of range selection, use Calendar.Range directly.
1 import { useState } from "react" 2 import { 3 DatePicker, 4 type DateRange, 5 } from "@/components/ui/date-picker" 6 7 export default function Page() { 8 const [range, setRange] = useState<DateRange | undefined>() 9 10 return ( 11 <DatePicker.Range 12 selected={range} 13 onSelect={setRange} 14 /> 15 ) 16 }
Year and month dropdown variant
Pass variant="dropdown" to swap the month-and-year caption for <select> elements. By default the dropdown lists today's year plus and minus twenty — set fromYear and toYear for a different window. This is the right default for birthday pickers (fromYear={1900}), expiry-date inputs (toYear={2050}), or anything where the user must jump across years without paginating month-by-month.
Under the hood, the variant prop forwards to the wrapped Calendar and the year shortcuts convert into the startMonth and endMonth Date objects react-day-picker expects. No additional date-fns code, no caption template — one prop change.
1 <DatePicker 2 variant="dropdown" 3 selected={date} 4 onSelect={setDate} 5 />
Custom date formatting
By default the trigger label uses toLocaleDateString with month: "short", day: "numeric", year: "numeric" — Apr 27, 2026. Pass a formatDate function to override how the selected date renders. The function takes a Date and returns a string; Drivn shows whatever you return inside the trigger button.
A common case is European day-month-year ordering or a tighter MM/DD/YYYY. Build the formatter inline or import a shared one from your i18n module — the prop accepts any (date: Date) => string. The same function applies whether you pass a single date or compose DatePicker.Range, where the formatter runs against both from and to separately.
1 import { useState } from "react" 2 import { DatePicker } from "@/components/ui/date-picker" 3 4 export default function Page() { 5 const [date, setDate] = useState<Date | undefined>() 6 7 return ( 8 <DatePicker 9 selected={date} 10 onSelect={setDate} 11 formatDate={(d) => 12 d.toLocaleDateString("en-GB", { 13 day: "2-digit", 14 month: "2-digit", 15 year: "numeric", 16 }) 17 } 18 /> 19 ) 20 }
Locale support
Pass a locale from react-day-picker/locale and the trigger label, weekday headers, month names, and first-day-of-week all update together. A Czech locale (cs) shifts the grid to start on Monday and renders month names as leden / únor / březen. No provider, no separate i18n setup — the locale is plain data passed by prop.
Dozens of locales ship pre-built in react-day-picker/locale. Pick the one matching your app's active locale and pass it in. If your translation layer already resolves a locale string, wire it through React context and the DatePicker reads from there. For tokens that affect the calendar appearance beyond what locale objects cover, see the theming docs.
1 import { useState } from "react" 2 import { DatePicker } from "@/components/ui/date-picker" 3 import { cs } from "react-day-picker/locale" 4 5 export default function Page() { 6 const [date, setDate] = useState<Date | undefined>() 7 8 return ( 9 <DatePicker 10 locale={cs} 11 selected={date} 12 onSelect={setDate} 13 /> 14 ) 15 }
Install Drivn in one command
Copy the source into your project and own every line. Zero runtime dependencies, pure React + Tailwind.
npx drivn@latest createRequires Node 18+. Works with npm, pnpm, and yarn.
Frequently asked questions
Calendar renders the month grid inline. DatePicker wraps Calendar in a trigger button plus a controlled popover, handling outside-click and Escape dismissal for you. Use Calendar when the grid is always visible — sidebar, card, booking widget. Use DatePicker when the grid should open from a button, the way most form inputs do.
Yes — DatePicker.Range is mounted on the same import via dot notation. Pass a DateRange | undefined to selected and a (range) => void to onSelect. The popover stays open between the two clicks and dismisses once both from and to are set. No additional component to install or import.
No — popover behavior is built in. The component manages its own open state, listens for outside clicks via a document mousedown listener, and dismisses on Escape via a keyboard listener. Open state, dismiss handlers, and the closing animation live inside date-picker.tsx. You do not need to install or compose a separate Popover primitive.
Pass defaultMonth as a Date. The calendar opens to that month but leaves selected undefined, so no day is highlighted. This is useful for vacation pickers that should open on next month, quarterly filters that should open on the start of Q1, or any case where you want to nudge the user toward a period without committing to a date yet.
The DatePicker file starts with "use client" because it manages state with useState and listens for events. You can import it from a Server Component, but it renders on the client. Next.js draws the client boundary correctly based on the use client directive at the top of the file — no manual configuration needed in your layout or page.