6.5 KiB
Tasks: Quick HP Input
Input: Design documents from /specs/011-quick-hp-input/
Prerequisites: plan.md (required), spec.md (required), research.md, data-model.md
Tests: No test tasks included (not explicitly requested in spec). Domain logic is already fully tested via adjustHp.test.ts.
Organization: US1 (damage), US2 (healing), and US3 (mode toggle) are all P1 and form a single inseparable component (QuickHpInput). They are combined into one phase since you cannot meaningfully implement damage input without the mode concept. US4 (keyboard workflow) is P2 and layered on top.
Format: [ID] [P?] [Story] Description
- [P]: Can run in parallel (different files, no dependencies)
- [Story]: Which user story this task belongs to (e.g., US1, US2, US3)
- Include exact file paths in descriptions
Phase 1: Core Quick HP Input Component (US1 + US2 + US3, Priority: P1)
Goal: Deliver a working inline damage/heal input per combatant with mode toggle and visual distinction. Covers the primary combat workflow: type a number, apply as damage or healing.
Independent Test: Set a combatant's max HP to 20, type "7" in damage mode and confirm -- HP drops to 13. Toggle to heal mode, type "5" and confirm -- HP rises to 18. Mode is visually distinguishable at a glance.
Implementation
- T001 [US1] [US2] [US3] Create
QuickHpInputcomponent skeleton with local state (mode: "damage" | "heal",inputValue: string), props interface (combatantId,disabled,onAdjustHp), and basic render structure inapps/web/src/components/quick-hp-input.tsx - T002 [US1] [US2] Implement numeric input field that only accepts digit characters, parses to integer on confirm, computes signed delta based on mode (damage = negative, heal = positive), calls
onAdjustHp(combatantId, delta), and clears input after successful application. Reject zero and empty input. File:apps/web/src/components/quick-hp-input.tsx - T003 [US3] Implement damage/heal mode toggle button adjacent to the input field. Use distinct visual treatments: damage mode with destructive color (red tones) and a damage icon (e.g.,
SwordorMinusfrom Lucide), heal mode with positive color (green tones) and a heal icon (e.g.,HeartorPlusfrom Lucide). Toggle with a single click. File:apps/web/src/components/quick-hp-input.tsx - T004 [US1] [US2] [US3] Integrate
QuickHpInputintoCombatantRowgrid layout. Add it alongside the existingCurrentHpInput/MaxHpInputdisplay. PassonAdjustHpprop through. Only render when combatant has HP tracking active (maxHpis defined). Ensure the compact resting state fits the existing row height. File:apps/web/src/components/combatant-row.tsx
Checkpoint: Damage and healing can be applied via the inline input with mouse interaction. Mode toggle works with clear visual distinction. Direct HP entry still functions alongside.
Phase 2: Keyboard-Driven Workflow (US4, Priority: P2)
Goal: Enable full keyboard-driven damage/heal workflow so the game master never needs to reach for the mouse during combat.
Independent Test: Focus the quick input, type "7", press Enter -- value applies and input clears. Press Escape -- input clears without applying. Press Tab -- mode toggles between damage and heal while keeping focus.
Implementation
- T005 [US4] Add
onKeyDownhandler to the quick input: Enter confirms and applies the value (same as existing confirm logic), Escape clears the input without applying. File:apps/web/src/components/quick-hp-input.tsx - T006 [US4] Add Tab key handling to toggle mode while preventing default tab-to-next-element behavior. When Tab is pressed while the input is focused, flip mode (
damage<->heal) and keep focus in the input. File:apps/web/src/components/quick-hp-input.tsx
Checkpoint: Full keyboard workflow functional -- Enter to apply, Escape to dismiss, Tab to toggle mode. No mouse required.
Phase 3: Polish & Cross-Cutting Concerns
Purpose: Final validation, visual polish, and quality gate
- T007 Verify compact resting state styling: input should be minimal/subtle when not focused and expand to full interactive state on focus. Ensure consistent look with existing combatant row elements (same height, alignment, font). File:
apps/web/src/components/quick-hp-input.tsx - T008 Run
pnpm check(knip + format + lint + typecheck + test) and fix any issues. Ensure no unused exports, no type errors, and all existing tests still pass.
Dependencies & Execution Order
Phase Dependencies
- Phase 1 (Core Component): Can start immediately -- no setup or foundational work needed. Domain
adjustHpanduseEncounterhook already exist. - Phase 2 (Keyboard): Depends on Phase 1 completion (T001-T004). Keyboard handlers are added to the existing component.
- Phase 3 (Polish): Depends on Phase 2 completion.
User Story Dependencies
- US1 (Damage) + US2 (Healing) + US3 (Mode Toggle): Implemented together in Phase 1 as they form one inseparable component. Cannot apply damage without the mode concept, cannot toggle without both modes.
- US4 (Keyboard): Depends on US1+US2+US3 (the component must exist before adding keyboard handlers).
Within Phase 1
T001 (skeleton) → T002 (input logic) → T004 (integration)
T001 (skeleton) → T003 (toggle UI) → T004 (integration)
T002 and T003 can run in parallel after T001 (different concerns in the same file, but T002 is input logic and T003 is toggle UI -- recommend sequential to avoid merge conflicts in the same file).
Parallel Opportunities
Limited parallelism due to single-file component. Recommended sequential execution:
T001 → T002 → T003 → T004 → T005 → T006 → T007 → T008
Implementation Strategy
MVP First (Phase 1 Only)
- Complete T001-T004 (core component + integration)
- STOP and VALIDATE: Test damage and healing with mouse clicks
- This delivers the core value: quick numeric HP adjustment
Full Feature
- Complete Phase 1 → Validate
- Complete Phase 2 (keyboard workflow) → Validate
- Complete Phase 3 (polish + quality gate) → Ready for commit
Notes
- No domain or application layer changes needed. All tasks are in
apps/web/src/. - The existing
adjustHp(id, delta)fromuseEncounterhook handles clamping, persistence, and event emission. - The
QuickHpInputcomponent only needs to: parse user input to integer, determine sign from mode, and callonAdjustHp. - Existing
CurrentHpInputandMaxHpInputremain untouched per clarification.