Skip to content

Calendar

What it does

The Calendar is a unified time-grid view shared by both the Today page (single day) and the Week page (seven days). It renders tasks as time blocks positioned by startTime/duration, supports infinite horizontal scrolling through days/weeks, and lets you pinch/ctrl-scroll to zoom the hour height.

Files tied to it

FilePurpose
src/features/calendar/UnifiedCalendar.tsxThe calendar component itself. Takes a mode: 'today' | 'week' prop so the same grid renders in both contexts
src/features/calendar/CalendarDayColumn.tsxA single day's column — the hour grid plus positioned task blocks
src/features/calendar/useCalendarZoom.tsCtrl+wheel zoom logic; hour height persisted per-mode to localStorage under kairo.cal.<mode>.hourHeight
src/features/calendar/useInfiniteDays.tsInfinite-scroll day windowing — keeps a rolling buffer of days (BUFFER_DAYS = 14) mounted around the visible range and prepends/appends as you scroll

Key concepts / how it connects

  • One component, two hosts. TodayPage mounts <UnifiedCalendar mode="today" />; WeekPage/WeekPlannerView mount it in week mode. There's no separate "day calendar" vs "week calendar" implementation to keep in sync — differences (single column vs seven, infinite horizontal scroll enabled or not) are branches inside UnifiedCalendar and its hooks.
  • Task blocks read from the same repository hooks as Planner/Markdown mode (useTasksForRange from src/db/repositories/taskRepository.ts), bucketed client-side by date.
  • Zoom and infinite scroll are separate concerns. useCalendarZoom only manipulates vertical hour height; useInfiniteDays only manages which day columns are mounted horizontally. Both operate on the same scroll container ref.
  • The .time-slot { height: 80px } rule in src/index.css is the default hour-row height that useCalendarZoom scales up/down from (DEFAULT_HOUR_HEIGHT = 80, clamped between 40 and 320).

Where to start editing

  • Changing how a task block looks/positions -> CalendarDayColumn.tsx.
  • Changing zoom limits or default zoom -> useCalendarZoom.ts (MIN_HOUR_HEIGHT / MAX_HOUR_HEIGHT / DEFAULT_HOUR_HEIGHT).
  • Changing how many days are buffered for infinite scroll -> useInfiniteDays.ts (BUFFER_DAYS).
  • Note: there is currently no dedicated component/test subfolder under calendar/ — all four files live flat in src/features/calendar/.