Scribble Calendar

A React Native calendar UI for Expo — a continuous month scroller where every completed day is crossed out with a generated marker stroke, seeded from the date so a day always draws the same scribble.

componentCalendars & DatesExpo SDK 57Free

Preview

Scribble Calendar screenshot 1

Usage

Terminal
$npx expo install react-native-svg expo-haptics react-native-safe-area-context

Built with React Native core only — no third-party UI library required.

Examples

6

buildProgram() produces the days, the lookup map and the range to render; ProgramCalendar renders them as a continuous month scroller with a sticky month title. Header and footer live inside the same scroll container, so the detail card scrolls with the grid instead of pinning to the bottom of the screen.

tsx
const program = buildProgram({ level: 1, finalGoal: 100 });const [selectedKey, setSelectedKey] = useState(program.todayKey);<ProgramCalendar  program={program}  selectedKey={selectedKey}  onSelect={(date, entry) => entry && setSelectedKey(entry.key)}  header={<ScheduleHeader level={program.level} />}  footer={<DayDetailCard entry={program.byKey.get(selectedKey)} />}/>

Overview

Scribble Calendar is a training-program calendar UI for Expo and React Native: a continuous, scrollable run of months with a sticky month title, a Monday-first seven-column grid, and a day tile that carries its own state. What makes it different from every other React Native calendar component is the mark. A completed day is not stamped with a checkmark icon or a tick font — it is crossed out with a marker stroke generated at render time. An FNV-1a hash of the date key seeds a mulberry32 PRNG, and buildStrokes turns that stream into one of four stroke families: a cursive loop, a two-row zigzag, a three-row zigzag, and a two-row zigzag with a decisive slash through it. The points are smoothed into quadratic segments and drawn as SVG paths with round caps and joins, so the scribble is vector at every cell size — no bitmaps, no icon font — and because the seed comes from the date rather than from Math.random, day 26 always draws the same scribble across renders, reloads and scroll recycling. Nothing flickers or redraws while you scroll. A day reads through five statuses from the program — done, missed, rest, today and upcoming — plus selected, which is orthogonal and layers on top of any of them; colour never carries the meaning alone, since each state also changes the tile's fill, elevation, shape or mark, so the grid stays legible at a glance and in monochrome. The program itself is generated relative to today by buildProgram(), so the calendar always opens with real history behind it, a live day, and a future ahead — no fixture dates to reset, whenever the app is opened. Presentation is split from data: nothing under src/data imports React, which is what makes the date maths and the scribble geometry testable in plain Node. Fourteen files, 1,067 lines, plain function components with no context and no global state — drop it into an Expo habit tracker, streak tracker, workout log, medication schedule or any app that has to show what got done. Built and run on iOS (New Architecture, Expo SDK 57, React Native 0.86, React 19); it contains no platform-specific code, but the Android build is not yet verified.

What's included

  • Continuous month scroller with a sticky month title
  • Generated marker strokes — four families: loop, 2-row zigzag, 3-row zigzag, zigzag + slash
  • Seeded from the date key — a day always draws the same scribble
  • SVG quadratic paths, not bitmaps or an icon font — crisp at any cell size
  • Five day states plus an orthogonal selected state
  • State never rides on colour alone — fill, elevation, shape and mark all shift
  • Monday-first grid, local-time date keys, no timezone drift
  • buildProgram() anchors history, today and the future to the real date
  • Spring press animation and haptics on every day tile
  • Auto-scrolls to the current month on mount
  • src/data imports no React — date maths and geometry testable in plain Node
  • Grid logic and 27 generated strokes covered by tests
  • 14 files, 1,067 lines, no context and no global state
  • Includes the patch-package fix for the Expo SDK 57 x Xcode 26.2 build error
  • Expo SDK 57, React Native 0.86, React 19, New Architecture
  • MIT licensed — free for personal and commercial use

Tech Stack

ExpoReact NativeJavaScriptreact-native-svgexpo-hapticsreact-native-safe-area-context

Get this component

Free

One-time payment · Lifetime access

Free License

Personal and commercial use

Free
  • Use in 1 personal project
  • Lifetime access to updates
  • Email support
  • Remove attribution
  • Commercial use included
Get it on GitHub
Full JavaScript source code
All examples & variants
Lifetime updates
Public repo — clone or fork it