From e0c5ca99697f283d7d95c0b0fb3af9e8c12206f6 Mon Sep 17 00:00:00 2001 From: Ajax Davis Date: Thu, 4 Dec 2025 18:20:33 +1000 Subject: [PATCH] feat(playground): enhance tool list UI with package names and detail modal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add two major UX improvements to the ToolsSidebar: 1. Package Name Display - Show package name as secondary label below tool name - Improves tool identification at a glance 2. Tool Detail Modal - Click any tool card to open detailed modal - Shows comprehensive information: * Tool name, package, version, category * Quality score (if available) * Full description * Supported frameworks (badges) * Environment variables (with required flag) * Import URL (for manual integration) * Tool ID (for debugging) - Modal features: * Backdrop blur effect * Click outside or press Escape to close * Close button (X icon) with SVG title * Responsive layout (max-w-2xl) * Scrollable content (max-h-90vh) * Full keyboard accessibility (ARIA labels, tabIndex, Escape key) 3. Enhanced Tool Interface - Added optional fields: toolId, qualityScore, frameworks, env, importUrl - Maintains backward compatibility with existing API This gives users full visibility into tool metadata and helps them understand what each tool does before using it in conversations. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../src/components/sidebar/ToolsSidebar.tsx | 217 ++++++++++++++---- 1 file changed, 176 insertions(+), 41 deletions(-) diff --git a/apps/playground/src/components/sidebar/ToolsSidebar.tsx b/apps/playground/src/components/sidebar/ToolsSidebar.tsx index 34687ef..30fac3a 100644 --- a/apps/playground/src/components/sidebar/ToolsSidebar.tsx +++ b/apps/playground/src/components/sidebar/ToolsSidebar.tsx @@ -6,17 +6,23 @@ import { Input } from '@tpmjs/ui/Input/Input'; import { useEffect, useState } from 'react'; interface Tool { + toolId?: string; packageName: string; exportName: string; description: string; category: string; version: string; + qualityScore?: number; + frameworks?: string[]; + env?: Record; + importUrl?: string; } export function ToolsSidebar(): React.ReactElement { const [tools, setTools] = useState([]); const [loading, setLoading] = useState(true); const [filter, setFilter] = useState(''); + const [selectedTool, setSelectedTool] = useState(null); useEffect(() => { async function fetchTools() { @@ -44,49 +50,178 @@ export function ToolsSidebar(): React.ReactElement { ); return ( - + + {/* Tool Details Modal */} + {selectedTool && ( + {/* biome-ignore lint/a11y/useSemanticElements: Modal backdrop - standard pattern for modal overlays with role=button */} +
setSelectedTool(null)} + onKeyDown={(e) => { + if (e.key === 'Escape') setSelectedTool(null); + }} + role="button" + tabIndex={0} + aria-label="Close modal" + > + {/* biome-ignore lint/a11y/useKeyWithClickEvents: Modal content - prevents click-through to backdrop */} +
e.stopPropagation()} + > + {/* Close button */} + + + {/* Tool header */} +
+

{selectedTool.exportName}

+

{selectedTool.packageName}

+
+ {selectedTool.category} + v{selectedTool.version} + {selectedTool.qualityScore && ( + + Score: {(selectedTool.qualityScore * 100).toFixed(0)}% + + )} +
+
+ + {/* Description */} +
+

Description

+

{selectedTool.description}

+
+ + {/* Frameworks */} + {selectedTool.frameworks && selectedTool.frameworks.length > 0 && ( +
+

Frameworks

+
+ {selectedTool.frameworks.map((framework) => ( + + {framework} + + ))} +
+
+ )} + + {/* Environment Variables */} + {selectedTool.env && Object.keys(selectedTool.env).length > 0 && ( +
+

+ Environment Variables +

+
+ {Object.entries(selectedTool.env).map(([key, config]) => ( +
+
+ {key} + {config.required && ( + + Required + + )} +
+

{config.description}

+
+ ))} +
+
+ )} + + {/* Import URL */} + {selectedTool.importUrl && ( +
+

Import URL

+ + {selectedTool.importUrl} + +
+ )} + + {/* Tool ID */} + {selectedTool.toolId && ( +
+

Tool ID

+ + {selectedTool.toolId} + +
+ )} +
+
+ )} + ); }