DayPicker
An inline month-grid day picker with single, multiple and range selection, react-day-picker style matchers, modifiers and month/year jump pickers.
Installation
pnpm dlx @docyrus/cli add @docyrus/rn-day-pickerInstalls mini-calendar (shared grid helpers), wheel-picker, action-sheet, button and docyrus-icon as registry dependencies.
Usage
import { DayPicker } from '@/components/docyrus-native/day-picker';
const [value, setValue] = useState<Date | Date[] | null>(new Date());
<DayPicker value={value} onChange={setValue} />Range selection
In range mode the first tap emits [start], the second tap emits [start, end] (sorted).
<DayPicker mode="range" value={range} onChange={setRange} numberOfMonths={2} />Disabling days (matchers)
disabled accepts true (the whole picker) or any react-day-picker style matcher — or a list of them:
<DayPicker
value={value}
onChange={setValue}
disabled={[
{ dayOfWeek: [0, 6] }, // weekends
{ before: new Date() }, // the past
{ from: new Date(2026, 9, 10), to: new Date(2026, 9, 14) },
(date) => date.getDate() === 13
]}
/>Caption dropdowns
captionLayout="dropdown" turns the month and year of the caption into buttons that open a bottom sheet with a WheelPicker. dropdown-months / dropdown-years enable only one of them. The year range is startMonth → endMonth (falling back to minDate / maxDate, else 100 years back and 10 years ahead).
<DayPicker
captionLayout="dropdown"
startMonth={new Date(1950, 0)}
endMonth={new Date(2030, 11)}
value={birthday}
onChange={setBirthday}
/>Modifiers and marked dates
<DayPicker
value={value}
onChange={setValue}
modifiers={{ booked: bookedDates, weekend: { dayOfWeek: [0, 6] } }}
modifiersClassNames={{ booked: 'border border-destructive', weekend: 'bg-muted' }}
markedDates={datesWithEvents}
onDayPress={(date, modifiers) => {
if (modifiers.booked) showToast('Already booked');
}}
footer="Tap a free day to book it"
/>markedDates uses the same dot indicator (and the same createMarkedDateSet helper) as MiniCalendar.
Web-compatible props
selected / onSelect are accepted as aliases of value / onChange so web react-day-picker call sites port over. The value shapes stay native (Date, Date[], [start, end] — not { from, to }).
API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
value | Date | Date[] | null | — | Selected value — Date (single), Date[] (multiple) or [start, end] (range). |
onChange | (value: Date | Date[] | null) => void | — | Called with the new value. |
selected | Date | Date[] | null | — | Web alias of value (value wins when both are set). |
onSelect | (value: Date | Date[] | null) => void | — | Web alias of onChange (both are called when both are set). |
mode | 'single' | 'multiple' | 'range' | 'single' | Selection mode. |
minDate | Date | — | Days before it are disabled. |
maxDate | Date | — | Days after it are disabled. |
disabled | boolean | Matcher | Matcher[] | false | true disables the whole picker; a matcher disables only the matching days. |
weekStartsOn | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 0 | First day of the week (0 = Sunday … 6 = Saturday). |
showOutsideDays | boolean | true | Render the leading / trailing days of adjacent months (muted, selectable). |
fixedWeeks | boolean | false | Always render 6 weeks per month. |
numberOfMonths | number | 1 | Number of months, stacked vertically. Navigation moves one month at a time. |
captionLayout | 'label' | 'dropdown' | 'dropdown-months' | 'dropdown-years' | 'label' | Plain caption or month / year jump pickers. |
startMonth | Date | minDate | Earliest month reachable by navigation and the year picker. |
endMonth | Date | maxDate | Latest month reachable by navigation and the year picker. |
month | Date | — | Controlled first visible month. |
defaultMonth | Date | selected date / today | Initial first visible month (uncontrolled). |
onMonthChange | (month: Date) => void | — | Called with the first day of the new first visible month. |
modifiers | Record<string, Matcher | Matcher[]> | — | Custom day modifiers. |
modifiersClassNames | Record<string, string> | — | className applied to a day's circle when its modifier matches. |
markedDates | Date[] | — | Dates that show a dot indicator. |
markedDotColor | string | theme primary | Color of the dot indicators. |
onDayPress | (date: Date, modifiers: DayPickerModifiers) => void | — | Called on every day press (also disabled days) with the day's active modifiers. |
footer | ReactNode | — | Content below the month grid(s); a string renders as muted centered text. |
locale | string | device locale | BCP-47 locale for month / weekday names. |
variant | 'default' | 'outline' | 'ghost' | 'default' | Visual style. |
size | 'sm' | 'default' | 'lg' | 'default' | Cell / caption size. |
className | string | — | Additional CSS classes for the root. |
Matcher
| Shape | Matches |
|---|---|
boolean | Every day (true) or none (false) |
Date / Date[] | The given day(s) |
{ from, to? } (DateRange) | Days between from and to, inclusive (only from when to is missing) |
{ before } (DateBefore) | Days strictly before before |
{ after } (DateAfter) | Days strictly after after |
{ before, after } (DateInterval) | Days between them (exclusive); outside of them when after > before |
{ dayOfWeek } (DayOfWeek) | The given weekday(s), 0 = Sunday |
(date: Date) => boolean | Custom predicate |
Built-in modifiers
onDayPress receives these keys plus every custom modifiers key: selected, disabled, today, outside, range_middle, marked.
Components
| Component | Description |
|---|---|
DayPicker | Month grid day picker |
Type Exports
| Type | Description |
|---|---|
DayPickerProps | Props for the DayPicker component |
DayPickerMode | 'single' | 'multiple' | 'range' |
DayPickerVariant | 'default' | 'outline' | 'ghost' |
DayPickerSize | 'sm' | 'default' | 'lg' |
DayPickerCaptionLayout | 'label' | 'dropdown' | 'dropdown-months' | 'dropdown-years' |
DayPickerValue | Date | Date[] | null |
DayPickerModifiers | Record<string, boolean> — active modifiers of a day |
Matcher, DateRange, DateBefore, DateAfter, DateInterval, DayOfWeek | Matcher shapes (re-exported from mini-calendar) |
WeekStartsOn | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
Migration (breaking)
- The
defaultvariant no longer draws a border — usevariant="outline"for the previous look. - Weekday headers and month names are localized (device locale or
locale) instead of hard-coded English. showOutsideDaysdefaults totrue(web parity) — passfalsefor the previous empty leading cells.