# Tasks: Fix HP Popover Overflow **Input**: Design documents from `/specs/024-fix-hp-popover-overflow/` **Prerequisites**: plan.md (required), spec.md (required for user stories), research.md **Tests**: Not explicitly requested in spec. No test tasks generated. **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: User Story 1 - HP popover stays fully visible (Priority: P1) 🎯 MVP **Goal**: The HP adjustment popover repositions itself to stay within the viewport when it would otherwise overflow to the right. **Independent Test**: Open the HP adjustment popover for any combatant. The entire popover (input, damage button, healing button) is visible without horizontal scrolling, even when the HP display is near the right edge of the viewport. ### Implementation for User Story 1 - [x] T001 [US1] Switch `HpAdjustPopover` in `apps/web/src/components/hp-adjust-popover.tsx` from `position: absolute` to `position: fixed` with viewport-aware positioning — use a `useLayoutEffect` to measure the trigger's viewport rect via `parentElement.getBoundingClientRect()` and the popover's width, then compute `top` (trigger bottom + 4px) and `left` (trigger left, clamped to `[8, vw - popover.width - 8]` using `document.documentElement.clientWidth`). Render with `visibility: hidden` until positioned to avoid flash. This escapes the scroll container's overflow clipping that made `position: absolute` approaches ineffective. - [x] T002 [US1] **Manual QA**: Verify that no horizontal scrollbar appears when the popover is open by ensuring the repositioned popover does not extend beyond `window.innerWidth`. Test with a combatant whose HP display is near the right viewport edge. **Checkpoint**: At this point, the HP popover should be fully visible for all combatant rows. No horizontal scrollbar should appear. --- ## Phase 2: User Story 2 - Popover remains usable with stat block panel open (Priority: P2) **Goal**: The HP popover stays fully visible even when the stat block side panel is open, which narrows the available width. **Independent Test**: Open the stat block panel, then open the HP popover for a combatant. The popover is fully visible within the encounter tracker area. ### Implementation for User Story 2 - [x] T003 [US2] **Manual QA**: Verify that the viewport-aware positioning from T001 correctly handles the reduced-width scenario when the stat block panel is open in `apps/web/src/App.tsx`. The `getBoundingClientRect()` measurement should already account for the narrowed layout since it measures against the actual viewport. If the popover still overflows (e.g., because the stat block panel is an overlay and the popover's `right` edge is under it), adjust the overflow detection threshold to account for the panel width. Test at narrow viewport widths (e.g., 375px mobile). **Checkpoint**: HP popover is fully visible at all viewport widths, including with stat block panel open. --- ## Phase 3: Polish & Cross-Cutting Concerns - [x] T004 Run `pnpm check` to ensure all linting, formatting, type checks, and tests pass in the repository --- ## Dependencies & Execution Order ### Phase Dependencies - **Phase 1 (US1)**: No dependencies — can start immediately - **Phase 2 (US2)**: Depends on Phase 1 (T001) — verifies the same positioning logic in a narrower viewport context - **Phase 3 (Polish)**: Depends on Phase 1 and Phase 2 ### Parallel Opportunities - T001 is the only implementation task; T002 and T003 are verification tasks that depend on T001 - No parallel implementation opportunities (single-file change) --- ## Implementation Strategy ### MVP First (User Story 1 Only) 1. Complete T001: Add viewport-aware positioning 2. Complete T002: Verify no horizontal scrollbar 3. **STOP and VALIDATE**: Test with combatants at various positions 4. If MVP is sufficient, proceed to Polish ### Incremental Delivery 1. T001 → Core fix (popover repositions) 2. T002 → Validate fix works in standard layout 3. T003 → Validate fix works with stat block panel 4. T004 → Ensure merge gate passes --- ## Notes - This is a single-component bug fix. The entire implementation is in `apps/web/src/components/hp-adjust-popover.tsx`. - The `ConditionPicker` pattern (`position: absolute` + `flipped` flag) was not usable here because the popover sits inside a scroll container that clips absolutely-positioned children. `position: fixed` was used instead. - The existing `ref` on the popover div is reused for measurement. - Commit after T001 as the atomic implementation change.