Skip to main content
Version: v0.22.x

DatePicker & Calendar

DatePicker is a React Native date picker that shows a month calendar. It supports single, range and multiple selection, min / max dates, disabled days, dots and labels under days, swipe navigation, a quick month jump and any locale.

import { DatePicker, Calendar } from '@elik56a/react-native-pickers';
  • DatePicker is the entry point. With display="calendar" (the default) it renders a Calendar, and with display="wheel" it renders a DateWheelPicker.
  • Calendar is what DatePicker renders by default, with the same props minus display. <DatePicker /> and <Calendar /> look and behave the same; import Calendar directly if you never need the wheel.
Loading…
<>
  <DatePicker value={date} onChange={setDate} />
  <Text style={{ textAlign: 'center', color: '#6E685E' }}>
    {date
      ? formatDate(date, undefined, { dateStyle: 'full' })
      : 'No date selected'}
  </Text>
</>

This page covers single selection and everything the calendar shares. Range and multiple selection are on the Date range & multiple page.

Try the props​

Platform
display
mode
weekdayFormat
firstDayOfWeek
<DatePicker value={value} onChange={setValue} firstDayOfWeek={0} />

Min and max dates​

Days outside [minDate, maxDate] are disabled (struck through). The arrows stop at the first and last allowed months, and the month grid greys out months outside the range. Only the day matters; the time of day is ignored.

Loading…
<DatePicker
  value={date}
  onChange={setDate}
  minDate={today}
  maxDate={addDays(today, 45)}
/>

Disabling days​

isDateDisabled runs for every visible day. Return true to disable it.

Loading…
<DatePicker
  value={date}
  onChange={setDate}
  initialMonth={new Date(2026, 11, 1)}
  isDateDisabled={(d) =>
    d.getDay() === 0 || d.getDay() === 6 || holidays.has(toDateKey(d))
  }
/>

You can also disable specific days through markedDates with disabled: true.

Keep it cheap

isDateDisabled is called up to 42 times per render. Avoid heavy work inside it; precompute a Set of disabled keys and check it with toDateKey.

Marked dates: dots, labels and colours​

markedDates is keyed by YYYY-MM-DD (local time; build keys with toDateKey). Each entry can have:

FieldTypeEffect
dotsstring[]Up to 3 coloured dots under the number (events, statuses)
labelstringSmall text under the number (prices, counts)
textColorstringColour of the day number
disabledbooleanDisable the day
Loading…
<DatePicker value={date} onChange={setDate} markedDates={marks} />

Locale and first day of week​

Month and weekday names come from Intl.DateTimeFormat for the locale you pass. firstDayOfWeek (0 = Sunday … 6 = Saturday) defaults to the locale's first day when Intl.Locale week info is available, else Sunday.

Loading…
<View style={{ gap: 24 }}>
  <DatePicker
    value={date}
    onChange={setDate}
    locale="fr-FR"
    firstDayOfWeek={1}
  />
  <DatePicker
    value={date}
    onChange={setDate}
    locale="ja-JP"
    weekdayFormat="narrow"
  />
</View>
  • Arrows step one month. They're disabled at minDate / maxDate.
  • Swipe left / right on the days to change month (enableSwipe, on by default). The direction flips in RTL.
  • Quick jump: tap the month title to open a grid of months (the arrows step by year), tap the title again for a grid of years (the arrows step by 12 years), and tap it once more to go back to days. Picking a year opens its months, and picking a month opens its days (enableQuickJump, on by default). The year grid is limited to yearRange, which defaults to the minDate / maxDate years or 100 years either side of today.
  • initialMonth sets the first month shown. By default it's the month of the selected date (or range start, or first multiple date), else today.
  • onMonthChange(month) fires with the first day of the newly shown month.

In single mode, when value changes from outside to a date in another month, the calendar follows it.

Layout​

Loading…
<DatePicker
  value={date}
  onChange={setDate}
  showOutsideDays={false}
  fixedWeeks={false}
  dayHeight={38}
  formatTitle={(month) =>
    month.toLocaleDateString('en-US', { month: 'short', year: '2-digit' })
  }
/>
  • fixedWeeks (default true) always renders 6 rows so the height never jumps between months. Set it to false to render only the weeks the month needs.
  • showOutsideDays (default true) shows the trailing and leading days of neighbouring months (tappable, dimmed).
  • dayHeight (default 44) is the row height; the selection circle is min(dayHeight − 4, 40).
  • showWeekdays={false} hides the weekday header row.

Custom days and arrows​

renderDay(state, theme) fully replaces a day cell's content (taps and the range band are still handled for you). renderArrow(direction, disabled) replaces the arrows.

Loading…
<DatePicker
  value={date}
  onChange={setDate}
  renderArrow={(dir, disabled) => (
    <Text style={{ fontSize: 16, opacity: disabled ? 0.3 : 1 }}>
      {dir === 'prev' ? '⬅️' : '➡️'}
    </Text>
  )}
  renderDay={(s, theme) => (
    <View
      style={{
        width: 36,
        height: 36,
        borderRadius: 10,
        alignItems: 'center',
        justifyContent: 'center',
        backgroundColor: s.selected
          ? theme.colors.primary
          : s.today
            ? theme.colors.primaryMuted
            : 'transparent',
        opacity: s.outside ? 0.35 : 1,
      }}
    >
      <Text
        style={{
          color: s.selected
            ? theme.colors.onPrimary
            : s.disabled
              ? theme.colors.textDisabled
              : theme.colors.text,
          fontWeight: '600',
        }}
      >
        {s.date.getDate()}
      </Text>
    </View>
  )}
