Calendar: event dots + configurable day-cell click in Day Panel - #299
Merged
Conversation
On the Calendar tab, the Day Panel mini-calendar now shows per-day event counts (from useCalendarRange) instead of the journal heatmap. Other tabs keep the journal heatmap unchanged. Day-cell click behavior is now user-configurable: - Global setting: journal (default) or calendar - Calendar-page override: inherit / journal / calendar (default: calendar, preserves current behavior) Click from a non-calendar tab with global=calendar now opens a Calendar tab and sets the anchor date. Adds a 'Calendar' settings section, new 'calendar' settings group (distinct from existing calendar.google), IPC get/set handlers, and a useCalendarPreferences hook exposing a pure resolveDayCellClickBehavior helper covered by 7 unit tests. Regenerates the IPC invoke map + preload RPC bindings (drift from the current generator output — pnpm ipc:check now passes).
…in tests The CalendarItemChip refactor to native Electron menu dropped the canDeleteEvent() guard (wiring delete on task/reminder/snooze chips) and left renderer tests without a showContextMenu mock, so three tests failed in CI and a fourth passed vacuously. Add the mock to the global test setup, restore the guard, and rewrite the 4 affected tests to drive through the IPC mock instead of looking for DOM menuitems that native menus don't render.
h4yfans
added a commit
that referenced
this pull request
May 6, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
useCalendarRange) instead of the journal heatmap. Other tabs keep the journal heatmap unchanged.journal(default) orcalendar.inherit/journal/calendar. Defaultcalendarso today's behavior is preserved when the Calendar tab is active.calendaropens a Calendar tab and sets the anchor date.Why
The right-sidebar Day Panel is useful on every tab, but on the Calendar tab the journal heatmap dots don't match what the user is actually looking at. The user also wanted control over where a day click leads — Journal for note-centric users, Calendar for calendar-centric users — with a per-page override so the Calendar tab can always mean "stay in Calendar."
What changed
Contracts / RPC
packages/contracts/src/settings-schemas.ts— addsCalendarSettingsSchema+CALENDAR_SETTINGS_DEFAULTS(distinct from existingcalendar.googlegroup).packages/contracts/src/ipc-channels.ts— addsGET_CALENDAR_SETTINGS/SET_CALENDAR_SETTINGS.packages/rpc/src/settings.ts— exposes the new methods on the generated RPC API.Main (Electron)
apps/desktop/src/main/ipc/settings-handlers.ts— registers + tears down the two handlers using existingreadGroupSettings/writeGroupSettingshelpers with key'calendar'.Renderer
apps/desktop/src/renderer/src/hooks/use-calendar-preferences.ts— new hook + pureresolveDayCellClickBehavior(settings, isCalendarTabActive)helper.apps/desktop/src/renderer/src/hooks/use-calendar-preferences.test.ts— 7 unit tests covering the full truth table (global × override × tab-active).apps/desktop/src/renderer/src/pages/settings/calendar-section.tsx— new settings UI (twoSelectrows).apps/desktop/src/renderer/src/pages/settings.tsx— addsCalendarnav entry (uses existingCalendarDaysicon).apps/desktop/src/renderer/src/contexts/settings-modal-context.tsx— extendsSettingsSectionunion with'calendar'.apps/desktop/src/renderer/src/components/day-panel/global-day-panel.tsx— queries the visible month viauseCalendarRange, swaps activity source based onisCalendarTabActive, and routes clicks + today through the resolver. Opens a new Calendar tab when needed.Tests
apps/desktop/tests/setup-dom.ts— addsgetCalendarSettings/setCalendarSettingsto thewindow.api.settingsmock so existing tests that touch the Day Panel keep working.Generated-file churn (flagging for reviewer)
apps/desktop/src/main/ipc/generated-ipc-invoke-map.tsandapps/desktop/src/preload/generated-rpc.tshave a ~3100-line drop that is not my hand edit. Runningpnpm ipc:generateproduced a different format than what was stored in the repo, suggesting pre-existing drift between the committed files and the current generator output.pnpm ipc:checkpasses after regeneration. Happy to revert if there's a preferred CI path (e.g., regenerate in a follow-up) — flagging so it isn't a surprise in review.Test plan
pnpm typecheck:node+pnpm typecheck:web— both clean.pnpm ipc:check— up to date.pnpm exec vitest run— 7139 pass. The 3 failures incalendar-page.test.tsxare pre-existing (window.api.showContextMenu is not a function— unrelated to this PR).pnpm dev):journalin Settings → click day on Calendar tab opens Journal.calendar→ click day from Notes tab opens a Calendar tab.onSettingsChangedbroadcast).right-sidebar-event-dots.spec.ts,sidebar-day-click-behavior.spec.ts). Not included here to keep this PR focused; remembernpx electron-vite buildbeforepnpm test:e2eper CLAUDE.md.Open design question
Event dots and journal dots currently share the
ACTIVITY_DOT_COLORSramp (green-family, quantized 0–4). Consider adding a distinct ramp (e.g., tint/blue) for events so the swap is visually obvious. Trivial to add adotColorVariantprop onDatePickerCalendarif desired.