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

8.2 KiB

Tasks: Combatant Row Declutter

Input: Design documents from /specs/019-combatant-row-declutter/ Prerequisites: plan.md (required), spec.md (required for user stories), research.md, data-model.md, quickstart.md

Tests: Not explicitly requested in the feature specification. Test tasks are omitted.

Organization: Tasks are grouped by user story to enable independent implementation and testing of each story.

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)
  • Include exact file paths in descriptions

Phase 1: Setup (Shared Infrastructure)

Purpose: No new project setup needed — this feature modifies existing components only. Phase skipped.


Phase 2: Foundational (Blocking Prerequisites)

Purpose: No foundational/blocking work required. Both user stories modify independent components within the same file and can proceed directly.


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

Goal: Replace the always-visible QuickHpInput (delta input + Sword/Heart buttons) with a clickable current HP display that opens a popover for damage/healing.

Independent Test: Click a combatant's current HP number, enter a value, press Enter (damage) or Shift+Enter (heal), verify HP updates and popover dismisses. Verify bloodied/unconscious color coding on the static HP display.

Implementation for User Story 1

  • T001 [US1] Create HpAdjustPopover component in apps/web/src/components/hp-adjust-popover.tsx — popover with auto-focused numeric input, Damage button (red/Sword icon), and Heal button (green/Heart icon). Input accepts positive integers only. Enter applies damage (negative delta), Shift+Enter applies healing (positive delta). Popover dismisses on action, Escape, or click-outside (use ref-based click-outside listener per research.md R1).
  • T002 [US1] Replace CurrentHpInput in apps/web/src/components/combatant-row.tsx with a clickable static HP display — render current HP as a <button> element with color-coded text (amber for bloodied, red for unconscious via deriveHpStatus). On click, open the HpAdjustPopover. Wire popover's onAdjustHp to existing onAdjustHp callback with unchanged signature.
  • T003 [US1] Remove QuickHpInput usage from apps/web/src/components/combatant-row.tsx — delete the <QuickHpInput> render and its import. The HP section should now show: clickable current HP / max HP input (always-visible).
  • T004 [US1] Delete apps/web/src/components/quick-hp-input.tsx — component is fully replaced by HpAdjustPopover.
  • T005 [US1] Run pnpm check to verify no lint, type, format, test, or unused-code errors after HP popover changes.

Checkpoint: HP adjustment works via click-to-adjust popover. No always-visible delta input or Sword/Heart buttons. Color-coded HP status preserved.


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

Goal: Replace the always-visible AC input field with a static display (shield icon + number) that becomes an inline edit on click.

Independent Test: View a combatant row and verify AC shows as shield+number text (not an input). Click it, edit the value, press Enter — verify AC updates. Press Escape — verify edit cancels. Clear and commit — verify AC unsets.

Implementation for User Story 2

  • T006 [US2] Refactor AcInput in apps/web/src/components/combatant-row.tsx to a click-to-edit pattern — default state renders shield icon + AC number as a <button> (or just shield icon if AC is unset). On click, switch to an inline <Input> with the current value pre-filled and selected. Commit on Enter/blur, cancel on Escape. Follow the same state pattern as the existing EditableName component (editing boolean, draft state, commit/cancel callbacks).
  • T007 [US2] Run pnpm check to verify no lint, type, format, test, or unused-code errors after AC click-to-edit changes.

Checkpoint: AC displays as compact static text. Click-to-edit works with Enter/blur commit and Escape cancel.


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

Goal: Replace the always-visible Max HP input field with a static display that becomes an inline edit on click, consistent with the AC click-to-edit pattern.

Independent Test: View a combatant row and verify Max HP shows as static text (not an input). Click it, edit the value, press Enter — verify Max HP updates. Press Escape — verify edit cancels. Clear and commit — verify Max HP unsets.

Implementation for User Story 3

  • T010 [US3] Refactor MaxHpInput in apps/web/src/components/combatant-row.tsx to a click-to-edit pattern — default state renders max HP number as a <button> (or placeholder text "Max" if unset). On click, switch to an inline <Input> with the current value pre-filled and selected. Commit on Enter/blur, cancel on Escape. Follow the same state pattern as AcDisplay and EditableName.
  • T011 [US3] Run pnpm check to verify no lint, type, format, test, or unused-code errors after Max HP click-to-edit changes.

Checkpoint: Max HP displays as compact static text. Click-to-edit works with Enter/blur commit and Escape cancel.


Phase 5: Polish & Cross-Cutting Concerns

Purpose: Final cleanup and grid layout adjustment after both stories are complete.

  • T008 Adjust combatant row grid layout in apps/web/src/components/combatant-row.tsx — update the grid-cols-[...] template to account for reduced HP section width (no more QuickHpInput) and compact AC display. Verify alignment on desktop and tablet-width viewports. Verify keyboard accessibility: HP display and AC display must be focusable via Tab, operable via Enter, and dismissable via Escape (FR-010).
  • T009 Run final pnpm check to verify the complete feature passes all quality gates.

Dependencies & Execution Order

Phase Dependencies

  • User Story 1 (Phase 3): No prerequisites — can start immediately
  • User Story 2 (Phase 4): No dependency on US1 — can start in parallel
  • Polish (Phase 5): Depends on both US1 and US2 being complete

User Story Dependencies

  • User Story 1 (P1): Independent — modifies HP section of combatant row
  • User Story 2 (P2): Independent — modifies AC section of combatant row

Within Each User Story

  • HpAdjustPopover component (T001) must be created before integrating into combatant row (T002)
  • QuickHpInput removal (T003, T004) must follow popover integration (T002)
  • AC refactor (T006) is a single self-contained change

Parallel Opportunities

  • US1 (T001-T005) and US2 (T006-T007) can run in parallel since they modify different sections of the combatant row
  • Within US1: T001 (new component) can be written before T002-T004 (integration + cleanup)

Parallel Example: User Stories 1 & 2

# These two stories can run in parallel (different component sections):
# Developer A: User Story 1 — HP popover
Task: T001 "Create HpAdjustPopover component"
Task: T002 "Replace CurrentHpInput with clickable display + popover"
Task: T003 "Remove QuickHpInput usage from combatant row"
Task: T004 "Delete quick-hp-input.tsx"
Task: T005 "Run pnpm check"

# Developer B: User Story 2 — AC click-to-edit
Task: T006 "Refactor AcInput to click-to-edit pattern"
Task: T007 "Run pnpm check"

Implementation Strategy

MVP First (User Story 1 Only)

  1. Complete Phase 3: User Story 1 (HP popover) — T001 through T005
  2. STOP and VALIDATE: Test HP popover independently
  3. This alone delivers the biggest declutter win (removes 3 always-visible controls per row)

Incremental Delivery

  1. Add User Story 1 → Test independently → Commit (MVP!)
  2. Add User Story 2 → Test independently → Commit
  3. Polish phase → Final grid adjustments → Commit
  4. Each story adds declutter value without breaking previous work

Notes

  • [P] tasks = different files, no dependencies
  • [Story] label maps task to specific user story for traceability
  • Domain and application layers are untouched — all changes in apps/web/src/components/
  • Callback signatures (onAdjustHp, onSetAc) remain unchanged
  • Commit after each completed user story