feat(web): keyboard-education — onboarding, connect/trial CTAs, shortcut tips - #2736
Merged
Merged
Conversation
Adds four new lessons (move focus, edit-sequence jump, Shift-tap targeting, Shift+Arrow nudge, undo) behind a basics/advanced fork so new users get the required-feeling basics and can opt into extra credit without ever being held hostage. Also fixes a bug where any welcome-modal exit into signup permanently burned the tour-seen flag; it's now offered once right after signup completes. Widens the PostHog ProductEvent union and instruments the tour end to end. Keyboard-only mouse-disable and ephemeral synthetic sandbox events are deferred to a fast-follow (see keyboard-education/01 brief) since they touch shared query/interaction code that deserves its own pass.
Once the onboarding tour ends (finish or skip), anonymous users now see a skippable "Connect Google Calendar" CTA (import runs in the background) followed by a "ready to try it for real?" trial CTA. Skipping connect goes straight to the trial step. Stage is persisted across the Google OAuth full-page redirect. Billing does not exist yet, so accepting the trial CTA opens signup for anonymous users and is a no-op stub for authenticated ones until the checkout brief lands.
Rotates a single-line tip (edit-sequence, nudge, targeting, edge cycle) into the sidebar's status strip when an event is focused with no form open, at lowest priority behind keyboard-only/event-jump/ edge-focus/sync-status. Capped to one rotation per 45s regardless of focus churn, biased toward the edit-sequence tip after 3 consecutive mouse-driven edits, muted permanently on click, and tracked via the tour's shortcut_tip_shown/acted_on events.
5 tasks
Palette label test still asserted "Restart onboarding tour" after the rename to "Practice shortcuts". The interactive-tour e2e happy path only exercised the original 5 steps; walks the new moveFocus/ editSequence steps and the fork's "I'm done" exit now.
With only one event on the calendar, ArrowRight (no adjacent target) doesn't reliably leave DOM focus on it. Mirrors the existing pattern in e2e/timed/edit-sequence-title.spec.ts.
PostOnboardingFlow rendered purely off the persisted stage, with no authenticated check: a user who reached "connect"/"trial" anonymously and then logged in by any path other than the Connect Google button (email/password, Google auth elsewhere) would still see the CTA on their next load, since nothing reset the stale localStorage stage. Fixes it two ways: PostOnboardingFlow now gates its own render on authenticated (defense in depth), and usePostOnboardingFlowTrigger resolves a stale connect/trial stage to done the moment authenticated flips true, so it can never resurface later either. Found via independent review before merge.
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
Brief 01 — extended onboarding tour
ProductEventunion and instruments tour start/task-completed/segment-reached/skip/finish/replay end to end.Brief 02 — connect-Google and trial CTAs
keyboard-education/03), so accepting the trial CTA opens signup for anonymous users; for an already-authenticated user (arrived via Connect Google, which signs up on its own) it's a stub no-op until checkout ships.Brief 04 — quiet shortcut tips in the sidebar
CALENDAR_VIEW_INTERACTION_ID_ATTRIBUTESselector the app already uses for view-agnostic event lookups, so it works across Day/Week without importing either view's internals.activitydiscriminator), muted permanently on click, and tracked viashortcut_tip_shown/shortcut_tip_acted_on.All three briefs are part of the
keyboard-educationproject spec (compass-calendar-internal/projects/keyboard-education/). Mouse-disable-during-practice and ephemeral, non-persisted synthetic sandbox events (the full "game" framing from brief 01) are intentionally deferred to brief 06 — they touch shared query/interaction code that deserves its own focused review rather than riding along here.Known limitations
savestep — pressing the key counts without verifying the resulting action landed, and unlike the app's real detectors they don't check for an editable-input target. Not a functional bug, just a pedagogy/tracking-accuracy gap worth tightening later.Test plan
bun test src/components/OnboardingTour/— 20/20 passingbun test src/components/PostOnboardingFlow/— 4/4 passingbun test src/shortcuts/tips/ src/components/Sidebar/SidebarStatusBar.test.tsx— 21/21 passingbun run type-check— cleanbiome checkon all touched files — cleanbunx knip— no new unused exports introducedSYNC_SERVICE_URL/SYNC_INTERNAL_AUTH_TOKENenv vars not present here (pre-existing environment gap, unrelated to this change)🤖 Generated with Claude Code