diff --git a/web/app/components/base/tooltip/TooltipManager.ts b/web/app/components/base/tooltip/TooltipManager.ts index e1b7f7ba9d..b0138af4b3 100644 --- a/web/app/components/base/tooltip/TooltipManager.ts +++ b/web/app/components/base/tooltip/TooltipManager.ts @@ -11,6 +11,17 @@ class TooltipManager { if (this.activeCloser === closeFn) this.activeCloser = null } + + /** + * Closes the currently active tooltip by calling its closer function + * and clearing the reference to it + */ + closeActiveTooltip() { + if (this.activeCloser) { + this.activeCloser() + this.activeCloser = null + } + } } export const tooltipManager = new TooltipManager() diff --git a/web/app/components/header/account-setting/model-provider-page/model-selector/popup.tsx b/web/app/components/header/account-setting/model-provider-page/model-selector/popup.tsx index 63849bddda..0449ded1e4 100644 --- a/web/app/components/header/account-setting/model-provider-page/model-selector/popup.tsx +++ b/web/app/components/header/account-setting/model-provider-page/model-selector/popup.tsx @@ -1,5 +1,5 @@ import type { FC } from 'react' -import { useMemo, useState } from 'react' +import { useEffect, useMemo, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' import { RiArrowRightUpLine, @@ -16,6 +16,7 @@ import PopupItem from './popup-item' import { XCircle } from '@/app/components/base/icons/src/vender/solid/general' import { useModalContext } from '@/context/modal-context' import { supportFunctionCall } from '@/utils/tool-call' +import { tooltipManager } from '@/app/components/base/tooltip/TooltipManager' type PopupProps = { defaultModel?: DefaultModel @@ -35,6 +36,25 @@ const Popup: FC = ({ const language = useLanguage() const [searchText, setSearchText] = useState('') const { setShowAccountSettingModal } = useModalContext() + const scrollRef = useRef(null) + + // Close any open tooltips when the user scrolls to prevent them from appearing + // in incorrect positions or becoming detached from their trigger elements + useEffect(() => { + const handleTooltipCloseOnScroll = () => { + tooltipManager.closeActiveTooltip() + } + + const scrollContainer = scrollRef.current + if (!scrollContainer) return + + // Use passive listener for better performance since we don't prevent default + scrollContainer.addEventListener('scroll', handleTooltipCloseOnScroll, { passive: true }) + + return () => { + scrollContainer.removeEventListener('scroll', handleTooltipCloseOnScroll) + } + }, []) const filteredModelList = useMemo(() => { return modelList.map((model) => { @@ -60,7 +80,7 @@ const Popup: FC = ({ }, [language, modelList, scopeFeatures, searchText]) return ( -
+