Files
HealthLog/src/lib/onboarding
Marc-André BombeckandClaude Opus 4.7 e57fc0a8da feat(onboarding): tour component with spotlight + keyboard navigation
v1.4.15 Phase B5 — second commit. Adds the spotlight-tour overlay
that walks new users through 5 dashboard features after they finish
the wizard at /onboarding:

  1. Tile strip            (BP / weight / pulse / mood)
  2. Quick-add menu
  3. Insights              (AI-assisted summaries)
  4. Settings → Integrations
  5. Achievements          (omittable via prop if B4 hasn't shipped)

Architecture:

  - `src/lib/onboarding/tour-state.ts` — pure state machine. Steps,
    navigation helpers (`nextStep`, `prevStep`, `skipTour`),
    completion outcome (`"completed" | "skipped"`). DOM-free so the
    Node-environment vitest setup can exercise it directly. 13 unit
    tests cover step list, navigation, idempotency once finished,
    and the 1-based step counter.

  - `src/components/onboarding/tour.tsx` — UI layer. In-house
    spotlight (no new dependency — package.json had no
    react-joyride / intro.js / shepherd already, and the surface
    area didn't justify a 30 KB add). Renders a fixed full-viewport
    overlay with a polygon `clip-path` cutout aligned to the live
    target, plus a tooltip card next to it. Targets are looked up
    via the stable `data-tour-id` attribute (NOT class names — the
    contract has to survive Tailwind churn). Re-measures on resize
    and scroll. Falls back to a centred-screen tooltip if the
    target is not in the DOM (mobile breakpoint, conditional
    render) so the tour never blocks indefinitely.

  - i18n: 19 new keys under `onboarding.tour.*` (EN + DE), one
    title + body per stop plus `next`/`back`/`skip`/`done`/
    `restart`/`stepOf` strings. The component test asserts the
    German strings resolve end-to-end via `<I18nProvider initialLocale="de">`.

Accessibility:

  - `role="dialog"` + `aria-modal="true"` + `aria-labelledby`,
    polite live region announces step transitions, focus moves to
    the primary action on every step.
  - Keyboard: Esc = skip, ArrowRight / Enter = next, ArrowLeft =
    back. Inputs / textareas / contenteditable nodes are
    explicitly NOT hijacked (defensive against future tour content
    that might embed an input).
  - `prefers-reduced-motion` disables the backdrop fade.

Tests: 917 / 917 unit pass (was 890 — +27 across 2 new files).
Lint clean (13 pre-existing warnings unchanged). Typecheck clean
for B5 files; dashboard-layout / sibling-agent typecheck issues
are pre-existing and out of scope.

The component is "dumb" — it takes `onClose(outcome)` and lets the
caller persist the flag. The launcher wiring lands in the next
commit (B5-3) so this commit is small and orthogonal.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 21:19:18 +02:00
..