Files
initiative/specs/032-inline-confirm-buttons/spec.md

8.2 KiB

Feature Specification: Inline Confirmation Buttons

Feature Branch: 032-inline-confirm-buttons Created: 2026-03-11 Status: Draft Input: User description: "Replace confirmation modals with inline confirmation buttons for destructive actions"

User Scenarios & Testing (mandatory)

User Story 1 - Confirm-to-delete for removing a combatant (Priority: P1)

A user hovering over a combatant row sees the remove (X) button. They click it and the button transitions into a red "confirm" state with a checkmark icon and a subtle scale pulse animation. If they click again within 5 seconds, the combatant is removed. If they wait, click elsewhere, or press Escape, the button quietly reverts to its original state without taking any action.

Why this priority: The remove combatant button currently has no confirmation at all — it deletes immediately. This is the highest-risk destructive action because it can be triggered accidentally during fast-paced encounter management and there is no undo.

Independent Test: Can be fully tested by adding a single combatant, clicking the X button once (verifying confirm state), then clicking again (verifying removal). Delivers immediate safety value.

Acceptance Scenarios:

  1. Given a combatant row is visible, When the user clicks the remove (X) button once, Then the button transitions to a confirm state showing a checkmark icon on a red/danger background with a scale pulse animation.
  2. Given the remove button is in confirm state, When the user clicks it again, Then the combatant is removed from the encounter.
  3. Given the remove button is in confirm state, When 5 seconds elapse without a second click, Then the button reverts to its original X icon and default styling.
  4. Given the remove button is in confirm state, When the user clicks outside the button, Then the button reverts to its original state without removing the combatant.
  5. Given the remove button is in confirm state, When the user presses Escape, Then the button reverts to its original state without removing the combatant.

User Story 2 - Confirm-to-clear for resetting the encounter (Priority: P2)

A user clicks the trash button to clear the entire encounter. Instead of a browser confirm dialog appearing, the trash button itself transitions into a red confirm state with a checkmark icon and a scale pulse. A second click clears the encounter; otherwise the button reverts after 5 seconds or on dismiss.

Why this priority: The clear encounter action already has a browser window.confirm() dialog. Replacing it with the inline pattern improves UX consistency but is lower priority since protection already exists.

Independent Test: Can be tested by adding combatants, clicking the trash button once (verifying confirm state), then clicking again (verifying encounter is cleared). Delivers a more modern, consistent experience.

Acceptance Scenarios:

  1. Given an encounter has combatants, When the user clicks the clear encounter (trash) button once, Then the button transitions to a confirm state with a checkmark icon on a red/danger background with a scale pulse animation.
  2. Given the trash button is in confirm state, When the user clicks it again, Then the entire encounter is cleared.
  3. Given the trash button is in confirm state, When 5 seconds pass, the user clicks outside, or the user presses Escape, Then the button reverts to its original trash icon and default styling without clearing the encounter.
  4. Given the encounter has no combatants, When the user views the trash button, Then it remains disabled and cannot enter confirm state.

User Story 3 - Keyboard-accessible confirmation flow (Priority: P2)

A keyboard-only user can trigger the confirm state with Enter or Space, confirm the destructive action with a second Enter or Space, and cancel with Escape — all without needing a mouse.

Why this priority: Keyboard accessibility is a core project requirement (established in the quality gates feature). It shares priority with Story 2 because it is integral to the component's correctness rather than an add-on.

Independent Test: Can be tested by tabbing to a destructive button, pressing Enter (verifying confirm state), then pressing Enter again (verifying action executes). Escape cancels.

Acceptance Scenarios:

  1. Given a destructive button has keyboard focus, When the user presses Enter or Space, Then the button enters confirm state.
  2. Given a destructive button is in confirm state with focus, When the user presses Enter or Space, Then the destructive action executes.
  3. Given a destructive button is in confirm state with focus, When the user presses Escape, Then the button reverts to its original state.
  4. Given a destructive button is in confirm state, When the button loses focus (e.g., Tab away), Then the button reverts to its original state.

Edge Cases

  • What happens if the user rapidly clicks the button three or more times? The first click enters confirm state, the second executes the action — additional clicks are no-ops since the target is already removed/cleared.
  • What happens if the component unmounts while in confirm state (e.g., navigating away)? The timer must be cleaned up to prevent memory leaks or stale state updates.
  • What happens if two ConfirmButtons are in confirm state simultaneously (e.g., hovering over one combatant's X then another's)? Each button manages its own state independently.
  • What happens if the remove button's combatant row is re-rendered while in confirm state (e.g., due to initiative changes)? The confirm state persists through re-renders as long as the combatant identity is stable.

Requirements (mandatory)

Functional Requirements

  • FR-001: System MUST provide a reusable ConfirmButton component that wraps any icon button to add a two-step confirmation flow.
  • FR-002: On first activation (click, Enter, or Space), the button MUST transition to a confirm state displaying a checkmark icon on a red/danger background.
  • FR-003: The confirm state MUST enter with a subtle scale pulse animation to draw attention to the state change.
  • FR-004: The button MUST automatically revert to its original state after 5 seconds if not confirmed.
  • FR-005: Clicking outside the button, pressing Escape, or moving focus away MUST cancel the confirm state and revert the button.
  • FR-006: A second activation (click, Enter, or Space) while in confirm state MUST execute the destructive action.
  • FR-007: The clear encounter (trash) button MUST use ConfirmButton instead of window.confirm().
  • FR-008: The remove combatant (X) button MUST use ConfirmButton instead of deleting immediately.
  • FR-009: The ConfirmButton MUST remain fully keyboard-accessible: focusable, activatable via Enter/Space, dismissable via Escape.
  • FR-010: Each ConfirmButton instance MUST manage its confirm state independently of other instances.

Success Criteria (mandatory)

Measurable Outcomes

  • SC-001: All destructive actions require exactly two deliberate user interactions to execute, eliminating single-click accidental deletions.
  • SC-002: The confirmation flow completes (enter confirm state, execute action) in under 2 seconds for an experienced user, keeping the interaction faster than a modal dialog.
  • SC-003: The confirm state is visually distinct enough that users can identify it without reading text — recognizable by color and icon change alone.
  • SC-004: All confirmation flows are fully operable via keyboard alone, with no mouse dependency.
  • SC-005: The auto-revert timer reliably resets the button after 5 seconds, preventing stale confirm states from persisting.

Assumptions

  • The checkmark icon will use the project's existing Lucide icon library (Check component).
  • The red/danger background will use the project's existing destructive color tokens.
  • The scale pulse animation will be a CSS animation, keeping it lightweight.
  • The 5-second timeout is a fixed value. MVP baseline does not include configurability.
  • MVP baseline does not include undo functionality — that would be a separate feature.