feat: bottom bar text truncation and tooltips (#2324)

This commit is contained in:
Best Codes
2025-04-24 17:44:56 -05:00
committed by GitHub
parent 9805d31734
commit bae5b0c0c0
3 changed files with 84 additions and 10 deletions
@@ -1,4 +1,4 @@
import React, { useState, useEffect, useRef } from 'react'; import { useState, useEffect, useRef } from 'react';
import { useModel } from '../settings/models/ModelContext'; import { useModel } from '../settings/models/ModelContext';
import { Sliders } from 'lucide-react'; import { Sliders } from 'lucide-react';
import { AlertType, useAlerts } from '../alerts'; import { AlertType, useAlerts } from '../alerts';
@@ -12,6 +12,7 @@ import { BottomMenuModeSelection } from './BottomMenuModeSelection';
import ModelsBottomBar from '../settings_v2/models/bottom_bar/ModelsBottomBar'; import ModelsBottomBar from '../settings_v2/models/bottom_bar/ModelsBottomBar';
import { useConfig } from '../ConfigContext'; import { useConfig } from '../ConfigContext';
import { getCurrentModelAndProvider } from '../settings_v2/models'; 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_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 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 toolCount = useToolCount();
const { getProviders, read } = useConfig(); const { getProviders, read } = useConfig();
const [tokenLimit, setTokenLimit] = useState<number>(TOKEN_LIMIT_DEFAULT); const [tokenLimit, setTokenLimit] = useState<number>(TOKEN_LIMIT_DEFAULT);
const [isDirTruncated, setIsDirTruncated] = useState(false);
// eslint-disable-next-line no-undef
const dirRef = useRef<HTMLSpanElement>(null);
const [isTooltipOpen, setIsTooltipOpen] = useState(false);
// Load providers and get current model's token limit // Load providers and get current model's token limit
const loadProviderDetails = async () => { const loadProviderDetails = async () => {
@@ -137,6 +142,21 @@ export default function BottomMenu({
}; };
}, [isModelMenuOpen]); }, [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 ( return (
<div className="flex justify-between items-center text-textSubtle relative bg-bgSubtle border-t border-borderSubtle text-xs pl-4 h-[40px] pb-1 align-middle"> <div className="flex justify-between items-center text-textSubtle relative bg-bgSubtle border-t border-borderSubtle text-xs pl-4 h-[40px] pb-1 align-middle">
{/* Directory Chooser - Always visible */} {/* Directory Chooser - Always visible */}
@@ -151,7 +171,23 @@ export default function BottomMenu({
}} }}
> >
<Document className="mr-1" /> <Document className="mr-1" />
Working in {window.appConfig.get('GOOSE_WORKING_DIR')} <TooltipProvider>
<Tooltip open={isTooltipOpen} onOpenChange={setIsTooltipOpen}>
<TooltipTrigger asChild>
<span
ref={dirRef}
className="truncate max-w-[170px] md:max-w-[200px] lg:max-w-[380px] min-w-0 block"
>
Working in {window.appConfig.get('GOOSE_WORKING_DIR') as string}
</span>
</TooltipTrigger>
{isDirTruncated && (
<TooltipContent className="max-w-96 overflow-auto scrollbar-thin" side="top">
{window.appConfig.get('GOOSE_WORKING_DIR') as string}
</TooltipContent>
)}
</Tooltip>
</TooltipProvider>
<ChevronUp className="ml-1" /> <ChevronUp className="ml-1" />
</span> </span>
@@ -118,12 +118,14 @@ export const BottomMenuModeSelection = ({ setView }: BottomMenuModeSelectionProp
} }
return ( return (
<div className="relative flex items-center ml-6" ref={gooseModeDropdownRef}> <div className="relative flex items-center" ref={gooseModeDropdownRef}>
<div <div
className="flex items-center cursor-pointer" className="flex items-center cursor-pointer"
onClick={() => setIsGooseModeMenuOpen(!isGooseModeMenuOpen)} onClick={() => setIsGooseModeMenuOpen(!isGooseModeMenuOpen)}
> >
<span className="truncate w-[170px]">Goose Mode: {getValueByKey(gooseMode)}</span> <span className="truncate max-w-[170px] md:max-w-[200px] lg:max-w-[380px]">
Goose Mode: {getValueByKey(gooseMode)}
</span>
{isGooseModeMenuOpen ? ( {isGooseModeMenuOpen ? (
<ChevronDown className="w-4 h-4 ml-1" /> <ChevronDown className="w-4 h-4 ml-1" />
) : ( ) : (
@@ -5,6 +5,7 @@ import { useConfig } from '../../../ConfigContext';
import { getCurrentModelAndProviderForDisplay } from '../index'; import { getCurrentModelAndProviderForDisplay } from '../index';
import { AddModelModal } from '../subcomponents/AddModelModal'; import { AddModelModal } from '../subcomponents/AddModelModal';
import { View } from '../../../../App'; import { View } from '../../../../App';
import { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from '../../../ui/Tooltip';
interface ModelsBottomBarProps { interface ModelsBottomBarProps {
dropdownRef: React.RefObject<HTMLDivElement>; dropdownRef: React.RefObject<HTMLDivElement>;
@@ -17,6 +18,10 @@ export default function ModelsBottomBar({ dropdownRef, setView }: ModelsBottomBa
const [model, setModel] = useState<string>(''); const [model, setModel] = useState<string>('');
const [isAddModelModalOpen, setIsAddModelModalOpen] = useState(false); const [isAddModelModalOpen, setIsAddModelModalOpen] = useState(false);
const menuRef = useRef<HTMLDivElement>(null); const menuRef = useRef<HTMLDivElement>(null);
const [isModelTruncated, setIsModelTruncated] = useState(false);
// eslint-disable-next-line no-undef
const modelRef = useRef<HTMLSpanElement>(null);
const [isTooltipOpen, setIsTooltipOpen] = useState(false);
useEffect(() => { useEffect(() => {
(async () => { (async () => {
@@ -24,11 +29,26 @@ export default function ModelsBottomBar({ dropdownRef, setView }: ModelsBottomBa
readFromConfig: read, readFromConfig: read,
getProviders, getProviders,
}); });
setProvider(modelProvider.provider); setProvider(modelProvider.provider as string | null);
setModel(modelProvider.model); 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 // Add click outside handler
useEffect(() => { useEffect(() => {
function handleClickOutside(event: MouseEvent) { function handleClickOutside(event: MouseEvent) {
@@ -52,14 +72,30 @@ export default function ModelsBottomBar({ dropdownRef, setView }: ModelsBottomBa
<div className="relative flex items-center ml-auto mr-4" ref={dropdownRef}> <div className="relative flex items-center ml-auto mr-4" ref={dropdownRef}>
<div ref={menuRef} className="relative"> <div ref={menuRef} className="relative">
<div <div
className="flex items-center cursor-pointer" className="flex items-center cursor-pointer max-w-[180px] md:max-w-[200px] lg:max-w-[380px] min-w-0 group"
onClick={() => setIsModelMenuOpen(!isModelMenuOpen)} onClick={() => setIsModelMenuOpen(!isModelMenuOpen)}
> >
{model} <TooltipProvider>
<Tooltip open={isTooltipOpen} onOpenChange={setIsTooltipOpen}>
<TooltipTrigger asChild>
<span
ref={modelRef}
className="truncate max-w-[130px] md:max-w-[200px] lg:max-w-[360px] min-w-0 block"
>
{model || 'Select Model'}
</span>
</TooltipTrigger>
{isModelTruncated && (
<TooltipContent className="max-w-96 overflow-auto scrollbar-thin" side="top">
{model || 'Select Model'}
</TooltipContent>
)}
</Tooltip>
</TooltipProvider>
{isModelMenuOpen ? ( {isModelMenuOpen ? (
<ChevronDown className="w-4 h-4 ml-1" /> <ChevronDown className="w-4 h-4 ml-1 flex-shrink-0" />
) : ( ) : (
<ChevronUp className="w-4 h-4 ml-1" /> <ChevronUp className="w-4 h-4 ml-1 flex-shrink-0" />
)} )}
</div> </div>