diff --git a/packages/ui/src/components/chat/message/TextSelectionMenu.tsx b/packages/ui/src/components/chat/message/TextSelectionMenu.tsx index 977f20b7..4dcce714 100644 --- a/packages/ui/src/components/chat/message/TextSelectionMenu.tsx +++ b/packages/ui/src/components/chat/message/TextSelectionMenu.tsx @@ -218,6 +218,7 @@ export const TextSelectionMenu: React.FC = ({ containerR const menuWidthRef = React.useRef(DESKTOP_MENU_FALLBACK_WIDTH_PX); const pendingSelectionRef = React.useRef(null); const openRafRef = React.useRef(null); + const mouseUpTimeoutRef = React.useRef(null); const isMenuVisibleRef = React.useRef(false); const createSession = useSessionUIStore((state) => state.createSession); const currentSessionId = useSessionUIStore((state) => state.currentSessionId); @@ -238,6 +239,10 @@ export const TextSelectionMenu: React.FC = ({ containerR window.cancelAnimationFrame(openRafRef.current); openRafRef.current = null; } + if (mouseUpTimeoutRef.current !== null) { + window.clearTimeout(mouseUpTimeoutRef.current); + mouseUpTimeoutRef.current = null; + } }; }, []); @@ -408,8 +413,12 @@ export const TextSelectionMenu: React.FC = ({ containerR isDraggingRef.current = false; // Check if we have a pending selection to show if (pendingSelectionRef.current) { + if (mouseUpTimeoutRef.current !== null) { + window.clearTimeout(mouseUpTimeoutRef.current); + } // Small delay to ensure selection is finalized - setTimeout(() => { + mouseUpTimeoutRef.current = window.setTimeout(() => { + mouseUpTimeoutRef.current = null; const selection = window.getSelection(); if (selection && selection.toString().trim()) { showMenu(); @@ -440,6 +449,10 @@ export const TextSelectionMenu: React.FC = ({ containerR document.addEventListener('mousedown', handleClickOutside); return () => { + if (mouseUpTimeoutRef.current !== null) { + window.clearTimeout(mouseUpTimeoutRef.current); + mouseUpTimeoutRef.current = null; + } document.removeEventListener('selectionchange', handleSelectionChange); container.removeEventListener('mousedown', handleMouseDown); document.removeEventListener('mouseup', handleMouseUp);