Files
initiative/specs/011-quick-hp-input/tasks.md

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 QuickHpInput component skeleton with local state (mode: "damage" | "heal", inputValue: string), props interface (combatantId, disabled, onAdjustHp), and basic render structure in apps/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., Sword or Minus from Lucide), heal mode with positive color (green tones) and a heal icon (e.g., Heart or Plus from Lucide). Toggle with a single click. File: apps/web/src/components/quick-hp-input.tsx
  • T004 [US1] [US2] [US3] Integrate QuickHpInput into CombatantRow grid layout. Add it alongside the existing CurrentHpInput/MaxHpInput display. Pass onAdjustHp prop through. Only render when combatant has HP tracking active (maxHp is 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 onKeyDown handler 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 adjustHp and useEncounter hook 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)

  1. Complete T001-T004 (core component + integration)
  2. STOP and VALIDATE: Test damage and healing with mouse clicks
  3. This delivers the core value: quick numeric HP adjustment

Full Feature

  1. Complete Phase 1 → Validate
  2. Complete Phase 2 (keyboard workflow) → Validate
  3. 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) from useEncounter hook handles clamping, persistence, and event emission.
  • The QuickHpInput component only needs to: parse user input to integer, determine sign from mode, and call onAdjustHp.
  • Existing CurrentHpInput and MaxHpInput remain untouched per clarification.