The ExpandableCalendar component provides an interactive calendar that can expand from a week view to a full month view, with smooth animations and gesture support.
The ExpandableCalendar should be wrapped with CalendarProvider to work properly.
Basic usage
import { CalendarProvider, ExpandableCalendar } from 'react-native-calendars';
<CalendarProvider date="2023-05-16">
<ExpandableCalendar
firstDay={1}
markedDates={{
'2023-05-16': {marked: true}
}}
/>
</CalendarProvider>
Props
ExpandableCalendar extends all CalendarList props.
Position and behavior
initialPosition
'open' | 'closed'
default:"'closed'"
The initial position of the calendar. Use the exported Positions enum.import { ExpandableCalendar } from 'react-native-calendars';
<ExpandableCalendar
initialPosition={ExpandableCalendar.positions.OPEN}
/>
Disable the pan gesture and prevent opening/closing of the calendar. The initialPosition will persist.
Whether to close the calendar when a day is pressed.
Gesture thresholds
A threshold (in pixels) for opening the calendar with the pan gesture.
A threshold (in pixels) for closing the calendar with the pan gesture.
Display options
Whether to hide the knob. Automatically hidden when numberOfDays > 1.
Whether to have shadow/elevation for the calendar.
Whether to disable the week scroll in closed position.
Arrow customization
Source for the left arrow image.leftArrowImageSource={require('./custom-left-arrow.png')}
Source for the right arrow image.rightArrowImageSource={require('./custom-right-arrow.png')}
Event handlers
onCalendarToggled
(isOpen: boolean) => void
Callback that fires when the calendar is opened or closed.onCalendarToggled={(isOpen) => {
console.log('Calendar is now', isOpen ? 'open' : 'closed');
}}
Handler which gets executed on day press.
onVisibleMonthsChange
(months: DateData[]) => void
Handler which gets executed when visible months change.
CalendarList props
Since ExpandableCalendar extends CalendarList, it also supports:
Whether to render the calendar list horizontally.
Theme object for styling the calendar.
First day of the week (0 = Sunday, 1 = Monday).
Collection of dates that need to be marked.
Hide month navigation arrows.
renderArrow
(direction: 'left' | 'right') => ReactNode
Replace default arrows with custom ones.
onPressArrowLeft
(method: () => void, month?: XDate) => void
Handler for left arrow press.
onPressArrowRight
(method: () => void, month?: XDate) => void
Handler for right arrow press.
Accessibility
Test identifier for automated testing.
Positions enum
The component exports a positions enum with the following values:
ExpandableCalendar.positions.OPEN - Calendar is fully expanded
ExpandableCalendar.positions.CLOSED - Calendar is collapsed to week view
Examples
Basic expandable calendar with CalendarProvider
import { CalendarProvider, ExpandableCalendar } from 'react-native-calendars';
import { useState } from 'react';
function MyExpandableCalendar() {
const [selected, setSelected] = useState('');
return (
<CalendarProvider date={selected || '2023-05-16'}>
<ExpandableCalendar
firstDay={1}
markedDates={{
[selected]: {selected: true, selectedColor: 'blue'}
}}
onDayPress={(day) => setSelected(day.dateString)}
/>
</CalendarProvider>
);
}
Expandable calendar with custom theme
<CalendarProvider date="2023-05-16">
<ExpandableCalendar
theme={{
backgroundColor: '#ffffff',
calendarBackground: '#ffffff',
selectedDayBackgroundColor: '#00adf5',
selectedDayTextColor: '#ffffff',
todayTextColor: '#00adf5',
dotColor: '#00adf5',
arrowColor: '#00adf5'
}}
firstDay={1}
markedDates={{
'2023-05-16': {marked: true, dotColor: 'red'},
'2023-05-17': {marked: true, dotColor: 'blue'}
}}
/>
</CalendarProvider>
Calendar starting in open position
<CalendarProvider date="2023-05-16">
<ExpandableCalendar
initialPosition={ExpandableCalendar.positions.OPEN}
onCalendarToggled={(isOpen) => {
console.log('Calendar toggled:', isOpen);
}}
/>
</CalendarProvider>
Disabled pan gesture
<CalendarProvider date="2023-05-16">
<ExpandableCalendar
disablePan
initialPosition={ExpandableCalendar.positions.OPEN}
closeOnDayPress={false}
/>
</CalendarProvider>
Custom arrows and thresholds
<CalendarProvider date="2023-05-16">
<ExpandableCalendar
leftArrowImageSource={require('./custom-left.png')}
rightArrowImageSource={require('./custom-right.png')}
openThreshold={50}
closeThreshold={50}
renderArrow={(direction) => (
<Text style={{fontSize: 20}}>
{direction === 'left' ? '◀' : '▶'}
</Text>
)}
/>
</CalendarProvider>
<CalendarProvider date="2023-05-16">
<ExpandableCalendar
disableWeekScroll
allowShadow={false}
hideKnob={true}
/>
</CalendarProvider>
Complete example with AgendaList
import {
CalendarProvider,
ExpandableCalendar,
AgendaList
} from 'react-native-calendars';
function CompleteAgenda() {
const [selected, setSelected] = useState('2023-05-16');
const [items, setItems] = useState({
'2023-05-16': [{name: 'Meeting'}],
'2023-05-17': [{name: 'Lunch'}]
});
return (
<CalendarProvider date={selected}>
<ExpandableCalendar
firstDay={1}
markedDates={{
[selected]: {selected: true}
}}
onDayPress={(day) => setSelected(day.dateString)}
/>
<AgendaList
sections={items}
renderItem={(item) => (
<View style={{padding: 20, backgroundColor: 'white'}}>
<Text>{item.name}</Text>
</View>
)}
/>
</CalendarProvider>
);
}
Notes
Always wrap ExpandableCalendar with CalendarProvider. The component relies on the context provided by CalendarProvider to function properly.
The knob is automatically hidden when using numberOfDays > 1 in the CalendarProvider.
When using horizontal mode, the calendar will automatically handle month transitions and week scrolling.