Files
initiative/specs/024-fix-hp-popover-overflow/research.md

2.4 KiB

Research: Fix HP Popover Overflow

R-001: Positioning strategy for popover inside scroll container

Decision: Use position: fixed with useLayoutEffect + getBoundingClientRect to position the popover relative to the viewport, escaping the scroll container's overflow clipping.

Rationale: The ConditionPicker component uses position: absolute with a flipped state for vertical overflow, but that pattern does not work for the HP popover's horizontal overflow. The popover sits inside a scroll container (flex-1 overflow-y-auto) which clips absolutely-positioned children. Both right-0 alignment and translateX shifts are ineffective because the scroll container clips the overflowing content regardless. position: fixed removes the popover from the container's clipping context entirely.

Alternatives considered:

  • position: absolute with right-0 flip (ConditionPicker pattern): The relative parent (ClickableHp) is too small, so right-0 barely shifts the popover. The scroll container still clips it. Rejected.
  • position: absolute with translateX(-Npx): Same clipping issue. Rejected.
  • overflow-x: hidden on scroll container: Clips the popover instead of showing a scrollbar — same visual problem. Rejected.
  • Floating UI / Popper.js: Heavy dependency for a simple case. Rejected.
  • CSS anchor-positioning: Not yet widely supported across browsers. Rejected.

R-002: Viewport measurement for overflow detection

Decision: Use document.documentElement.clientWidth instead of window.innerWidth for viewport width measurement.

Rationale: When the popover overflows the viewport, window.innerWidth expands to include the scrollbar area, causing overflow detection to report no overflow. document.documentElement.clientWidth returns the CSS viewport width excluding scrollbars, giving an accurate measurement even when overflow has already occurred.

R-003: Horizontal scrollbar cause

Decision: The fix addresses the root cause (popover overflow) rather than masking the symptom (scrollbar).

Rationale: The scrollbar appeared because the combatant list container (flex-1 overflow-y-auto min-h-0) has default overflow-x: visible. The absolutely-positioned popover extended beyond the viewport, creating the scrollbar. Switching to position: fixed removes the popover from the document flow entirely, so it cannot cause overflow on any ancestor container.