ExpandableCalendar
ExpandableCalendar is the date picker at the top of schedule, booking and habit screens: one week of days that opens into the whole month as you drag it down, following your finger, or when you tap the handle under it, and folds back into a week as you drag it up. The week you open from stays in place as the rest of the month slides out around it, and the month folds into the week of the day you pick.
It's a WeekStrip and the Calendar's month in one, so it takes the same markedDates, minDate, maxDate, isDateDisabled, renderDay and styles, and follows the design: a grabber under the days on iOS, as a sheet has, and a chevron in Material and on the web.
It picks a day; it doesn't draw events. Put an Agenda or a Timeline under it for the events, or list the picked day's items yourself, as in the schedule below.
import { ExpandableCalendar } from '@elik56a/react-native-pickers';
<ExpandableCalendar value={day} onChange={setDay} />
Try the propsβ
firstDayOfWeekweekdayFormat<ExpandableCalendar
value={day}
onChange={setDay}
firstDayOfWeek={0}
weekdayFormat="short"
/>
A schedule screenβ
Pass the days that have something on them as markedDates, and list the picked day's items under the calendar. onWeekChange and onMonthChange tell you which days are shown, to load them.
<View> <ExpandableCalendar value={day} onChange={setDay} markedDates={MARKS} /> <View style={{ padding: 16, gap: 8 }}> {classes.length ? classes.map((item) => <Text key={item}>{item}</Text>) : <Text>Nothing booked</Text>} </View> </View>
To add an event, open a form with a DateTimePickerField or a TimeRangePickerField.
Open and foldedβ
The calendar starts as a week, or as the month with defaultExpanded. To open or fold it from your own button, control it with expanded and onExpandedChange:
const [expanded, setExpanded] = useState(false);
<ExpandableCalendar value={day} onChange={setDay} expanded={expanded} onExpandedChange={setExpanded} />
<Button title={expanded ? 'Week' : 'Month'} onPress={() => setExpanded(!expanded)} />
-
Opening shows the month of the selected day when it's in the week shown, else the month most of the week falls in.
-
Folding shows the week of the selected day when it's in the month shown, else today's week, else the month's first week.
-
The arrows and a swipe left or right page by month while open and by week while folded.
-
Dragging moves the month with your finger. Let go past a short way, or with a flick, and it carries on; otherwise it springs back.
enableSwipe={false} turns off the drag and the swipes, leaving the arrows and the handle.
Propsβ
| Prop | Type | Default | Description |
|---|---|---|---|
value | Date | null | β | Selected day (controlled). |
defaultValue | Date | null | β | Initial day when uncontrolled. |
onChange | (date: Date) => void | β | Fires when a day is tapped. |
expanded | boolean | β | Showing the whole month (controlled). |
defaultExpanded | boolean | false | Initial state when uncontrolled. |
onExpandedChange | (expanded: boolean) => void | β | Fires when the user opens or folds the month. |
initialDate | Date | the selected day or today | A day in the week and month shown first. |
onWeekChange | (weekStart: Date) => void | β | Fires with the first day of the week after paging while folded. |
onMonthChange | (month: Date) => void | β | Fires with the first of the month after paging while open. |
firstDayOfWeek | 0β6 | from locale, else 0 | 0 = Sunday. |
locale | string | device | Weekday and month names. |
minDate / maxDate | Date | β | Days outside are disabled, and paging stops at them. |
isDateDisabled | (date: Date) => boolean | β | Disable a day. |
markedDates | Record<string, MarkedDate> | β | Dots, labels or disabled days, keyed by YYYY-MM-DD. |
showHeader | boolean | true | Show the month title and the arrows. |
formatTitle | (month: Date, locale?: string) => string | the month shown | Title text. |
showWeekdays | boolean | true | Show the weekday names. |
weekdayFormat | 'short' | 'narrow' | from the design | Weekday names: Mon or M. |
enableSwipe | boolean | true | Swipe left or right to page, and drag down to open and up to fold. |
renderDay | (state: DayState, theme: PickerTheme) => ReactNode | β | Fully custom day cell, as on the calendar. |
renderArrow | (direction, disabled) => ReactNode | β | Custom arrows. |
dayHeight | number | 44 | Day cell height. |
style | StyleProp<ViewStyle> | β | Container style. |
styles | SlotStyles<CalendarSlot> | β | The calendar slots, plus expandHandle. |
theme | DeepPartial<PickerTheme> | β | Theme override. |
design | 'ios' | 'material' | 'web' | from PickersProvider | The look to follow, over the provider's: iOS, Material or web. |
testID | string | β | Test ID. |
Accessibilityβ
The handle is a button named "Show month" or "Show week", with its expanded state. Days read as on the calendar, such as "Wednesday, October 14, 2026", and the arrows as "Previous" and "Next".
Relatedβ
- WeekStrip: one week, without the month
- Agenda and Timeline: the events under it, as a list or by the hour
- DatePicker: a whole month, ranges and multiple days
- Migrating from react-native-calendars: its
ExpandableCalendarandCalendarProvider