From 418b1eae65353e506dfc87d37bac39fe2f062c4d Mon Sep 17 00:00:00 2001 From: Sergey Kozyrenko Date: Tue, 7 Jul 2026 19:54:30 +0700 Subject: [PATCH] fix(markdown-editor): write the table-grip open ref synchronously to close a race MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit openRef was mirrored from the `open` state through a passive effect, but the document-level mousemove handler and the stale-target droppers read openRef.current on continuous events. Between a grip click (setOpen) and the effect flush, a mousemove saw the stale null and retargeted the grip — and the about-to-open menu — onto a neighbouring cell. Set the ref synchronously inside onMenuChange before setOpen and drop the mirroring effect. Co-Authored-By: Claude Opus 4.8 --- .../markdown-editor-table-handles.tsx | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/frontend/src/components/shared/markdown-editor/markdown-editor-table-handles.tsx b/frontend/src/components/shared/markdown-editor/markdown-editor-table-handles.tsx index b8298a55..769528bf 100644 --- a/frontend/src/components/shared/markdown-editor/markdown-editor-table-handles.tsx +++ b/frontend/src/components/shared/markdown-editor/markdown-editor-table-handles.tsx @@ -248,10 +248,6 @@ function useTableHandles(editor: Editor): TableHandlesController { const openRef = useRef(null); const cellPosRef = useRef(null); - useEffect(() => { - openRef.current = open; - }, [open]); - useEffect(() => { const dom = editor.view.dom; @@ -367,7 +363,13 @@ function useTableHandles(editor: Editor): TableHandlesController { }, [editor]); const onMenuChange = (menu: 'column' | 'row') => (isOpen: boolean) => { - setOpen(isOpen ? menu : null); + const next = isOpen ? menu : null; + + // Write the ref synchronously, before setOpen. handleMove/dropStaleTarget are continuous-event handlers + // reading openRef.current; mirroring `open` through a passive effect flushes a tick late, so a mousemove + // in that window would retarget the grip to a neighbouring cell just as a menu opens on this one. + openRef.current = next; + setOpen(next); if (!isOpen) { cellPosRef.current = null;