feat: light, extensible first-run onboarding coachmarks (0206) - #209
Merged
Conversation
Light, non-blocking, one-at-a-time tips shown the first time you open a view. Declarative, plugin-extensible tip registry; 'seen' state persisted in the workbench store; rail anchors; Settings → Replay onboarding. - apps/web/src/coachmarks/: registry, useCoachmarks engine, Coachmark (non-modal portal + Presence motion), useAnchorEl, view mapping, seeds - workbench store: seenTips + markTipSeen/resetTips (twin of lastSeenChangelogId) - Rail: data-coach anchors; Workbench mounts CoachmarkLayer (desktop+mobile) - Settings: 'Tips & tours' replay control - 19 tests (registry, views, engine serialization/cap, component dismiss) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…0206) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Contributor
🖼️ UI changes in this PRComponentsScreensAuto-captured by CI · run. Informational — not a blocking check. |
Contributor
|
Preview removed for PR #209. |
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.





What
Light, lovely, non-blocking first-run onboarding — a few contextual tips that appear the first time you open a view, dismissible and never in the way. Implements exploration 0206.
Not a product tour. The research is lopsided (~70% skip linear tours; ~78% abandon by step three), so this is the modern coachmark pattern: one tip at a time, on first visit to a surface, Escape/✕/"Got it" to dismiss, replayable from Settings.
How it works
A declarative, plugin-extensible tip registry keyed by view. The "seen" set is persisted in the existing workbench store (
xnet:workbench:v1) — the engine is a structural twin of the shipped What's-New plumbing. Zero new runtime dependencies (builds on the Base-UIPresencemotion vocabulary +lucide-react+react-dom, all already present).The "grow with us" property: a feature or bundled plugin registers tips with
contributeTips([...])— the engine never changes. As the app pluginizes (0205), features bring their own onboarding.Design choices
CommentPopoverpattern), so the user's first action is never hijacked.hasOnboarded()— never piles on top of the welcome/auth flow.motion.css(no Framer Motion).Changes
apps/web/src/coachmarks/— registry,useCoachmarksengine,Coachmark(+ story),useAnchorEl, view mapping,CoachmarkLayer, seed tipsseenTips+markTipSeen/resetTipsdata-coachanchors; Workbench mountsCoachmarkLayer(desktop + mobile)docs/ONBOARDING.md(how to add a tip) + changelog fragmentSeed tips
Command palette (⌘K) on Home, plus CRM, Tasks, and Discover — each anchored to its Rail icon.
Verification
apps/webdom suite green (144 tests); full repo suite green (8840 passed).Coachmarkin Storybook (renders, positions to anchor, "Got it" dismisses end-to-end); app boots with no console errors. (The passkey gate can't be passed headlessly, so per-view in-app confirmation is via Storybook + unit tests.)🤖 Generated with Claude Code