Files
initiative/specs/019-combatant-row-declutter/spec.md

9.4 KiB

Feature Specification: Combatant Row Declutter

Feature Branch: 019-combatant-row-declutter Created: 2026-03-06 Status: Draft Input: User description: "Declutter combatant row with click-to-edit patterns — replace always-visible HP adjustment and AC inputs with compact, on-demand interactions"

User Scenarios & Testing (mandatory)

User Story 1 - HP Click-to-Adjust Popover (Priority: P1)

As a DM running combat, I want to click on a combatant's current HP value to open a small adjustment popover, so the combatant row is visually clean and I can still quickly apply damage or healing when needed.

Why this priority: HP adjustment is the most frequent mid-combat interaction and the QuickHpInput with its Sword/Heart buttons is the biggest source of visual clutter. Replacing it with an on-demand popover delivers the largest declutter impact.

Independent Test: Can be fully tested by clicking a combatant's current HP, entering a number, and pressing Enter (damage) or Shift+Enter (heal), then verifying the HP updates correctly and the popover dismisses.

Acceptance Scenarios:

  1. Given a combatant with max HP set (e.g., 30/30), When I look at the row, Then I see only the current HP number and max HP — no delta input or action buttons are visible.
  2. Given a combatant with max HP set, When I click the current HP number, Then a small popover opens containing an auto-focused numeric input and Damage/Heal buttons.
  3. Given the HP popover is open with a valid number entered, When I press Enter, Then damage is applied (negative delta), the popover closes, and the HP value updates.
  4. Given the HP popover is open with a valid number entered, When I press Shift+Enter, Then healing is applied (positive delta), the popover closes, and the HP value updates.
  5. Given the HP popover is open with a valid number entered, When I click the Damage button, Then damage is applied and the popover closes.
  6. Given the HP popover is open with a valid number entered, When I click the Heal button, Then healing is applied and the popover closes.
  7. Given the HP popover is open, When I press Escape, Then the popover closes without applying any change.
  8. Given the HP popover is open, When I click outside the popover, Then the popover closes without applying any change.
  9. Given a combatant whose HP is at or below half (bloodied), When I view the row, Then the current HP number displays in the bloodied color (amber).
  10. Given a combatant whose HP is at 0 (unconscious), When I view the row, Then the current HP number displays in the unconscious color (red).
  11. Given a combatant with no max HP set, When I view the row, Then the HP area shows only the max HP input — no clickable current HP value.

User Story 2 - AC Click-to-Edit (Priority: P2)

As a DM, I want the AC field to appear as a compact static display (shield icon + number) that I can click to edit inline, so the row is less cluttered while AC remains easy to set or change.

Why this priority: AC is set less frequently than HP is adjusted, so converting it to a click-to-edit pattern provides good declutter value with lower interaction frequency impact.

Independent Test: Can be fully tested by clicking the AC display, editing the value, and confirming via Enter or blur, then verifying the AC updates correctly.

Acceptance Scenarios:

  1. Given a combatant with AC set (e.g., 15), When I view the row, Then I see a shield icon followed by the number "15" as static text — not an input field.
  2. Given a combatant with no AC set, When I view the row, Then I see just the shield icon (no number) as a clickable element.
  3. Given a combatant's AC display, When I click it, Then an inline input appears with the current AC value pre-filled and selected.
  4. Given the AC inline edit is active, When I type a new value and press Enter, Then the AC updates and the display reverts to static mode.
  5. Given the AC inline edit is active, When I click away (blur), Then the AC updates and the display reverts to static mode.
  6. Given the AC inline edit is active, When I press Escape, Then the edit is cancelled, the original value is preserved, and the display reverts to static mode.
  7. Given the AC inline edit is active, When I clear the field and press Enter, Then the AC is unset and the display shows just the shield icon.

User Story 3 - Max HP Click-to-Edit (Priority: P2)

As a DM, I want the max HP field to appear as a compact static display that I can click to edit inline, so the row is consistent with the AC click-to-edit pattern and further reduces visual clutter.

