Initial Commit
This commit is contained in:
136
openspec/changes/enterprise-browser-react-tour/tasks.md
Normal file
136
openspec/changes/enterprise-browser-react-tour/tasks.md
Normal file
@@ -0,0 +1,136 @@
|
||||
# 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/`.
|
||||
Reference in New Issue
Block a user