Implement the 011-quick-hp-input feature that adds an inline damage/heal numeric input per combatant row with mode toggle, keyboard workflow, and visual distinction

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Lukas
2026-03-05 22:43:26 +01:00
parent 1c40bf7889
commit a0d85a07e3
10 changed files with 644 additions and 0 deletions

View File

@@ -0,0 +1,87 @@
# Data Model: Quick HP Input
## Existing Entities (unchanged)
### Combatant
| Field | Type | Notes |
|-------|------|-------|
| id | CombatantId (branded string) | Unique identifier |
| name | string | Display name |
| initiative | number or undefined | Turn order value |
| maxHp | number or undefined | Positive integer >= 1, optional |
| currentHp | number or undefined | Integer in [0, maxHp], optional |
No changes to the domain `Combatant` type. HP fields already support the full range of operations needed.
### Encounter
| Field | Type | Notes |
|-------|------|-------|
| combatants | readonly Combatant[] | Ordered list |
| currentTurnIndex | number | Active combatant index |
| roundNumber | number | Current round |
No changes to the domain `Encounter` type.
## Existing Domain Events (unchanged)
### CurrentHpAdjusted
| Field | Type | Notes |
|-------|------|-------|
| type | "CurrentHpAdjusted" | Discriminant |
| combatantId | CombatantId | Target combatant |
| previousHp | number | HP before adjustment |
| newHp | number | HP after adjustment (clamped) |
| delta | number | Signed delta applied |
This event is already emitted by `adjustHp()` and fully supports the quick input feature. A negative delta represents damage, a positive delta represents healing.
## New UI-Only State (component-local, not persisted)
### QuickHpInput component state
| State | Type | Default | Notes |
|-------|------|---------|-------|
| mode | "damage" or "heal" | "damage" | Toggle between subtract and add |
| inputValue | string | "" | Raw text in the input field |
This state is local to the React component and does not persist across page reloads. The mode resets to "damage" on component mount. The input value clears after each successful application.
## State Transitions
### Apply damage
```
User enters number N in damage mode -> Enter
-> adjustHp(encounter, combatantId, -N)
-> currentHp = max(0, currentHp - N)
-> input clears
```
### Apply healing
```
User enters number N in heal mode -> Enter
-> adjustHp(encounter, combatantId, +N)
-> currentHp = min(maxHp, currentHp + N)
-> input clears
```
### Toggle mode
```
User clicks toggle or presses Tab while focused
-> mode flips: "damage" <-> "heal"
-> input value preserved (not cleared)
-> visual treatment updates immediately
```
### Dismiss
```
User presses Escape
-> input clears
-> no HP change applied
```