3.6 KiB
Implementation Plan: Inline Confirmation Buttons
Branch: 032-inline-confirm-buttons | Date: 2026-03-11 | Spec: spec.md
Input: Feature specification from /specs/032-inline-confirm-buttons/spec.md
Summary
Replace single-click destructive actions and window.confirm() dialogs with a reusable ConfirmButton component that provides inline two-step confirmation. First click arms the button (checkmark icon, red background, scale pulse animation); second click executes the action. Auto-reverts after 5 seconds. Applied to the remove combatant (X) and clear encounter (trash) buttons. Fully keyboard-accessible.
Technical Context
Language/Version: TypeScript 5.8 (strict mode, verbatimModuleSyntax)
Primary Dependencies: React 19, Tailwind CSS v4, Lucide React, class-variance-authority (cva)
Storage: N/A (no persistence changes — confirm state is ephemeral)
Testing: Vitest (unit tests for state logic; manual testing for animation/visual)
Target Platform: Web (modern browsers)
Project Type: Web application (monorepo: apps/web + packages/domain + packages/application)
Performance Goals: Instant visual feedback (<16ms frame budget for animation)
Constraints: No new runtime dependencies; CSS-only animation
Scale/Scope: 1 new component, 3 modified files, 1 CSS animation added
Constitution Check
GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.
| Principle | Status | Notes |
|---|---|---|
| I. Deterministic Domain Core | PASS | No domain changes. Confirm state is purely UI-local. |
| II. Layered Architecture | PASS | ConfirmButton lives in adapter layer (apps/web/src/components/ui/). Confirmation logic moves from application hook to UI component where it belongs. No reverse dependencies. |
| III. Clarification-First | PASS | Spec is fully specified with zero NEEDS CLARIFICATION markers. |
| IV. Escalation Gates | PASS | All work is within spec scope. |
| V. MVP Baseline Language | PASS | Spec uses "MVP baseline does not include" for undo and configurability. |
| VI. No Gameplay Rules | PASS | No gameplay mechanics involved. |
Post-Phase 1 re-check: All gates still pass. Moving window.confirm() out of use-encounter.ts into a UI component improves layer separation — confirmation is a UI concern, not an application concern.
Project Structure
Documentation (this feature)
specs/032-inline-confirm-buttons/
├── plan.md # This file
├── research.md # Phase 0 output
├── data-model.md # Phase 1 output
├── quickstart.md # Phase 1 output
└── tasks.md # Phase 2 output (/speckit.tasks — NOT created by /speckit.plan)
Source Code (repository root)
apps/web/src/
├── components/
│ ├── ui/
│ │ ├── button.tsx # Existing — wrapped by ConfirmButton
│ │ └── confirm-button.tsx # NEW — reusable two-step confirm component
│ ├── combatant-row.tsx # MODIFIED — use ConfirmButton for remove
│ └── turn-navigation.tsx # MODIFIED — use ConfirmButton for trash
├── hooks/
│ └── use-encounter.ts # MODIFIED — remove window.confirm()
└── index.css # MODIFIED — add scale pulse keyframe
Structure Decision: This feature adds one new component file to the existing ui/ directory and modifies three existing files. No new directories or structural changes needed. No contracts directory needed — this is an internal UI component with no external interfaces.