Skip to content

Library · 2024 — now

Flash Calendar

An incredibly fast and flexible way to build calendars in React Native.

Flash Calendar started as a dependency of something else. I was building date pickers for Moni, a personal finance app I work on in my free time, and the options available didn't fit: no bottom sheet support, inconsistent spacing between five- and six-week months, a bundle heavier than it needed to be.

I had been maintaining a patch against the most popular alternative for three years. At some point maintaining someone else's calendar became more work than writing my own.

1.5k
GitHub stars
18kb
Minified, 6kb gzipped
1
Third-party dependency

Solve fewer needs better

The library that came before tried to do everything, and paid for it in surface area. Flash Calendar goes the other way: it builds calendars and calendar lists well, and declines the rest. Agenda mode is explicitly out of scope.

That constraint is what makes the rest possible. There isn't much surface to optimise, so it stays fast, and there isn't much to configure, so customising it never turns into a prop soup. It fits in 18kb.

import { Calendar, toDateId } from "@marceloterreiro/flash-calendar";

const today = toDateId(new Date());

<Calendar
  calendarActiveDateRanges={[{ startId: selected, endId: selected }]}
  calendarMonthId={today}
  onCalendarDayPress={setSelected}
/>;

Every prop contains the word calendar (calendarMinDateId, calendarActiveDateRanges, getCalendarDayFormat), so autocomplete finds them without you remembering the name.

The hooks underneath

Under the components sit useCalendar and useCalendarList, hooks that hand you the structure (weeks, days, active ranges, disabled states) and stop there. When the default theme doesn't match your product, you render your own components against the same hooks instead of fighting a styling API.

Infinite scroll, localization, dark mode, and bottom sheet compatibility come from that same structure rather than from flags.

What maintaining it taught me

The interesting part turned out not to be the date math. It was everything downstream of other people depending on you. A version number is a promise you have to keep. Documentation has to answer the question someone actually has, which is rarely the question that's easiest to write up. And when the same workaround shows up in a third issue, the API is wrong and that workaround is what the API should have been.