Build2 min read

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:

  1. When are you arriving?
  2. 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:

Cabin-planner UI demo

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:

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.