Description:
super-calendar is a React calendar component that creates month, week, day, 3-day, custom N-day, and schedule views with event data, date selection, and gesture-driven time grids.
The component uses a virtualized date pager, Reanimated zoom on native, and a separate DOM renderer for standard React web apps.
Preview

Features
- Renders month, week, day, 3-day, custom N-day, and schedule calendar views.
- Virtualizes and snap-pages date views across long ranges.
- Responds to pinch zoom on native and Ctrl or Command plus scroll on web.
- Accepts application-specific event fields and a custom event component.
- Handles single-date, multiple-date, and range selection in a scrollable month list.
- Supports event move, resize, and creation on the week and day grid.
- Applies light and dark theme presets plus locale-aware date labels.
- Runs on iOS, Android, and web through separate React Native and DOM renderers.
How To Use It
Install the Native Calendar
Import Reanimated, Worklets, Gesture Handler, Legend List, and date-fns.
npm install @super-calendar/native
npm install react-native-reanimated react-native-worklets react-native-gesture-handler @legendapp/list date-fnsRender a Controlled Calendar
Calendar keeps the visible date controlled through the date prop. Echo onChangeDate into that state so page changes and today alignment follow the current value.
import { useState } from "react";
import { Calendar, type CalendarEvent } from "@super-calendar/native";
type ScheduleEvent = {
id: string;
color: string;
team: string;
};
const events: CalendarEvent<ScheduleEvent>[] = [
{
id: "design-review",
color: "#7C3AED",
team: "Product",
title: "Design review",
start: new Date(2026, 7, 5, 9, 30),
end: new Date(2026, 7, 5, 10, 30),
},
{
id: "release-window",
color: "#0891B2",
team: "Engineering",
title: "Release window",
start: new Date(2026, 7, 6, 14, 0),
end: new Date(2026, 7, 6, 16, 0),
},
];
export function ScheduleCalendar() {
const [date, setDate] = useState(new Date(2026, 7, 1));
const [mode, setMode] = useState<"month" | "week" | "day">("week");
// Keep page changes in the controlled date state.
return (
<Calendar
mode={mode}
date={date}
events={events}
weekStartsOn={1}
onChangeDate={setDate}
onPressEvent={(event) => console.log(event.title)}
onPressDay={(day) => {
setDate(day);
setMode("day");
}}
/>
);
}Render Custom Event Cards
renderEvent receives a React component. Define it outside the screen component or memoize it so the calendar can reuse the inner views across renders.
import { Pressable, Text } from "react-native";
import { Calendar, type RenderEventArgs } from "@super-calendar/native";
type ScheduleEvent = {
id: string;
color: string;
team: string;
};
function EventCard({ event, onPress, isAllDay }: RenderEventArgs<ScheduleEvent>) {
return (
<Pressable
onPress={onPress}
style={{ flex: 1, padding: 6, borderRadius: 8, backgroundColor: event.color }}
>
{/* Keep the content inside the event box supplied by the calendar. */}
<Text style={{ color: "#FFFFFF", fontWeight: "700" }}>{event.title}</Text>
<Text style={{ color: "#FFFFFF" }}>{isAllDay ? "All day" : event.team}</Text>
</Pressable>
);
}
// Reuse the events array from the controlled calendar example.
<Calendar
mode="week"
date={new Date(2026, 7, 3)}
events={events}
renderEvent={EventCard}
/>Add Dragging and Event Creation
Pass onDragEvent to enable move and resize interactions. The handler receives the event plus its proposed start and end dates. Return false to reject a placement.
<Calendar
mode="week"
date={date}
events={events}
dragStepMinutes={30}
eventOverlap={false}
onDragEvent={(event, start, end) => {
if (event.team === "Locked") return false;
setEvents((current) =>
current.map((item) =>
item.id === event.id ? { ...item, start, end } : item,
),
);
}}
onCreateEvent={(start, end) => {
setEvents((current) => [
...current,
{
id: String(Date.now()),
color: "#EA580C",
team: "Operations",
title: "New appointment",
start,
end,
},
]);
}}
/>Add Recurring Events
The calendar accepts recurrence rules through event data. Expand the rules for the visible range before passing the result to Calendar.
import { Calendar, expandRecurringEvents } from "@super-calendar/native";
const recurring = [
{
id: "support-checkin",
title: "Support check-in",
start: new Date(2026, 7, 3, 11, 0),
end: new Date(2026, 7, 3, 11, 30),
recurrence: {
freq: "weekly",
weekdays: [1, 3],
count: 12,
},
},
];
const visibleEvents = expandRecurringEvents(
recurring,
new Date(2026, 7, 1),
new Date(2026, 7, 31),
);
<Calendar mode="month" date={new Date(2026, 7, 1)} events={visibleEvents} />;Create a Date Range Picker
Use MonthList for date picking. The paged month view is intended for event browsing. useDateRange owns the range state machine.
import { useMemo, useState } from "react";
import { MonthList, useDateRange } from "@super-calendar/native";
export function BookingDatePicker() {
const [month, setMonth] = useState(new Date(2026, 7, 1));
const minDate = useMemo(() => new Date(), []);
const { range, onPressDate, selectRange } = useDateRange({ minDate });
return (
<MonthList
date={month}
weekStartsOn={1}
selectedRange={range ?? undefined}
minDate={minDate}
isDateDisabled={(day) => day.getDay() === 0}
onPressDay={onPressDate}
onSelectDrag={selectRange}
onChangeVisibleMonth={setMonth}
/>
);
}Use the Web or Headless Packages
Use @super-calendar/dom for a plain React DOM app. It exports MonthView, MonthList, TimeGrid, and useDateRange. It uses inline styles through a theme prop.
npm install @super-calendar/dom react react-dom @legendapp/list date-fnsimport { MonthList, TimeGrid, useDateRange } from "@super-calendar/dom";Use @super-calendar/core when the application owns the renderer. Its exports include buildMonthGrid, useMonthGrid, useDateRange, selection helpers, event layout, and date utilities.
npm install @super-calendar/core react date-fnsimport { buildMonthGrid, nextDateRange } from "@super-calendar/core";Calendar API
| Group | props |
|---|---|
| Data | events, date, mode, numberOfDays, weekStartsOn, weekdayFormat, timeZone |
| Navigation | onChangeDate, onChangeDateRange, freeSwipe |
| Rendering | renderEvent, eventAccessibilityLabel, renderCustomDateForMonth, eventCellStyle, calendarCellStyle, businessHours, renderBusinessHours, renderTimeGridHeader, renderHeaderForMonthView, headerComponent, keyExtractor |
| Interaction | onDragEvent, onDragStart, onCreateEvent, dragStepMinutes, showDragHandle, eventStartEditable, eventDurationEditable, eventOverlap, onPressEvent, onPressCell, onPressDay, onPressMore |
| Selection | selectedDates, selectedRange, onSelectDrag, minDate, maxDate, isDateDisabled |
| Display | scrollOffsetMinutes, hourHeight, timeslots, ampm, showNowIndicator, showAllDayEventCell, allDayLabel, highlightWeekends, maxVisibleEventCount, theme, classNames, styles |
Alternatives and Related Resources
- 10 Best Calendar Components For React & React Native Apps
- React Native Timeline Calendar Kit
- Swipeable Calendar Component For React Native
FAQs
Q: Which package should I install for a React DOM calendar?
A: Install @super-calendar/dom with react, react-dom, @legendapp/list, and date-fns. Import MonthView, MonthList, or TimeGrid from @super-calendar/dom.
Q: Why does paging stop following the current date?
A: Keep date controlled and pass the new value from onChangeDate back into Calendar.
Q: Can I use only the date picker?
A: Yes. Import MonthList, useDateRange, and useMonthGrid from @super-calendar/native/picker. Install the picker peers listed in the package documentation.
Q: How do I block past dates or specific weekdays?
A: Pass minDate, maxDate, or isDateDisabled to MonthList and pass the same range constraints to useDateRange.
Q: Why do custom event cards remount during calendar updates?
A: Keep the renderEvent component and interaction callbacks stable. Define the renderer at module scope or wrap callbacks in useCallback.





