diff --git a/frontend/src/components/ContextMenu.tsx b/frontend/src/components/ContextMenu.tsx index bfeea1c49..7ad3efb46 100644 --- a/frontend/src/components/ContextMenu.tsx +++ b/frontend/src/components/ContextMenu.tsx @@ -24,6 +24,7 @@ export function ContextMenu({ x, y, items, onClose }: ContextMenuProps) { const submenuTimeoutRef = useRef(null); const [position, setPosition] = useState({ x, y, visible: false }); const [openSubmenuLeft, setOpenSubmenuLeft] = useState(false); + const [submenuPositions, setSubmenuPositions] = useState>({}); useEffect(() => { const handleClickOutside = (e: MouseEvent) => { @@ -100,11 +101,23 @@ export function ContextMenu({ x, y, items, onClose }: ContextMenuProps) { } }, [x, y]); - const handleMouseEnterSubmenu = (index: number) => { + const handleMouseEnterSubmenu = (index: number, element: HTMLElement) => { if (submenuTimeoutRef.current) { clearTimeout(submenuTimeoutRef.current); submenuTimeoutRef.current = null; } + + // Calculate if submenu should open upward or downward + const rect = element.getBoundingClientRect(); + const viewportHeight = window.innerHeight; + const submenuMaxHeight = 300; // matches max-h-[300px] + const padding = 8; + + // Check if there's enough space below for the submenu + const spaceBelow = viewportHeight - rect.top - padding; + const shouldOpenUpward = spaceBelow < submenuMaxHeight && rect.top > submenuMaxHeight; + + setSubmenuPositions(prev => ({ ...prev, [index]: shouldOpenUpward ? 'bottom' : 'top' })); setActiveSubmenu(index); }; @@ -135,11 +148,11 @@ export function ContextMenu({ x, y, items, onClose }: ContextMenuProps) {
hasSubmenu && handleMouseEnterSubmenu(index)} + onMouseEnter={(e) => hasSubmenu && handleMouseEnterSubmenu(index, e.currentTarget)} onMouseLeave={() => hasSubmenu && handleMouseLeaveSubmenu()} >