# Tasks: Inline Confirmation Buttons **Input**: Design documents from `/specs/032-inline-confirm-buttons/` **Prerequisites**: plan.md, spec.md, research.md, data-model.md, quickstart.md **Tests**: Not explicitly requested in spec. Tests included for the ConfirmButton component since its state machine logic is well-suited to unit testing and the spec defines precise acceptance scenarios. **Organization**: Tasks are grouped by user story to enable independent implementation and testing of each story. ## Format: `[ID] [P?] [Story] Description` - **[P]**: Can run in parallel (different files, no dependencies) - **[Story]**: Which user story this task belongs to (e.g., US1, US2, US3) - Include exact file paths in descriptions ## Phase 1: Setup (Shared Infrastructure) **Purpose**: CSS animation and reusable component that all user stories depend on - [x] T001 Add `animate-confirm-pulse` scale pulse keyframe animation in `apps/web/src/index.css` — define a `@keyframes confirm-pulse` (scale 1 → 1.15 → 1) and register it as `@utility animate-confirm-pulse` following the existing `animate-concentration-pulse` pattern - [x] T002 Create `ConfirmButton` component in `apps/web/src/components/ui/confirm-button.tsx` — wraps the existing `Button` component with a two-step confirmation flow: accepts `onConfirm`, `icon`, `label`, `className?`, `disabled?` props; manages `isConfirming` state via `useState`; on first click sets `isConfirming=true` and starts a 5-second `setTimeout` to auto-revert; on second click calls `onConfirm()`; in confirm state renders `Check` icon with `bg-destructive text-primary-foreground rounded-md animate-confirm-pulse`; adds `mousedown` click-outside listener and `keydown` Escape listener (both with cleanup); reverts on focus loss via `onBlur`; calls `e.stopPropagation()` on all clicks; updates `aria-label` to reflect confirm state (e.g., "Confirm remove combatant" when armed, using `label` prop as base); cleans up timer on unmount --- ## Phase 2: Foundational (Blocking Prerequisites) **Purpose**: Unit tests for the ConfirmButton state machine - [x] T003 Write unit tests for `ConfirmButton` in `apps/web/src/__tests__/confirm-button.test.tsx` — test: (1) renders default icon in idle state, (2) first click transitions to confirm state with Check icon and destructive background, (3) second click in confirm state calls `onConfirm`, (4) auto-reverts after 5 seconds (use `vi.useFakeTimers`), (5) Escape key reverts to idle, (6) click outside reverts to idle, (7) disabled prop prevents entering confirm state, (8) unmount cleans up timer, (9) independent instances don't interfere with each other **Checkpoint**: ConfirmButton component is fully functional and tested. User story integration can begin. --- ## Phase 3: User Story 1 — Confirm-to-delete for removing a combatant (Priority: P1) MVP **Goal**: The remove combatant (X) button uses ConfirmButton instead of deleting immediately. **Independent Test**: Add a combatant, click X once (verify confirm state with checkmark), click again (verify removal). Wait 5s after first click (verify revert). Press Escape (verify cancel). ### Implementation for User Story 1 - [x] T004 [US1] Replace the remove `