Multi-select calendar
Building my multi-select calendar was surprisingly fun. Take a look at how it's made.
I made a fully functioning multi-select/date range calendar component, and it lets you select multiple days while staying somewhat accessible.
Motivation
I'm building a simple service for my (rather large) family to coordinate different things (dinner, cabin trips etc). I needed a calendar to select date ranges to make it easy to answer the following:
- When are you arriving?
- When are you leaving?
It sorta works like Airbnb's calendar picker, except that it doesn't update the
range on :hover, only on click. Here's how it's used in the family planner:

I also plan to use the component to filter data in a list view at a later stage.
Technical details
All the date stuff relies heavily on Dayjs, and styling is done with TailwindCSS.
The package (not published to NPM btw) essentially has two exports:
useCalendar(): Hook that handles all the logic. If you want to style this your own way, you can use this hook without importing theCalendarcomponents.Calendar: Consist of three "compound components":<Calendar.CalendarActions />: Showing the calendar title and the buttons for navigating between months.<Calendar.CalendarHeader />: The top list of days (Monday-Sunday)<Calendar.CalendarGrid />: Showing the currently selected months, and it's days.
Here's a minimal code example of how it's used:
const CalendarDemo = () => {
const [calendarState, calendarEvents] = useCalendar();
const { currentDate, days } = calendarState;
return (
<div className="">
<div className="text-center">
<Calendar.CalendarActions
className="mb-4"
onNextMonth={calendarEvents.handleNextMonthClick}
onPrevMonth={calendarEvents.handlePreviousMonthClick}
>
{currentDate.format("MMMM YYYY")}
</Calendar.CalendarActions>
<Calendar.CalendarHeader daysToRender={days} />
</div>
<Calendar.CalendarGrid
onClick={calendarEvents.handleDateClick}
selectionStart={calendarState.selectionStart}
selectionEnd={calendarState.selectionEnd}
selectedMonth={currentDate.month()}
daysToRender={days}
/>
</div>
);
};
I'll probably go more in-depth about it's API and how it's built in the future, but for now I just wanted to show this off to the world 🌍.
If you want to take a look at the source code, you'll find that on Github.
Feedback
If you have any feedback, please reach out to @rix1 on Twitter.