From c81bdeecb76b1e00b6d347151100c7e73dd97ad3 Mon Sep 17 00:00:00 2001 From: Dustin Healy <54083382+dustinhealy@users.noreply.github.com> Date: Thu, 27 Nov 2025 09:22:29 -0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=A7=B0=20feat:=20Accessible=20MCP=20Tool?= =?UTF-8?q?=20Lists=20(#10695)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: add aria-label for expansion chevron in Agent Builder's MCP tool list dropdown * fix: remove duplicate tool info button in MCPTool so it doesn't get picked up via keyboard nav (still exists on mouse hover as it should to provide tooltip description of tool) * feat: use InfoHoverCard rather than Ariakit components for tool descriptions * chore: remove unused i18n keys --- .../components/SidePanel/Agents/MCPTool.tsx | 71 +++++-------------- client/src/locales/en/translation.json | 6 +- 2 files changed, 20 insertions(+), 57 deletions(-) diff --git a/client/src/components/SidePanel/Agents/MCPTool.tsx b/client/src/components/SidePanel/Agents/MCPTool.tsx index e0217ed3ce..25d7c4c424 100644 --- a/client/src/components/SidePanel/Agents/MCPTool.tsx +++ b/client/src/components/SidePanel/Agents/MCPTool.tsx @@ -1,17 +1,17 @@ import React, { useState } from 'react'; -import * as Ariakit from '@ariakit/react'; import { ChevronDown } from 'lucide-react'; import { useFormContext } from 'react-hook-form'; import { Constants } from 'librechat-data-provider'; import * as AccordionPrimitive from '@radix-ui/react-accordion'; import { Label, + ESide, Checkbox, OGDialog, Accordion, TrashIcon, + InfoHoverCard, AccordionItem, - CircleHelpIcon, OGDialogTrigger, AccordionContent, OGDialogTemplate, @@ -31,7 +31,6 @@ export default function MCPTool({ serverInfo }: { serverInfo?: MCPServerInfo }) const [isFocused, setIsFocused] = useState(false); const [isHovering, setIsHovering] = useState(false); const [accordionValue, setAccordionValue] = useState(''); - const [hoveredToolId, setHoveredToolId] = useState(null); if (!serverInfo) { return null; @@ -183,7 +182,16 @@ export default function MCPTool({ serverInfo }: { serverInfo?: MCPServerInfo }) 'flex h-7 w-7 items-center justify-center rounded transition-colors duration-200 hover:bg-surface-active-alt focus:translate-x-0 focus:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-1', isExpanded && 'bg-surface-active-alt', )} - aria-hidden="true" + aria-label={ + isExpanded + ? localize('com_ui_tool_list_collapse', { + serverName: currentServerName, + }) + : localize('com_ui_tool_list_expand', { + serverName: currentServerName, + }) + } + aria-expanded={isExpanded} tabIndex={0} onFocus={() => setIsFocused(true)} > @@ -227,15 +235,13 @@ export default function MCPTool({ serverInfo }: { serverInfo?: MCPServerInfo }) key={subTool.tool_id} htmlFor={subTool.tool_id} className={cn( - 'border-token-border-light hover:bg-token-surface-secondary flex cursor-pointer items-center rounded-lg border p-2', + 'group/item border-token-border-light hover:bg-token-surface-secondary flex cursor-pointer items-center rounded-lg border p-2', 'ml-2 mr-1 focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2 focus-within:ring-offset-background', )} onClick={(e) => e.stopPropagation()} onKeyDown={(e) => { e.stopPropagation(); }} - onMouseEnter={() => setHoveredToolId(subTool.tool_id)} - onMouseLeave={() => setHoveredToolId(null)} > {subTool.metadata.description && ( - -
- - - - {localize('com_ui_tool_info')} - - - } - /> - - - {localize('com_ui_tool_more_info')} - - - -
- -
-

- {subTool.metadata.description} -

-
-
-
+
+ +
)} ))} diff --git a/client/src/locales/en/translation.json b/client/src/locales/en/translation.json index a873753db7..6930ecfef4 100644 --- a/client/src/locales/en/translation.json +++ b/client/src/locales/en/translation.json @@ -782,6 +782,7 @@ "com_ui_close_settings": "Close Settings", "com_ui_close_window": "Close Window", "com_ui_code": "Code", + "com_ui_collapse": "Collapse", "com_ui_collapse_chat": "Collapse Chat", "com_ui_command_placeholder": "Optional: Enter a command for the prompt or name will be used", "com_ui_command_usage_placeholder": "Select a Prompt by command or name", @@ -918,6 +919,7 @@ "com_ui_error_updating_preferences": "Error updating preferences", "com_ui_everyone_permission_level": "Everyone's permission level", "com_ui_examples": "Examples", + "com_ui_expand": "Expand", "com_ui_expand_chat": "Expand Chat", "com_ui_export_convo_modal": "Export Conversation Modal", "com_ui_feedback_more": "More...", @@ -1282,8 +1284,8 @@ "com_ui_token_url": "Token URL", "com_ui_tokens": "tokens", "com_ui_tool_collection_prefix": "A collection of tools from", - "com_ui_tool_info": "Tool Information", - "com_ui_tool_more_info": "More information about this tool", + "com_ui_tool_list_collapse": "Collapse {{serverName}} tool list", + "com_ui_tool_list_expand": "Expand {{serverName}} tool list", "com_ui_tools": "Tools", "com_ui_tools_and_actions": "Tools and Actions", "com_ui_transferred_to": "Transferred to",