From 817e69a9eb06792af44a9598c3d473a3b8c5d9c5 Mon Sep 17 00:00:00 2001 From: Naiyuan Qing <145280634+NevilleQingNY@users.noreply.github.com> Date: Wed, 15 Apr 2026 13:49:33 +0800 Subject: [PATCH] fix(editor): fix bubble menu positioning on first selection Tiptap's React wrapper initialises the menu element with position:absolute, but computePosition needs position:fixed so getOffsetParent returns the viewport instead of a positioned ancestor. On the first show, coordinates were computed relative to the wrong containing block, causing the menu to fly off-screen (negative coords). Fix: set position:fixed in the onShow callback, which fires right before updatePosition(), ensuring computePosition sees the correct offset parent. Co-Authored-By: Claude Opus 4.6 (1M context) --- packages/views/editor/bubble-menu.tsx | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/packages/views/editor/bubble-menu.tsx b/packages/views/editor/bubble-menu.tsx index 384c486f3..e7aa81ae5 100644 --- a/packages/views/editor/bubble-menu.tsx +++ b/packages/views/editor/bubble-menu.tsx @@ -359,6 +359,7 @@ function ListDropdown({ editor, onOpenChange, isBullet, isOrdered }: { editor: E function EditorBubbleMenu({ editor }: { editor: Editor }) { const [mode, setMode] = useState<"toolbar" | "link-edit">("toolbar"); const [scrollTarget, setScrollTarget] = useState(window); + const menuElRef = useRef(null); // Precise subscription to formatting state — only re-renders when these // values actually change, replacing direct editor.isActive() calls that @@ -456,6 +457,7 @@ function EditorBubbleMenu({ editor }: { editor: Editor }) { return ( { + if (menuElRef.current) { + menuElRef.current.style.position = "fixed"; + } + }, }} > {mode === "link-edit" ? (