Files
2026-05-27 23:29:53 +01:00

5.7 KiB

Tasks: enterprise-browser-react-tour

Change ID: enterprise-browser-react-tour Package: @suaveplan/react-tour Target path: browser/react/react-tour Prerequisite packages on Verdaccio: @suaveplan/error, @suaveplan/events, @suaveplan/logger, @suaveplan/schema-registry


0. Pre-flight (non-negotiable)

  • 0.1 Confirm clean working tree (git status reports nothing) and no in-flight worktrees with uncommitted work (git worktree list then git status in each)
  • 0.2 If any worktrees exist under .claude/worktrees/, account for each one: still-active agent, work-pending-merge, or stale-and-prune. Stale worktrees MUST be removed (git worktree remove) before opening a new one — code that has been lost twice on main is the failure mode this guards against.
  • 0.3 Confirm the package set in MANIFEST.md matches find packages -maxdepth 3 -name package.json count. Drift here means a prior change archived without regenerating the manifest.

1. Scaffold

  • Create directory tree per proposal.md.
  • package.json v0.0.0, "sideEffects": false.
    • dependencies: @suaveplan/error workspace:^, @suaveplan/events workspace:^, @suaveplan/logger workspace:^, @suaveplan/schema-registry workspace:^, zod catalog:forms, @opentelemetry/api catalog:observability, tslib catalog:build, react catalog:react
    • peerDependencies: react
    • devDependencies: vitest catalog:testing, @vitest/coverage-istanbul catalog:testing, happy-dom catalog:testing, @testing-library/react catalog:testing, @suaveplan/testing workspace:^, @suaveplan/testing-dom workspace:^
    • Subpath exports: ".", "./core/tour/tour", "./utils/positioning", "./persistence"
  • tsconfig.json, vitest.config.ts (pool: forks, happy-dom environment).

2. Error codes

  • TOUR_CONFIG_INVALID, TOUR_STEP_NOT_FOUND.
  • registerTourErrorCodes() — call eagerly.

3. Types (src/types/common.ts)

  • TourConfig, TourStep, TourState, TourActions, TooltipPlacement, TooltipPosition, SpotlightInset.
  • Write common.md.

4. TourSchema (src/schema/tour-schema/)

  • tour-schema.ts — TourConfigSchema, TourStepSchema (Zod); registerTourSchemas().
  • Write tour-schema.md.

5. Positioning utilities (src/utils/positioning/)

  • positioning.ts — calculateSpotlightInset, calculateTooltipPosition, getTargetRect, scrollTargetIntoView.
  • All functions SSR-safe (typeof document guard).
  • Write positioning.test.ts (happy-dom geometry, SSR import smoke test). Write positioning.md.

6. Observer utility (src/utils/observe-target/)

  • observe-target.ts — composite observeTarget(selector, callback) using ResizeObserver + IntersectionObserver + scroll listener; returns cleanup.
  • Write observe-target.test.ts (observer fires on resize, fires on scroll). Write observe-target.md.

7. Persistence adapters (src/persistence/persistence/)

  • persistence.ts — PersistenceAdapter interface; LocalStoragePersistence (SSR-safe), SessionStoragePersistence, MemoryPersistence.
  • Write persistence.test.ts (each adapter: isCompleted, markCompleted, clear, SSR no-throw). Write persistence.md.

8. Tour state helpers (src/core/tour/tour-state.ts)

  • computeProgress(step, total): number, boundary guards, shouldSkip evaluation.

9. Tour effects (src/core/tour/tour-effects.ts)

  • Observer wiring: call observeTarget on step change, update targetRect on callback.
  • Emit @suaveplan/events lifecycle events (tour:start, tour:step-change, tour:complete, tour:skip, tour:error).
  • Wire OTel metrics.

10. Tour actions (src/core/tour/tour-actions.ts)

  • next(), prev(), goTo(n), skip(), reset() — with boundary checks and shouldSkip evaluation.

11. useTour hook (src/core/tour/tour.ts)

  • Compose state + effects + actions.
  • Validate TourConfig via TourConfigSchema on entry; throw TOUR_CONFIG_INVALID.
  • Log storage errors via @suaveplan/logger instead of swallowing.
  • Write tour.test.ts (config validation, next/prev/goTo/skip, persistence, SSR no-throw). Write tour.md.

12. Storybook stories (src/stories/use-tour.stories.tsx)

  • Default story: basic 3-step tour.
  • Spotlight overlay: CSS spotlight with calculateSpotlightInset.
  • Scroll-into-view: target below the fold.
  • Completion persistence: reload and confirm tour does not restart.
  • Accessibility-compliant tooltip: role="dialog", focus trap, aria-live.

13. Integration test (tests/integration.test.ts)

  • Full tour flow: start, navigate, complete, verify persistence adapter called.
  • MemoryPersistence swap: no localStorage touched.
  • shouldSkip step evaluated; step skipped automatically.

14. Playwright E2E (e2e/react-tour.spec.ts)

  • targetRect stays aligned after element resizes (Playwright + Chromium).
  • Completion persists across reload (Playwright localStorage).
  • SSR smoke: import from Node without throwing.

15. Docs + verify

  • Write .md per module (≥200 words, API reference, examples).
  • Write README.md with subpath table, persistence-adapter guide, SSR guide, a11y notes.
  • bunx turbo lint typecheck test --filter=@suaveplan/react-tour — green.
  • bunx turbo test:coverage — 100%.
  • No @ts-expect-error in src/ or tests. No vi.stubGlobal.
  • Storybook stories render and pass axe-core.
  • Playwright E2E green on Chromium.
  • bun scripts/publish.ts --package @suaveplan/react-tour.
  • Archive to openspec/archive/2026-04-24-enterprise-browser-react-tour/.