diff --git a/ui/desktop/src/components/bottom_menu/BottomMenu.tsx b/ui/desktop/src/components/bottom_menu/BottomMenu.tsx index 25fab978..8537bc59 100644 --- a/ui/desktop/src/components/bottom_menu/BottomMenu.tsx +++ b/ui/desktop/src/components/bottom_menu/BottomMenu.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect, useRef } from 'react'; +import { useState, useEffect, useRef } from 'react'; import { useModel } from '../settings/models/ModelContext'; import { Sliders } from 'lucide-react'; import { AlertType, useAlerts } from '../alerts'; @@ -12,6 +12,7 @@ import { BottomMenuModeSelection } from './BottomMenuModeSelection'; import ModelsBottomBar from '../settings_v2/models/bottom_bar/ModelsBottomBar'; import { useConfig } from '../ConfigContext'; import { getCurrentModelAndProvider } from '../settings_v2/models'; +import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '../ui/Tooltip'; const TOKEN_LIMIT_DEFAULT = 128000; // fallback for custom models that the backend doesn't know about const TOKEN_WARNING_THRESHOLD = 0.8; // warning shows at 80% of the token limit @@ -33,6 +34,10 @@ export default function BottomMenu({ const toolCount = useToolCount(); const { getProviders, read } = useConfig(); const [tokenLimit, setTokenLimit] = useState(TOKEN_LIMIT_DEFAULT); + const [isDirTruncated, setIsDirTruncated] = useState(false); + // eslint-disable-next-line no-undef + const dirRef = useRef(null); + const [isTooltipOpen, setIsTooltipOpen] = useState(false); // Load providers and get current model's token limit const loadProviderDetails = async () => { @@ -137,6 +142,21 @@ export default function BottomMenu({ }; }, [isModelMenuOpen]); + useEffect(() => { + const checkTruncation = () => { + if (dirRef.current) { + setIsDirTruncated(dirRef.current.scrollWidth > dirRef.current.clientWidth); + } + }; + checkTruncation(); + window.addEventListener('resize', checkTruncation); + return () => window.removeEventListener('resize', checkTruncation); + }, []); + + useEffect(() => { + setIsTooltipOpen(false); + }, [isDirTruncated]); + return (
{/* Directory Chooser - Always visible */} @@ -151,7 +171,23 @@ export default function BottomMenu({ }} > - Working in {window.appConfig.get('GOOSE_WORKING_DIR')} + + + + + Working in {window.appConfig.get('GOOSE_WORKING_DIR') as string} + + + {isDirTruncated && ( + + {window.appConfig.get('GOOSE_WORKING_DIR') as string} + + )} + + diff --git a/ui/desktop/src/components/bottom_menu/BottomMenuModeSelection.tsx b/ui/desktop/src/components/bottom_menu/BottomMenuModeSelection.tsx index d6f4e12c..6858c89b 100644 --- a/ui/desktop/src/components/bottom_menu/BottomMenuModeSelection.tsx +++ b/ui/desktop/src/components/bottom_menu/BottomMenuModeSelection.tsx @@ -118,12 +118,14 @@ export const BottomMenuModeSelection = ({ setView }: BottomMenuModeSelectionProp } return ( -
+
setIsGooseModeMenuOpen(!isGooseModeMenuOpen)} > - Goose Mode: {getValueByKey(gooseMode)} + + Goose Mode: {getValueByKey(gooseMode)} + {isGooseModeMenuOpen ? ( ) : ( diff --git a/ui/desktop/src/components/settings_v2/models/bottom_bar/ModelsBottomBar.tsx b/ui/desktop/src/components/settings_v2/models/bottom_bar/ModelsBottomBar.tsx index 406545c2..52e4f340 100644 --- a/ui/desktop/src/components/settings_v2/models/bottom_bar/ModelsBottomBar.tsx +++ b/ui/desktop/src/components/settings_v2/models/bottom_bar/ModelsBottomBar.tsx @@ -5,6 +5,7 @@ import { useConfig } from '../../../ConfigContext'; import { getCurrentModelAndProviderForDisplay } from '../index'; import { AddModelModal } from '../subcomponents/AddModelModal'; import { View } from '../../../../App'; +import { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from '../../../ui/Tooltip'; interface ModelsBottomBarProps { dropdownRef: React.RefObject; @@ -17,6 +18,10 @@ export default function ModelsBottomBar({ dropdownRef, setView }: ModelsBottomBa const [model, setModel] = useState(''); const [isAddModelModalOpen, setIsAddModelModalOpen] = useState(false); const menuRef = useRef(null); + const [isModelTruncated, setIsModelTruncated] = useState(false); + // eslint-disable-next-line no-undef + const modelRef = useRef(null); + const [isTooltipOpen, setIsTooltipOpen] = useState(false); useEffect(() => { (async () => { @@ -24,11 +29,26 @@ export default function ModelsBottomBar({ dropdownRef, setView }: ModelsBottomBa readFromConfig: read, getProviders, }); - setProvider(modelProvider.provider); - setModel(modelProvider.model); + setProvider(modelProvider.provider as string | null); + setModel(modelProvider.model as string); })(); }); + useEffect(() => { + const checkTruncation = () => { + if (modelRef.current) { + setIsModelTruncated(modelRef.current.scrollWidth > modelRef.current.clientWidth); + } + }; + checkTruncation(); + window.addEventListener('resize', checkTruncation); + return () => window.removeEventListener('resize', checkTruncation); + }, [model]); + + useEffect(() => { + setIsTooltipOpen(false); + }, [isModelTruncated]); + // Add click outside handler useEffect(() => { function handleClickOutside(event: MouseEvent) { @@ -52,14 +72,30 @@ export default function ModelsBottomBar({ dropdownRef, setView }: ModelsBottomBa
setIsModelMenuOpen(!isModelMenuOpen)} > - {model} + + + + + {model || 'Select Model'} + + + {isModelTruncated && ( + + {model || 'Select Model'} + + )} + + {isModelMenuOpen ? ( - + ) : ( - + )}