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.tsxwith a clickable static HP display — render current HP as a<button>element with color-coded text (amber for bloodied, red for unconscious viaderiveHpStatus). On click, open the HpAdjustPopover. Wire popover's onAdjustHp to existingonAdjustHpcallback 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 checkto 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.tsxto 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 existingEditableNamecomponent (editing boolean, draft state, commit/cancel callbacks). - T007 [US2] Run
pnpm checkto 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.tsxto 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 asAcDisplayandEditableName. - T011 [US3] Run
pnpm checkto 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 thegrid-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 checkto 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)
- Complete Phase 3: User Story 1 (HP popover) — T001 through T005
- STOP and VALIDATE: Test HP popover independently
- This alone delivers the biggest declutter win (removes 3 always-visible controls per row)
Incremental Delivery
- Add User Story 1 → Test independently → Commit (MVP!)
- Add User Story 2 → Test independently → Commit
- Polish phase → Final grid adjustments → Commit
- 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