From 2706d511cebbc5e8f3ca8c787aa76be2f404f535 Mon Sep 17 00:00:00 2001 From: Nevo David Date: Fri, 5 Dec 2025 15:55:14 +0700 Subject: [PATCH] fix: hot fix for menu items --- .../src/components/launches/menu/menu.tsx | 42 +++++++++++++++---- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/apps/frontend/src/components/launches/menu/menu.tsx b/apps/frontend/src/components/launches/menu/menu.tsx index 55b3b768..bca334d1 100644 --- a/apps/frontend/src/components/launches/menu/menu.tsx +++ b/apps/frontend/src/components/launches/menu/menu.tsx @@ -1,11 +1,7 @@ 'use client'; import React, { - FC, - MouseEventHandler, - useCallback, - useMemo, - useState, + FC, MouseEventHandler, useCallback, useLayoutEffect, useMemo, useRef, useState } from 'react'; import { useClickOutside } from '@mantine/hooks'; import { useFetch } from '@gitroom/helpers/utils/custom.fetch'; @@ -60,17 +56,39 @@ export const Menu: FC<{ const { integrations, reloadCalendarView } = useCalendar(); const toast = useToaster(); const modal = useModals(); - const [show, setShow] = useState(false); + const [show, setShow] = useState(false); + const menuRef = useRef(null); const ref = useClickOutside(() => { setShow(false); }); + const showRef = useRef(); + + // Adjust menu position if it would overflow viewport + useLayoutEffect(() => { + if (show && menuRef.current) { + const menuRect = menuRef.current.getBoundingClientRect(); + const viewportHeight = window.innerHeight; + const padding = 10; + + // Check if menu overflows bottom of viewport + if (menuRect.bottom > viewportHeight - padding) { + const newY = Math.max(padding, viewportHeight - menuRect.height - padding); + // Only update if position actually changed significantly to avoid infinite loop + if (Math.abs(show.y - newY) > 1) { + setShow(prev => prev ? { ...prev, y: newY } : false); + } + } + } + }, [show]); const findIntegration: any = useMemo(() => { return integrations.find((integration) => integration.id === id); }, [integrations, id]); const changeShow: MouseEventHandler = useCallback( (e) => { e.stopPropagation(); - setShow(!show); + // @ts-ignore + const boundBox = showRef?.current?.getBoundingClientRect(); + setShow(show ? false : { x: boundBox?.left, y: boundBox?.top + boundBox?.height }); }, [show] ); @@ -284,9 +302,10 @@ export const Menu: FC<{ ), }); }, []); + return (
@@ -303,10 +322,15 @@ export const Menu: FC<{ fill="currentColor" /> +
+
+
{show && (
e.stopPropagation()} - className={`absolute top-[100%] start-0 p-[12px] bg-newBgColorInner shadow-menu flex flex-col gap-[16px] z-[100] rounded-[8px] border border-tableBorder text-nowrap`} + style={{left: show.x, top: show.y}} + className={`fixed p-[12px] bg-newBgColorInner shadow-menu flex flex-col gap-[16px] z-[100] rounded-[8px] border border-tableBorder text-nowrap`} > {canDisable && !findIntegration?.refreshNeeded && (