From 8c510a380a9ebdefac561c2db94852d4ab135fc7 Mon Sep 17 00:00:00 2001 From: LordMelkor Date: Thu, 17 Jul 2025 13:51:57 -0400 Subject: [PATCH] feat: Add extension name tooltips with improved loading UI and DRY code Implements extension name tooltips on tool banners, combining the best of both the original feature and the latest main branch improvements: Features: - Extension name tooltips (e.g., "memory extension") appear on hover for tools that belong to extensions (identified by __ separator in tool names) - Enhanced loading indicators with LoaderCircle animation and improved layout - DRY code implementation that eliminates duplication in tool label rendering Implementation: - Add TooltipWrapper import for tooltip functionality - Add getExtensionTooltip() helper to extract extension names from tool names - Add getToolLabelContent() helper to eliminate code duplication - Use conditional styling with cn() utility for tooltip-specific classes - Preserve all main branch UI improvements (LoaderCircle, layout structure) - Conditionally wrap tool labels with TooltipWrapper when extension detected The tooltip appears with "top" positioning and "start" alignment, providing contextual information about which extension provides each tool without cluttering the interface. --- .../src/components/ToolCallWithResponse.tsx | 48 +++++++++++++++---- 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/ui/desktop/src/components/ToolCallWithResponse.tsx b/ui/desktop/src/components/ToolCallWithResponse.tsx index f5daabfe5ec8..a75a7065201c 100644 --- a/ui/desktop/src/components/ToolCallWithResponse.tsx +++ b/ui/desktop/src/components/ToolCallWithResponse.tsx @@ -7,6 +7,7 @@ import { cn, snakeToTitleCase } from '../utils'; import Dot, { LoadingStatus } from './ui/Dot'; import { NotificationEvent } from '../hooks/useMessageStream'; import { ChevronRight, LoaderCircle } from 'lucide-react'; +import { TooltipWrapper } from './settings/providers/subcomponents/buttons/TooltipWrapper'; interface ToolCallWithResponseProps { isCancelledMessage: boolean; @@ -121,6 +122,17 @@ const logToString = (logMessage: NotificationEvent) => { const notificationToProgress = (notification: NotificationEvent): Progress => notification.message.params as unknown as Progress; +// Helper function to extract extension name for tooltip +const getExtensionTooltip = (toolCallName: string): string | null => { + const lastIndex = toolCallName.lastIndexOf('__'); + if (lastIndex === -1) return null; + + const extensionName = toolCallName.substring(0, lastIndex); + if (!extensionName) return null; + + return `${extensionName} extension`; +}; + function ToolCallView({ isCancelledMessage, toolCall, @@ -387,6 +399,25 @@ function ToolCallView({ return null; }; + // Get extension tooltip for the current tool + const extensionTooltip = getExtensionTooltip(toolCall.name); + + // Extract tool label content to avoid duplication + const getToolLabelContent = () => { + const description = getToolDescription(); + if (description) { + return description; + } + // Fallback tool name formatting + return snakeToTitleCase(toolCall.name.substring(toolCall.name.lastIndexOf('__') + 2)); + }; + + const toolLabel = ( + + {getToolLabelContent()} + + ); + return ( )} - - {(() => { - const description = getToolDescription(); - if (description) { - return description; - } - // Fallback tool name formatting - return snakeToTitleCase(toolCall.name.substring(toolCall.name.lastIndexOf('__') + 2)); - })()} - + {extensionTooltip ? ( + + {toolLabel} + + ) : ( + toolLabel + )} } >