mirror of
https://github.com/aljazceru/goose.git
synced 2026-02-23 07:24:24 +01:00
feat: bottom bar text truncation and tooltips (#2324)
This commit is contained in:
@@ -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<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
|
||||
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 (
|
||||
<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 */}
|
||||
@@ -151,7 +171,23 @@ export default function BottomMenu({
|
||||
}}
|
||||
>
|
||||
<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" />
|
||||
</span>
|
||||
|
||||
|
||||
@@ -118,12 +118,14 @@ export const BottomMenuModeSelection = ({ setView }: BottomMenuModeSelectionProp
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="relative flex items-center ml-6" ref={gooseModeDropdownRef}>
|
||||
<div className="relative flex items-center" ref={gooseModeDropdownRef}>
|
||||
<div
|
||||
className="flex items-center cursor-pointer"
|
||||
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 ? (
|
||||
<ChevronDown className="w-4 h-4 ml-1" />
|
||||
) : (
|
||||
|
||||
@@ -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<HTMLDivElement>;
|
||||
@@ -17,6 +18,10 @@ export default function ModelsBottomBar({ dropdownRef, setView }: ModelsBottomBa
|
||||
const [model, setModel] = useState<string>('');
|
||||
const [isAddModelModalOpen, setIsAddModelModalOpen] = useState(false);
|
||||
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(() => {
|
||||
(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
|
||||
<div className="relative flex items-center ml-auto mr-4" ref={dropdownRef}>
|
||||
<div ref={menuRef} className="relative">
|
||||
<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)}
|
||||
>
|
||||
{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 ? (
|
||||
<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>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user