Why this priority: Max HP is set once during encounter setup and rarely changed. Converting it to click-to-edit applies the same declutter pattern as AC for consistency.

Independent Test: Can be fully tested by clicking the max HP display, editing the value, and confirming via Enter or blur, then verifying the max HP updates correctly.

Acceptance Scenarios:

  1. Given a combatant with max HP set (e.g., 30), When I view the row, Then I see the max HP as static text — not an input field.
  2. Given a combatant with no max HP set, When I view the row, Then I see a clickable placeholder to set max HP.
  3. Given a combatant's max HP display, When I click it, Then an inline input appears with the current max HP value pre-filled and selected.
  4. Given the max HP inline edit is active, When I type a new value and press Enter, Then the max HP updates and the display reverts to static mode.
  5. Given the max HP inline edit is active, When I click away (blur), Then the max HP updates and the display reverts to static mode.
  6. Given the max HP inline edit is active, When I press Escape, Then the edit is cancelled and the display reverts to static mode.
  7. Given the max HP inline edit is active, When I clear the field and press Enter, Then the max HP is unset and HP tracking is removed.

Edge Cases

  • What happens when the user enters non-numeric or negative values in the HP popover? The input only accepts positive integers; non-numeric input is ignored.
  • What happens when the user enters 0 in the HP popover? Zero is not a valid delta and the action buttons remain disabled.
  • What happens when the HP popover is open and the user tabs away? The popover closes without applying changes (same as blur/click-outside).
  • What happens on tablet-width screens? The popover and inline edit must remain accessible and not overflow or clip at viewports ≥ 768px wide (Tailwind md breakpoint).

Requirements (mandatory)

Functional Requirements

  • FR-001: System MUST replace the always-visible QuickHpInput (delta input + Sword/Heart buttons) with a clickable current HP display that opens a popover on interaction.
  • FR-002: The HP popover MUST contain a single auto-focused numeric input and two action buttons (Damage and Heal).
  • FR-003: The HP popover MUST support keyboard shortcuts: Enter for damage, Shift+Enter for heal, Escape to dismiss.
  • FR-004: The HP popover MUST dismiss automatically after an action is applied, on Escape, or when clicking outside.
  • FR-005: The current HP display MUST retain color-coded status indicators (amber for bloodied, red for unconscious) when the popover is closed.
  • FR-006: System MUST replace the always-visible AC input field with a static display (shield icon + number).
  • FR-007: Clicking the AC static display MUST open an inline edit input that commits on Enter or blur and cancels on Escape.
  • FR-008: The max HP MUST display as compact static text with click-to-edit, consistent with the AC pattern.
  • FR-009: The existing callback signatures (onAdjustHp, onSetAc) MUST remain unchanged — this is a UI-only change.
  • FR-010: All interactive elements MUST remain keyboard-accessible (focusable, operable via keyboard).
  • FR-011: The HP popover input MUST only accept positive integers as valid delta values.

Success Criteria (mandatory)

Measurable Outcomes

  • SC-001: The combatant row displays fewer always-visible interactive controls — specifically, 3 fewer visible elements (delta input, Damage button, Heal button) per combatant when HP is set.
  • SC-002: The AC field takes up less horizontal space in its default state compared to an always-visible input field.
  • SC-003: Users can apply damage or healing in 3 or fewer interactions (click HP, type number, press Enter/Shift+Enter).
  • SC-004: Users can edit AC in 3 or fewer interactions (click AC, type number, press Enter).
  • SC-005: All HP and AC interactions remain fully operable using only a keyboard.

Assumptions

  • The popover is a lightweight component positioned near the current HP value — not a full modal dialog.
  • The HP popover uses a simple overlay/click-outside pattern, consistent with how the condition picker already works in the app.
  • The AC click-to-edit follows the exact same pattern as the existing editable name component (click to edit, Enter/blur to commit, Escape to cancel).
  • Domain and application layers require zero changes — all modifications are confined to the web adapter (React components).
  • The CurrentHpInput component is either removed or repurposed as a static display + popover trigger, rather than being an always-visible input.