diff --git a/frontend/src/components/WorkspaceChat/ChatContainer/PromptInput/ToolsMenu/index.jsx b/frontend/src/components/WorkspaceChat/ChatContainer/PromptInput/ToolsMenu/index.jsx index a688e4f0..5437ed2e 100644 --- a/frontend/src/components/WorkspaceChat/ChatContainer/PromptInput/ToolsMenu/index.jsx +++ b/frontend/src/components/WorkspaceChat/ChatContainer/PromptInput/ToolsMenu/index.jsx @@ -1,4 +1,11 @@ -import { useState, useEffect, useCallback, useRef, useMemo } from "react"; +import { + useState, + useEffect, + useLayoutEffect, + useCallback, + useRef, + useMemo, +} from "react"; import { useTranslation } from "react-i18next"; import useUser from "@/hooks/useUser"; import AgentSkillsTab from "./Tabs/AgentSkills"; @@ -50,7 +57,9 @@ export default function ToolsMenu({ const TABS = useMemo(() => getTabs(t, user), [t, user]); const [activeTab, setActiveTab] = useState(TABS[0].key); const [highlightedIndex, setHighlightedIndex] = useState(-1); + const [maxHeight, setMaxHeight] = useState(360); const itemCountRef = useRef(0); + const popoverRef = useRef(null); // Always open to the slash commands useEffect(() => { @@ -62,6 +71,24 @@ export default function ToolsMenu({ setHighlightedIndex(-1); }, [activeTab, showing]); + // Constrain popover height to the space available in the viewport so it + // never overflows off-screen on shorter windows (e.g. centered home view). + useLayoutEffect(() => { + if (!showing) return; + const update = () => { + const el = popoverRef.current; + if (!el) return; + const rect = el.getBoundingClientRect(); + const available = centered + ? window.innerHeight - rect.top - 16 + : rect.bottom - 16; + setMaxHeight(Math.max(0, Math.min(360, available))); + }; + update(); + window.addEventListener("resize", update); + return () => window.removeEventListener("resize", update); + }, [showing, centered]); + // Keep the parent ref in sync so PromptInput can check it on Enter useEffect(() => { if (highlightedIndexRef) highlightedIndexRef.current = highlightedIndex; @@ -119,15 +146,15 @@ export default function ToolsMenu({ onClick={() => setShowing(false)} />