Implement the 024-fix-hp-popover-overflow feature that switches the HP adjustment popover from absolute to fixed positioning with viewport-aware clamping so it stays fully visible and causes no horizontal scrollbar, even when the HP display is near the right edge of the viewport

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Lukas
2026-03-09 16:50:39 +01:00
parent 24198c25f1
commit c6349928eb
7 changed files with 345 additions and 2 deletions

View File

@@ -1,5 +1,11 @@
import { Heart, Sword } from "lucide-react";
import { useCallback, useEffect, useRef, useState } from "react";
import {
useCallback,
useEffect,
useLayoutEffect,
useRef,
useState,
} from "react";
import { Button } from "./ui/button";
import { Input } from "./ui/input";
@@ -10,9 +16,28 @@ interface HpAdjustPopoverProps {
export function HpAdjustPopover({ onAdjust, onClose }: HpAdjustPopoverProps) {
const [inputValue, setInputValue] = useState("");
const [pos, setPos] = useState<{ top: number; left: number } | null>(null);
const ref = useRef<HTMLDivElement>(null);
const inputRef = useRef<HTMLInputElement>(null);
useLayoutEffect(() => {
const el = ref.current;
if (!el) return;
const parent = el.parentElement;
if (!parent) return;
const trigger = parent.getBoundingClientRect();
const popover = el.getBoundingClientRect();
const vw = document.documentElement.clientWidth;
let left = trigger.left;
if (left + popover.width > vw) {
left = vw - popover.width - 8;
}
if (left < 8) {
left = 8;
}
setPos({ top: trigger.bottom + 4, left });
}, []);
useEffect(() => {
requestAnimationFrame(() => inputRef.current?.focus());
}, []);
@@ -61,7 +86,12 @@ export function HpAdjustPopover({ onAdjust, onClose }: HpAdjustPopoverProps) {
return (
<div
ref={ref}
className="absolute z-10 mt-1 rounded-md border border-border bg-background p-2 shadow-lg"
className="fixed z-10 rounded-md border border-border bg-background p-2 shadow-lg"
style={
pos
? { top: pos.top, left: pos.left }
: { visibility: "hidden" as const }
}
>
<div className="flex items-center gap-1">
<Input