# Implementation Plan: Inline Confirmation Buttons **Branch**: `032-inline-confirm-buttons` | **Date**: 2026-03-11 | **Spec**: [spec.md](./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) ```text 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) ```text 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.