Files
kandev/docs/plans/compact-workflow-step-navigation/plan.md
T
2026-08-26 13:11:37 +00:00

122 lines
6.9 KiB
Markdown

---
created: 2026-08-26
status: complete
requirements:
- REQ-UI-COMPACT-WORKFLOW-STEP-NAVIGATION-001
system_design:
- ../../specs/ui/system-design/compact-workflow-step-navigation.md
legacy_specs: []
---
# Implementation Plan: Compact Workflow Step Navigation
## Overview
Add an interactive disclosure to the compact task top-bar stepper. Reuse the existing movement policy and task-move callback.
Implement the component behavior and its browser proof in one vertical work order. This order keeps the responsive contract and movement result in one TDD cycle.
## Scope
### In scope
- Make the compact stepper a semantic and accessible trigger for active tasks.
- Show every workflow step in workflow order from the compact presentation.
- Permit moves only to targets that the full stepper already permits.
- Use an interactive Popover for fine pointers and an inset drawer for coarse pointers. The fine-pointer trigger and dialog expose matching ARIA semantics, and the move buttons remain keyboard tabbable.
- Give the coarse-pointer trigger a 44px hit area and visible disclosure cue.
- Preserve the existing phone movement path and full-stepper behavior.
- Cover the compact desktop and tablet paths with component and E2E tests.
### Out of scope
- Backend task-move changes.
- Cross-workflow movement from the compact stepper.
- A new phone top-bar control.
- New move notifications or error copy.
- Public documentation changes.
## Technical approach
### Stepper model and disclosure
Update `apps/web/components/task/workflow-stepper.tsx`. Keep `WorkflowStepper` as the owner of sorted steps, the current index, and move state.
Replace the static active-task branch in `MinimalWorkflowStepper` with a disclosure trigger. Keep the archived branch static.
Extract one disclosure body that renders each step from a shared row model. The model uses `canMoveToStep` for every target.
Reuse `StepCircleIndicator`, `task:currentStep`, `task:moveHere`, `task:moving`, and `task:stepOf`. Do not add untranslated copy.
Use `useTouchDrawer` to select the surface. Fine pointers use a controlled `Popover` with hover and focus behavior, dialog semantics, keyboard focus handling, and compact desktop-sized movement buttons. Coarse pointers use `Drawer` with internal overflow, safe-area padding, a 44px trigger hit area, 44px action hit areas, and a visible disclosure cue. Apply touch sizing only through coarse-pointer styles.
Keep the move request in `handleMove`. Return its success result so the temporary surface closes only after a successful request.
### Component tests
Extend `apps/web/components/task/workflow-stepper.test.tsx`. Mock width collapse and pointer mode independently.
Add tests for these results:
- fine-pointer hover or focus shows all ordered steps
- eligible targets show movement controls and the current step does not
- selection calls `moveTask` with the existing payload
- coarse-pointer activation opens the drawer with the same targets
- archived compact state stays static
- expanded mode does not mount the compact disclosure
### Browser tests
Add `apps/web/e2e/tests/layout/task-topbar-workflow-stepper.spec.ts`. Use a long task title and a 900px viewport to force the measured compact state.
The desktop scenario hovers and focuses the compact trigger, verifies the Popover dialog semantics, tabs to a step-specific move button, activates it with Enter, and polls the task API for the new step.
The tablet scenario uses `tabletTestPage`. It verifies the trigger hit area, opens the touch drawer, checks viewport containment, selects a target, and polls the same API result.
Keep `apps/web/e2e/tests/task/mobile-sidebar-task-actions.spec.ts` unchanged. Its current Pixel 5 move scenario remains the phone parity proof.
## Tests
| Acceptance criterion | Evidence |
| ---------------------------------------------- | ------------------------------------------------------------- |
| `AC-UI-COMPACT-WORKFLOW-STEP-NAVIGATION-001.1` | Compact component test and desktop E2E trigger assertion |
| `AC-UI-COMPACT-WORKFLOW-STEP-NAVIGATION-001.2` | Fine-pointer component test and desktop Popover E2E |
| `AC-UI-COMPACT-WORKFLOW-STEP-NAVIGATION-001.3` | Touch-drawer component test and tablet trigger geometry E2E |
| `AC-UI-COMPACT-WORKFLOW-STEP-NAVIGATION-001.4` | Eligibility and current-step component tests |
| `AC-UI-COMPACT-WORKFLOW-STEP-NAVIGATION-001.5` | `moveTask` payload component test and API-poll E2E assertions |
| `AC-UI-COMPACT-WORKFLOW-STEP-NAVIGATION-001.6` | Keyboard desktop E2E with Tab and Enter, plus tablet geometry |
| `AC-UI-COMPACT-WORKFLOW-STEP-NAVIGATION-001.7` | Archived compact-state component test |
| `AC-UI-COMPACT-WORKFLOW-STEP-NAVIGATION-001.8` | Existing expanded-mode component test |
| `AC-UI-COMPACT-WORKFLOW-STEP-NAVIGATION-001.9` | Existing Pixel 5 mobile task-drawer E2E scenario |
| `AC-UI-COMPACT-WORKFLOW-STEP-NAVIGATION-001.10` | Desktop compact button and coarse-pointer hit-area E2E |
## E2E tests
- `apps/web/e2e/tests/layout/task-topbar-workflow-stepper.spec.ts`, Chromium project: compact hover disclosure and task movement.
- `apps/web/e2e/tests/layout/task-topbar-workflow-stepper.spec.ts`, Chromium project with `tabletTestPage`: touch drawer, geometry, and task movement.
- `apps/web/e2e/tests/task/mobile-sidebar-task-actions.spec.ts`, mobile-chrome project: existing phone task movement through **Move to**.
## Work orders
- [x] [Task 01: Add compact workflow step disclosure](task-01-compact-step-disclosure.md)
## Verification results
Completed 2026-08-26.
- Component tests: 9 passed in `components/task/workflow-stepper.test.tsx`.
- Focused ESLint: passed with no warnings for the changed component, test, and E2E files.
- TypeScript typecheck: passed.
- i18n checks: passed with no new violations.
- Chromium E2E: compact Popover dialog semantics, keyboard Tab and Enter movement, Escape dismissal, focus return, and tablet touch-drawer scenarios passed.
- Mobile-chrome E2E: the existing phone **Move to** scenario passed.
- Desktop density: the fine-pointer move button measured below 40px, while the coarse-pointer move button and disclosure trigger remained at least 44px.
- Tablet geometry: the disclosure trigger and touch rows measured at least 44px, the touch drawer stayed inside the viewport, and the document did not gain horizontal overflow.
## Risks
- A nested disclosure can close its parent before a movement button receives the pointer. The design uses one Popover surface and no nested hover roots.
- The compact state depends on rendered width. The E2E fixture must prove that `workflow-stepper-minimal` is visible before it opens the disclosure.
- Tablet pointer detection depends on browser media queries. The E2E uses the existing `tabletTestPage` touch context.
- A failed move must not leave movement controls disabled or close the disclosure.