Files
suaveplan/openspec/changes/enterprise-react-wizard/tasks.md
2026-05-27 23:29:53 +01:00

4.1 KiB

Tasks: enterprise-react-wizard

Change ID: enterprise-react-wizard Package: @suaveplan/react-wizard Target path: react/forms/react-wizard Prerequisite packages on Verdaccio: @suaveplan/error, @suaveplan/react-translate


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 layout.
  • Write package.json at 0.1.0 with "sideEffects": false, exports map.
  • Dependencies: @suaveplan/error workspace:^, @suaveplan/react-translate workspace:^, zod catalog:forms, @opentelemetry/api catalog:observability, tslib catalog:build.
  • Write tsconfig.json, vitest.config.ts, scripts.

2. Error codes and types

  • Define WizardError extending SuaveplanError; codes: WIZARD_CONTEXT_MISSING, WIZARD_GUARD_FAILED, WIZARD_STEP_NOT_FOUND.
  • Define all public types: StepStatus, ProgressVariant, StepGuard, StepValidator, StepValidation, WizardContextValue, WizardDataContextValue.

3. Guards

  • Implement runGuard(guard: StepGuard, data: unknown): Promise<StepValidation> — calls guard, catches errors and wraps in WizardError(WIZARD_GUARD_FAILED).
  • Implement combineGuards(...guards): StepGuard — runs sequentially; first failure stops the chain.
  • Write step-guard.test.ts: passing guard, failing guard, combined guards short-circuit. { timeout: 10000 }.
  • Write step-guard.md.

4. WizardContext + WizardProvider

  • Manages currentStep, totalSteps, stepStatuses: Record<number, StepStatus>, goNext(), goPrevious(), goTo(index), validateCurrent().
  • useWizard() throws WizardError(WIZARD_CONTEXT_MISSING) outside provider.
  • OTel wizard.step_complete span emitted in goNext() on validation success; attributes wizard.step_index, wizard.total_steps.
  • Write test + md.

5. WizardDataContext

  • Manages cross-step data bag; useWizardData() returns { data, setData, mergeData, getData }.
  • Write test + stories (playground for useWizardData) + md.

6. Components

Wizard

  • Top-level orchestrator; collects WizardStep children via React traversal; renders current step.
  • Write test, stories (linear-3-step, with-guard, playground), md.

WizardStep

  • Step boundary: accepts label, validator?, guard?; registers with WizardContext.
  • Throws WizardError(WIZARD_STEP_NOT_FOUND) if used outside Wizard.
  • Write test, stories, md.

WizardBranch

  • Conditional step rendering based on a condition(data): boolean prop.
  • Write test, stories (conditional-path demo), md.

WizardProgress

  • Progress bar/stepper variants (ProgressVariant: bar, dots, steps).
  • Uses useTranslation for step labels.
  • Write test, stories (all-variants), md.

7. useWizard hook

  • Returns { currentStep, totalSteps, stepStatus, goNext, goPrevious, goTo, validateCurrent, isFirstStep, isLastStep }.
  • Write test, stories (playground), md.

8. E2E

  • e2e/wizard.spec.ts — Playwright: render 3-step wizard, fill step 1, click Next (validates), fill step 2 with invalid data (validation error shown), fix and click Next, fill step 3, complete → onComplete called.

9. Verify and publish

  • bunx turbo lint typecheck test --filter=@suaveplan/react-wizard — green.
  • bunx turbo test:coverage --filter=@suaveplan/react-wizard — 100%.
  • bun scripts/publish.ts --package @suaveplan/react-wizard.
  • Archive change folder.