diff --git a/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/menus/bubble-menu.tsx b/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/menus/bubble-menu.tsx index 785e7c24d21..160657905fe 100644 --- a/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/menus/bubble-menu.tsx +++ b/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/menus/bubble-menu.tsx @@ -179,14 +179,13 @@ export function EditorBubbleMenu({ setLinkValue(null) } - const { resolveAnchor, options, appendTo } = useBubbleMenuFloating(editor, scrollContainerRef) + const { resolveAnchor, appendTo } = useBubbleMenuFloating(editor, scrollContainerRef) return ( ` so a clipping or transformed ancestor can't reparent or shift it. */ -const appendTo = () => document.body - -/** - * Wires a BubbleMenu's Floating UI concerns — the selection anchor, positioning options, and the - * body portal — so the text and table toolbars share one source of truth and can't drift. Captures - * the parent-owned scroll container into state so `options` gains a new identity once the element - * resolves, which is what makes the BubbleMenu bind its scroll listener to the pane. + * Wires a BubbleMenu's Floating UI concerns — the selection anchor and the portal target — so the + * text and table toolbars share one source of truth and can't drift. + * + * The toolbar is appended into the editor's scroll container (which must be a positioning context) + * and left at TipTap's default `absolute` strategy, so it becomes an absolutely-positioned child of + * the scrolled content and tracks the selection through native scrolling — no scroll listener, so no + * lag or "chase" as the pane scrolls. TipTap's default `flip` still parks it above or below the + * selection at the pane edges, and the container's overflow clips it once the selection scrolls out. */ export function useBubbleMenuFloating( editor: Editor, scrollContainerRef: React.RefObject ) { - const [scrollTarget, setScrollTarget] = useState(null) - - useEffect(() => { - setScrollTarget(scrollContainerRef.current) - }, [scrollContainerRef]) - const resolveAnchor = useCallback(() => selectionVirtualElement(editor), [editor]) - const options = useMemo(() => bubbleMenuFloatingOptions(scrollTarget), [scrollTarget]) + const appendTo = useCallback( + () => scrollContainerRef.current ?? document.body, + [scrollContainerRef] + ) - return { resolveAnchor, options, appendTo } + return { resolveAnchor, appendTo } } diff --git a/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/rich-markdown-editor.tsx b/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/rich-markdown-editor.tsx index 447c8aebb2e..f00c89f7a0c 100644 --- a/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/rich-markdown-editor.tsx +++ b/apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/rich-markdown-editor.tsx @@ -1204,7 +1204,7 @@ export function LoadedRichMarkdownEditor({ return (
{editor && (