/>

DayState passed to renderDay:

interface DayState {
date: Date;
selected: boolean; // the selected day, a range end, or one of multiple
rangeStart: boolean;
rangeEnd: boolean;
inRange: boolean; // strictly between start and end
today: boolean;
disabled: boolean;
outside: boolean; // belongs to the previous / next month
marking?: MarkedDate;
}

Styling​

Loading…
<DatePicker
  value={date}
  onChange={setDate}
  theme={{
    colors: { primary: '#059669', primaryMuted: 'rgba(5,150,105,0.12)' },
  }}
  styles={{
    container: {
      borderRadius: 20,
      borderWidth: 1,
      borderColor: '#E8E4DC',
      paddingHorizontal: 8,
    },
    headerTitle: { fontSize: 20, fontWeight: '800' },
    weekdayText: {
      textTransform: 'uppercase',
      fontSize: 10,
      letterSpacing: 1,
    },
    selectedDay: { borderRadius: 10 },
    todayDay: { borderRadius: 10 },
  }}
/>

Slots​

SlotElement
containerOuter view
headerTitle + arrows row
headerTitleMonth / year title text
arrowArrow button
arrowTextDefault arrow glyph
weekdaysWeekday header row
weekdayTextWeekday labels
weekEach week row
dayDay cell (pressable, full width of the column)
dayInnerThe circle inside the cell
dayTextDay number
selectedDay / selectedDayTextSelected circle / number
todayDay / todayDayTextToday's circle / number
disabledDayTextDisabled day numbers
outsideDayTextDays from neighbouring months
rangeBandRange highlight band
dotMarked-date dots
dayLabelMarked-date label text
gridCell / gridCellTextMonth and year grid cells (quick jump)

Props​

DatePicker accepts everything below plus display. With display="wheel", see DateWheelPicker instead.

Selection​

PropTypeDefaultDescription
display'calendar' | 'wheel''calendar'DatePicker only.
mode'single' | 'range' | 'multiple' | 'ranges''single'Selection mode; changes the type of value.
valueDate | null · DateRange · Date[] · DateRange[]—Selection (controlled), typed by mode.
defaultValuesame as valuenull · {start:null,end:null} · [] · []Initial selection when uncontrolled.
onChange(date: Date) => void · (range: DateRange) => void · (dates: Date[]) => void · (ranges: DateRange[]) => void—Fires on every tap that changes the selection.
minRangeDaysnumber—range and ranges. See range.
maxRangeDaysnumber—range and ranges.
allowSingleDayRangebooleantruerange and ranges.
maxSelectionsnumber—multiple only.
maxRangesnumber—ranges only.

Calendar​

PropTypeDefaultDescription
minDateDate—Earliest selectable day.
maxDateDate—Latest selectable day.
isDateDisabled(date: Date) => boolean—Return true to disable a day.
markedDatesRecord<string, MarkedDate>—Keyed by YYYY-MM-DD: { dots?, label?, textColor?, disabled? }.
localestringdeviceMonth / weekday names and default first day.
firstDayOfWeeknumber (0–6)from locale, else 00 = Sunday … 6 = Saturday.
initialMonthDateselected date or todayMonth shown first.
onMonthChange(month: Date) => void—Fires with the first day of the new month.
showOutsideDaysbooleantrueShow neighbouring months' days.
fixedWeeksbooleantrueAlways 6 rows.
enableSwipebooleantrueSwipe horizontally to change months.
enableQuickJumpbooleantrueTap the title to cycle days → months → years.
weekdayFormat'short' | 'narrow'from the design: 'narrow' in Material, else 'short'Mon vs M.
showWeekdaysbooleantrueShow the weekday header.
formatTitle(month: Date, locale?: string) => string"October 2026"Custom title text.
renderDay(state: DayState, theme: PickerTheme) => ReactNode—Custom day cell content.
renderArrow(direction: 'prev' | 'next', disabled: boolean) => ReactNode—Custom arrows.
yearRange[number, number]min/max or ±100 yearsYears available in the year grid.
dayHeightnumber44Height of a day row.
styleStyleProp<ViewStyle>—Container style.
stylesSlotStyles<CalendarSlot>—See slots.
themeDeepPartial<PickerTheme>—Theme override.
design'ios' | 'material' | 'web'from PickersProviderThe look to follow, over the provider's: iOS, Material or web.
testIDstring—Test ID.

Types​

interface DateRange { start: Date | null; end: Date | null }
interface MarkedDate { dots?: string[]; disabled?: boolean; label?: string; textColor?: string }
type CalendarProps = CalendarBaseProps & CalendarSelectionProps;
type DatePickerProps = ({ display?: 'calendar' } & CalendarProps) | ({ display: 'wheel' } & DateWheelPickerProps);

Accessibility​

Each day is a button whose label is the full date ("Wednesday, October 14, 2026") with selected / disabled state. The arrows are labelled "Previous" / "Next", and the title is a button when quick jump is on.

In a form field​

DatePickerField is a field that opens a DatePickerSheet and shows the confirmed date. Switch presentation in the panel: auto opens a dropdown under the field on the web and a bottom sheet on iOS and Android.

Platform
presentation
display
<DatePickerField
label="Due date"
placeholder="Pick a date"
value={date}
onConfirm={setDate}
/>

→ Picker fields