114 lines
9.4 KiB
Markdown
114 lines
9.4 KiB
Markdown
# 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.
|