From b768e0affbc6fef7a41f1d65a22f5b74c27aca39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=91=A3=E5=AE=8F=E5=87=AF?= Date: Sun, 17 May 2026 20:38:35 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=B9=E5=86=99=E5=BC=B9=E7=AA=97=E5=87=BA?= =?UTF-8?q?=E7=8E=B0=E7=9A=84=E4=BD=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../artifact/WritingRewritePreview.tsx | 52 +++++++++++-------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/frontend-web/src/open-canvas/components/artifact/WritingRewritePreview.tsx b/frontend-web/src/open-canvas/components/artifact/WritingRewritePreview.tsx index 907ea73c..02f24a58 100644 --- a/frontend-web/src/open-canvas/components/artifact/WritingRewritePreview.tsx +++ b/frontend-web/src/open-canvas/components/artifact/WritingRewritePreview.tsx @@ -101,27 +101,35 @@ export function WritingRewritePreview({ // ── Position ──────────────────────────────────────────────────────────── const panelWidth = 480; - const containerRef = useRef(null); - const [computedPos, setComputedPos] = useState<{ left: number; top: number } | null>(null); + const [computedPos, setComputedPos] = useState<{ + left: number; + top?: number; + bottom?: number; + maxHeight: number; + } | null>(null); useLayoutEffect(() => { - const el = containerRef.current; - if (!el) return; - const h = el.getBoundingClientRect().height; - const safeX = Math.min(Math.max(pos.x, 8), window.innerWidth - panelWidth - 8); - const spaceBelow = window.innerHeight - pos.y - 8; - const spaceAbove = pos.y - 8; - let safeY: number; - if (spaceBelow >= h) { - safeY = pos.y + 6; - } else if (spaceAbove >= h) { - safeY = pos.y - h - 6; - } else if (spaceBelow >= spaceAbove) { - safeY = Math.max(8, window.innerHeight - h - 8); + const MARGIN = 8; + const GAP = 6; + const MIN_HEIGHT = 160; + const safeX = Math.min(Math.max(pos.x, MARGIN), window.innerWidth - panelWidth - MARGIN); + const spaceBelow = window.innerHeight - pos.y - MARGIN; + const spaceAbove = pos.y - MARGIN; + if (spaceBelow >= spaceAbove) { + // More space below — anchor top at selection bottom, grow downward + setComputedPos({ + left: safeX, + top: pos.y + GAP, + maxHeight: Math.max(MIN_HEIGHT, spaceBelow - GAP), + }); } 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]); const actionLabel = tone @@ -134,16 +142,18 @@ export function WritingRewritePreview({
{/* Header */}
@@ -179,7 +189,7 @@ export function WritingRewritePreview({
{/* Body */} -
+
{/* Thinking — collapsible with animation */} {thinking && (