改写弹窗出现的位置

This commit is contained in:
董宏凯 committed 2026-05-17 20:38:35 +08:00
1 parent 05ff10df1b
commit b768e0affb
1 file changed
+31 -21
@@ -101,27 +101,35 @@ export function WritingRewritePreview({
// ── Position ──────────────────────────────────────────────────────────── // ── Position ────────────────────────────────────────────────────────────
const panelWidth = 480; const panelWidth = 480;
const containerRef = useRef<HTMLDivElement>(null); const [computedPos, setComputedPos] = useState<{
const [computedPos, setComputedPos] = useState<{ left: number; top: number } | null>(null); left: number;
top?: number;
bottom?: number;
maxHeight: number;
} | null>(null);
useLayoutEffect(() => { useLayoutEffect(() => {
const el = containerRef.current; const MARGIN = 8;
if (!el) return; const GAP = 6;
const h = el.getBoundingClientRect().height; const MIN_HEIGHT = 160;
const safeX = Math.min(Math.max(pos.x, 8), window.innerWidth - panelWidth - 8); const safeX = Math.min(Math.max(pos.x, MARGIN), window.innerWidth - panelWidth - MARGIN);
const spaceBelow = window.innerHeight - pos.y - 8; const spaceBelow = window.innerHeight - pos.y - MARGIN;
const spaceAbove = pos.y - 8; const spaceAbove = pos.y - MARGIN;
let safeY: number; if (spaceBelow >= spaceAbove) {
if (spaceBelow >= h) { // More space below — anchor top at selection bottom, grow downward
safeY = pos.y + 6; setComputedPos({
} else if (spaceAbove >= h) { left: safeX,
safeY = pos.y - h - 6; top: pos.y + GAP,
} else if (spaceBelow >= spaceAbove) { maxHeight: Math.max(MIN_HEIGHT, spaceBelow - GAP),
safeY = Math.max(8, window.innerHeight - h - 8); });
} else { } else {
safeY = 8; // More space above — anchor bottom at selection top, grow upward
setComputedPos({
left: safeX,
bottom: window.innerHeight - pos.y + GAP,
maxHeight: Math.max(MIN_HEIGHT, spaceAbove - GAP),
});
} }
setComputedPos({ left: safeX, top: safeY });
}, [pos.x, pos.y]); }, [pos.x, pos.y]);
const actionLabel = tone const actionLabel = tone
@@ -134,16 +142,18 @@ export function WritingRewritePreview({
<div className="fixed inset-0 z-[9990]" onMouseDown={onClose} /> <div className="fixed inset-0 z-[9990]" onMouseDown={onClose} />
<div <div
ref={containerRef}
style={{ style={{
position: "fixed", position: "fixed",
left: computedPos?.left ?? pos.x, left: computedPos?.left ?? pos.x,
top: computedPos?.top ?? (pos.y + 6), ...(computedPos?.bottom !== undefined
? { bottom: computedPos.bottom }
: { top: computedPos?.top ?? (pos.y + 6) }),
maxHeight: computedPos?.maxHeight,
width: panelWidth, width: panelWidth,
zIndex: 9999, zIndex: 9999,
visibility: computedPos ? "visible" : "hidden", visibility: computedPos ? "visible" : "hidden",
}} }}
className="rounded-xl border bg-popover shadow-xl animate-in fade-in zoom-in-95 duration-100 overflow-hidden" className="flex flex-col rounded-xl border bg-popover shadow-xl animate-in fade-in zoom-in-95 duration-100 overflow-hidden"
> >
{/* Header */} {/* Header */}
<div className="flex items-center justify-between px-3 py-2 border-b bg-muted/40"> <div className="flex items-center justify-between px-3 py-2 border-b bg-muted/40">
@@ -179,7 +189,7 @@ export function WritingRewritePreview({
</div> </div>
{/* Body */} {/* Body */}
<div className="p-3 space-y-2 max-h-96 overflow-y-auto"> <div className="p-3 space-y-2 overflow-y-auto flex-1 min-h-0">
{/* Thinking — collapsible with animation */} {/* Thinking — collapsible with animation */}
{thinking && ( {thinking && (