diff --git a/components/ui/context-menu.tsx b/components/ui/context-menu.tsx index 3f4c0d6b..bc0d942c 100644 --- a/components/ui/context-menu.tsx +++ b/components/ui/context-menu.tsx @@ -158,22 +158,41 @@ export function ContextMenuSubMenu({ children, }: ContextMenuSubMenuProps) { const [isOpen, setIsOpen] = useState(false); - const [subMenuPosition, setSubMenuPosition] = useState<"right" | "left">("right"); + const [subMenuPos, setSubMenuPos] = useState(null); const itemRef = useRef(null); const subMenuRef = useRef(null); const closeTimerRef = useRef | null>(null); - useEffect(() => { - if (isOpen && itemRef.current) { - const rect = itemRef.current.getBoundingClientRect(); - const viewportWidth = window.innerWidth; - - if (rect.right + 200 > viewportWidth - 10) { - setSubMenuPosition("left"); - } else { - setSubMenuPosition("right"); - } + useLayoutEffect(() => { + if (!isOpen) { + setSubMenuPos(null); + return; } + const itemEl = itemRef.current; + const subEl = subMenuRef.current; + if (!itemEl || !subEl) return; + + const itemRect = itemEl.getBoundingClientRect(); + const subRect = subEl.getBoundingClientRect(); + const vw = window.innerWidth; + const vh = window.innerHeight; + + let left: number; + if (itemRect.right + subRect.width <= vw - VIEWPORT_MARGIN) { + left = itemRect.right; + } else if (itemRect.left - subRect.width >= VIEWPORT_MARGIN) { + left = itemRect.left - subRect.width; + } else { + left = Math.max(VIEWPORT_MARGIN, vw - subRect.width - VIEWPORT_MARGIN); + } + + let top = itemRect.top; + if (top + subRect.height > vh - VIEWPORT_MARGIN) { + top = vh - subRect.height - VIEWPORT_MARGIN; + } + top = Math.max(VIEWPORT_MARGIN, top); + + setSubMenuPos({ x: left, y: top }); }, [isOpen]); useEffect(() => { @@ -220,13 +239,17 @@ export function ContextMenuSubMenu({
-
+
{children}