diff --git a/.planning/REQUIREMENTS.md b/.planning/REQUIREMENTS.md index b52c14e..6cf7e85 100644 --- a/.planning/REQUIREMENTS.md +++ b/.planning/REQUIREMENTS.md @@ -28,8 +28,8 @@ - [x] **POLISH-01**: Wizard layout adapts to mobile screens — backend cards stack, form fields go full-width, step indicator collapses, buttons stretch - [x] **POLISH-02**: All interactive elements have visible MD3 focus indicators (3px outline) using `focus-visible` for keyboard navigation -- [ ] **POLISH-03**: Step transitions use subtle fade/slide animation that respects `prefers-reduced-motion` -- [ ] **POLISH-04**: On validation failure, the view auto-scrolls to the first errored field +- [x] **POLISH-03**: Step transitions use subtle fade/slide animation that respects `prefers-reduced-motion` +- [x] **POLISH-04**: On validation failure, the view auto-scrolls to the first errored field ### Tech Debt @@ -69,8 +69,8 @@ | UX-04 | Phase 10 | Complete | | POLISH-01 | Phase 11 | Complete | | POLISH-02 | Phase 11 | Complete | -| POLISH-03 | Phase 11 | Pending | -| POLISH-04 | Phase 11 | Pending | +| POLISH-03 | Phase 11 | Complete | +| POLISH-04 | Phase 11 | Complete | **Coverage:** - v1.2 requirements: 15 total diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index 8495dc2..dfd2c8c 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -38,7 +38,7 @@ Full phase details: [.planning/milestones/v1.1-ROADMAP.md](milestones/v1.1-ROADM - [x] **Phase 8: Theme Foundation** - MD3 color token system and dark mode infrastructure (completed 2026-04-01) - [x] **Phase 9: MD3 Components** - UI primitives and component migration to semantic tokens (completed 2026-04-01) - [x] **Phase 10: Content & Clarity** - Intro section, step descriptions, and contextual help (completed 2026-04-01) -- [ ] **Phase 11: Polish & Responsiveness** - Mobile layout, focus states, transitions, scroll-to-error +- [x] **Phase 11: Polish & Responsiveness** - Mobile layout, focus states, transitions, scroll-to-error (completed 2026-04-01) ## Phase Details @@ -98,7 +98,7 @@ Plans: 2. Every interactive element shows a visible 3px MD3 focus outline when navigated via keyboard (using `focus-visible`) 3. Step transitions use a subtle fade/slide animation that is suppressed when the user has `prefers-reduced-motion` enabled 4. When form validation fails, the view auto-scrolls to the first field with an error -**Plans:** 1/2 plans executed +**Plans:** 2/2 plans complete Plans: - [ ] 11-01-PLAN.md — Mobile responsive layout + MD3 focus-visible indicators - [ ] 11-02-PLAN.md — Step transition animation + auto-scroll to first error @@ -117,4 +117,4 @@ Plans: | 8. Theme Foundation | v1.2 | 2/2 | Complete | 2026-04-01 | | 9. MD3 Components | v1.2 | 5/5 | Complete | 2026-04-01 | | 10. Content & Clarity | v1.2 | 3/3 | Complete | 2026-04-01 | -| 11. Polish & Responsiveness | 1/2 | In Progress| | - | +| 11. Polish & Responsiveness | 2/2 | Complete | 2026-04-01 | - | diff --git a/.planning/STATE.md b/.planning/STATE.md index 6ff31d3..8aea3fd 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -3,15 +3,15 @@ gsd_state_version: 1.0 milestone: v1.2 milestone_name: UI Polish & Clarity status: completed -stopped_at: Completed 11-01-PLAN.md -last_updated: "2026-04-01T11:26:15.869Z" -last_activity: 2026-04-01 — Phase 11 plan 01 complete (POLISH-01, POLISH-02 satisfied) +stopped_at: Completed 11-02-PLAN.md +last_updated: "2026-04-01T11:32:08.129Z" +last_activity: 2026-04-01 — Phase 11 plan 02 complete (POLISH-03, POLISH-04 satisfied) progress: total_phases: 4 - completed_phases: 3 + completed_phases: 4 total_plans: 12 - completed_plans: 11 - percent: 98 + completed_plans: 12 + percent: 100 --- # Project State @@ -25,12 +25,12 @@ See: .planning/PROJECT.md (updated 2026-03-31) ## Current Position -Phase: 11 of 11 (Polish & Responsiveness) — In Progress -Plan: 11-01 (complete) -Status: Phase 11 in progress, plan 11-01 complete (POLISH-01, POLISH-02 satisfied) -Last activity: 2026-04-01 — Phase 11 plan 01 complete (POLISH-01, POLISH-02 satisfied) +Phase: 11 of 11 (Polish & Responsiveness) — Complete +Plan: 11-02 (complete) +Status: Phase 11 complete — all plans done (POLISH-01, POLISH-02, POLISH-03, POLISH-04 satisfied) +Last activity: 2026-04-01 — Phase 11 plan 02 complete (POLISH-03, POLISH-04 satisfied) -Progress: [██████████] 98% (v1.2) +Progress: [██████████] 100% (v1.2) ## Accumulated Context @@ -67,6 +67,8 @@ Recent decisions affecting current work: - [Phase 11-polish-responsiveness]: ring-inset on ThemeToggle focus ring because overflow-hidden on container clips outset rings - [Phase 11-polish-responsiveness]: No ring-offset-2 on BackendCard to avoid dark mode surface color issues - [Phase 11-polish-responsiveness]: FieldRenderer select uses focus-visible:ring-2 (not focus:ring-2) for keyboard-only ring on selects +- [Phase 11-polish-responsiveness]: CSS-only reduced-motion guard via @media (prefers-reduced-motion: reduce) — no JS listener needed +- [Phase 11-polish-responsiveness]: key={state.currentStep} on step wrapper forces React remount triggering CSS animation from initial state ### Pending Todos @@ -78,6 +80,6 @@ None yet. ## Session Continuity -Last session: 2026-04-01T11:26:10.100Z -Stopped at: Completed 11-01-PLAN.md +Last session: 2026-04-01T11:32:08.126Z +Stopped at: Completed 11-02-PLAN.md Resume file: None diff --git a/.planning/phases/11-polish-responsiveness/11-02-SUMMARY.md b/.planning/phases/11-polish-responsiveness/11-02-SUMMARY.md new file mode 100644 index 0000000..d536e5b --- /dev/null +++ b/.planning/phases/11-polish-responsiveness/11-02-SUMMARY.md @@ -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*