docs(11-02): complete step animation and scroll-to-error plan
- Create 11-02-SUMMARY.md documenting POLISH-03 and POLISH-04 completion - Update STATE.md: phase 11 complete, 100% progress, new decisions added - Update ROADMAP.md: phase 11 plan progress (2/2 complete) - Update REQUIREMENTS.md: mark POLISH-03 and POLISH-04 complete
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
---
|
||||
phase: 11-polish-responsiveness
|
||||
plan: 02
|
||||
subsystem: ui
|
||||
tags: [react, tailwind, css-animation, react-hook-form, accessibility, reduced-motion]
|
||||
|
||||
# Dependency graph
|
||||
requires:
|
||||
- phase: 11-01
|
||||
provides: focus rings and BackendCard hover states (polish foundation)
|
||||
- phase: 10-content-clarity
|
||||
provides: App.tsx WizardShell structure with step content wrapper
|
||||
provides:
|
||||
- CSS @keyframes step-in animation with 200ms ease-out fade/slide-up on step change
|
||||
- prefers-reduced-motion guard disabling animation for accessibility
|
||||
- Auto-scroll to first errored field on validation failure in BackendSelectionStep and RemoteConfigStep
|
||||
affects: [11-03, any future plan modifying App.tsx WizardShell or wizard form steps]
|
||||
|
||||
# Tech tracking
|
||||
tech-stack:
|
||||
added: []
|
||||
patterns:
|
||||
- "key={state.currentStep} on step wrapper forces React remount, triggering CSS animation from initial state"
|
||||
- "@theme --animate-step-in token pattern for Tailwind v4 custom animation utility"
|
||||
- "onInvalidSubmit second arg to handleSubmit for scroll-to-error without JS media query listener"
|
||||
- "document.getElementById(firstKey)?.scrollIntoView for registry-driven field error targeting"
|
||||
|
||||
key-files:
|
||||
created: []
|
||||
modified:
|
||||
- src/index.css
|
||||
- src/App.tsx
|
||||
- src/components/wizard/BackendSelectionStep.tsx
|
||||
- src/components/wizard/BackendSelectionStep.test.tsx
|
||||
- src/components/wizard/RemoteConfigStep.tsx
|
||||
- src/components/wizard/RemoteConfigStep.test.tsx
|
||||
|
||||
key-decisions:
|
||||
- "CSS-only reduced-motion guard via @media (prefers-reduced-motion: reduce) — no JS listener needed"
|
||||
- "key={state.currentStep} on step wrapper (not on step components themselves) to trigger animation"
|
||||
- "onInvalidSubmit hardcodes getElementById('remote-name') in BackendSelectionStep — only one validatable field exists"
|
||||
- "FieldErrors type added to react-hook-form imports in RemoteConfigStep for typed errors param"
|
||||
|
||||
patterns-established:
|
||||
- "Tailwind v4 custom animation: register --animate-X in @theme, define @keyframes, add reduced-motion guard"
|
||||
- "react-hook-form scroll-to-error: pass onInvalidSubmit as second arg to handleSubmit"
|
||||
|
||||
requirements-completed: [POLISH-03, POLISH-04]
|
||||
|
||||
# Metrics
|
||||
duration: 3min
|
||||
completed: 2026-04-01
|
||||
---
|
||||
|
||||
# Phase 11 Plan 02: Polish & Responsiveness — Animation & Scroll-to-Error Summary
|
||||
|
||||
**CSS step-in animation (200ms fade/slide-up) with reduced-motion guard, plus auto-scroll to first errored form field via react-hook-form onInvalidSubmit handler**
|
||||
|
||||
## Performance
|
||||
|
||||
- **Duration:** 3 min
|
||||
- **Started:** 2026-04-01T11:28:03Z
|
||||
- **Completed:** 2026-04-01T11:31:00Z
|
||||
- **Tasks:** 2 (Task 2 used TDD: RED → GREEN)
|
||||
- **Files modified:** 6
|
||||
|
||||
## Accomplishments
|
||||
- Wizard step transitions now play a 200ms opacity/translateY(8px) fade-slide animation on step change
|
||||
- Users with `prefers-reduced-motion` enabled see zero animation (declarative CSS guard, no JS)
|
||||
- BackendSelectionStep scrolls to `remote-name` input when form submitted with invalid/empty name
|
||||
- RemoteConfigStep scrolls to the first errored field (by key) when form submitted with missing required fields
|
||||
- Both scroll behaviors verified by unit tests with `vi.fn()` mock on `Element.prototype.scrollIntoView`
|
||||
- Full test suite: 204 tests pass, 0 failures, 0 regressions
|
||||
|
||||
## Task Commits
|
||||
|
||||
Each task was committed atomically:
|
||||
|
||||
1. **Task 1: Step transition animation with reduced-motion guard** - `9af58bc` (feat)
|
||||
2. **Task 2 RED: Failing tests for auto-scroll to first error** - `8b7daa8` (test)
|
||||
3. **Task 2 GREEN: Auto-scroll to first errored field implementation** - `90cdeda` (feat)
|
||||
|
||||
**Plan metadata:** (docs commit follows)
|
||||
|
||||
_Note: Task 2 used TDD — separate test commit (RED) then implementation commit (GREEN)._
|
||||
|
||||
## Files Created/Modified
|
||||
- `src/index.css` - Added `--animate-step-in` token in `@theme`, `@keyframes step-in`, and `@media prefers-reduced-motion: reduce` guard
|
||||
- `src/App.tsx` - Step content wrapper: added `key={state.currentStep}` and `animate-step-in` class
|
||||
- `src/components/wizard/BackendSelectionStep.tsx` - Added `onInvalidSubmit` scrolling to `remote-name`, wired to form `onSubmit` and `handleCardClick`
|
||||
- `src/components/wizard/BackendSelectionStep.test.tsx` - Added `scrollIntoView` mock in `beforeEach`, added POLISH-04 scroll test
|
||||
- `src/components/wizard/RemoteConfigStep.tsx` - Added `FieldErrors` import, `onInvalidSubmit` scrolling to first error key, wired to form `onSubmit`
|
||||
- `src/components/wizard/RemoteConfigStep.test.tsx` - Added `scrollIntoView` mock in `beforeEach`, added POLISH-04 scroll test
|
||||
|
||||
## Decisions Made
|
||||
- CSS-only reduced-motion guard via `@media (prefers-reduced-motion: reduce)` — consistent with existing `prefers-reduced-motion: no-preference` pattern at line 45 of index.css. No JS listener.
|
||||
- `key={state.currentStep}` on the step content wrapper div (not on step components themselves) — forces React to unmount/remount the wrapper, reliably triggering the CSS animation from its `from` state on every step change.
|
||||
- BackendSelectionStep `onInvalidSubmit` uses `getElementById('remote-name')` directly (hardcoded) — only one validatable field exists in that step, no dynamic key needed.
|
||||
- Added `FieldErrors` to react-hook-form imports in RemoteConfigStep (alongside existing `FieldError`) for typed `errors` parameter in `onInvalidSubmit`.
|
||||
|
||||
## Deviations from Plan
|
||||
|
||||
None - plan executed exactly as written.
|
||||
|
||||
## Issues Encountered
|
||||
|
||||
None.
|
||||
|
||||
## User Setup Required
|
||||
|
||||
None - no external service configuration required.
|
||||
|
||||
## Next Phase Readiness
|
||||
- POLISH-03 (step animation) and POLISH-04 (scroll-to-error) are complete
|
||||
- Phase 11 plan 02 satisfies all must_haves and success criteria
|
||||
- Ready for plan 11-03 if it exists, or phase 11 completion
|
||||
|
||||
---
|
||||
*Phase: 11-polish-responsiveness*
|
||||
*Completed: 2026-04-01*
|
||||
Reference in New Issue
Block a user