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:
- 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.
- Given the remove button is in confirm state, When the user clicks it again, Then the combatant is removed from the encounter.
- 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.
- 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.
- 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:
- 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.
- Given the trash button is in confirm state, When the user clicks it again, Then the entire encounter is cleared.
- 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.
- 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:
- Given a destructive button has keyboard focus, When the user presses Enter or Space, Then the button enters confirm state.
- Given a destructive button is in confirm state with focus, When the user presses Enter or Space, Then the destructive action executes.
- Given a destructive button is in confirm state with focus, When the user presses Escape, Then the button reverts to its original state.
- 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
ConfirmButtoncomponent 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
ConfirmButtoninstead ofwindow.confirm(). - FR-008: The remove combatant (X) button MUST use
ConfirmButtoninstead of deleting immediately. - FR-009: The
ConfirmButtonMUST remain fully keyboard-accessible: focusable, activatable via Enter/Space, dismissable via Escape. - FR-010: Each
ConfirmButtoninstance 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 (
Checkcomponent). - 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.