/** * Reusable ToolChain component with smart truncation and tooltip expansion * Used across FileListItem, FileDetails, and FileThumbnail for consistent display */ import React from 'react'; import { Text, Tooltip, Badge, Group } from '@mantine/core'; import { ToolOperation } from '../../types/file'; import { useTranslation } from 'react-i18next'; import { ToolId } from '../../types/toolId'; interface ToolChainProps { toolChain: ToolOperation[]; maxWidth?: string; displayStyle?: 'text' | 'badges' | 'compact'; size?: 'xs' | 'sm' | 'md'; color?: string; } const ToolChain: React.FC = ({ toolChain, maxWidth = '100%', displayStyle = 'text', size = 'xs', color = 'var(--mantine-color-blue-7)' }) => { if (!toolChain || toolChain.length === 0) return null; const { t } = useTranslation(); const toolIds = toolChain.map(tool => tool.toolId); const getToolName = (toolId: ToolId) => { return t(`home.${toolId}.title`, toolId); } // Create full tool chain for tooltip const fullChainDisplay = displayStyle === 'badges' ? ( {toolChain.map((tool, index) => ( {getToolName(tool.toolId)} {index < toolChain.length - 1 && ( )} ))} ) : ( {toolIds.map(getToolName).join(' → ')} ); // Create truncated display based on available space const getTruncatedDisplay = () => { if (toolIds.length <= 2) { // Show all tools if 2 or fewer return { text: toolIds.map(getToolName).join(' → '), isTruncated: false }; } else { // Show first tool ... last tool for longer chains return { text: `${getToolName(toolIds[0])} → +${toolIds.length-2} → ${getToolName(toolIds[toolIds.length - 1])}`, isTruncated: true, }; } }; const { text: truncatedText, isTruncated } = getTruncatedDisplay(); // Compact style for very small spaces if (displayStyle === 'compact') { const compactText = toolIds.length === 1 ? getToolName(toolIds[0]) : `${toolIds.length} tools`; const isCompactTruncated = toolIds.length > 1; const compactElement = ( {compactText} ); return isCompactTruncated ? ( {compactElement} ) : compactElement; } // Badge style for file details if (displayStyle === 'badges') { const isBadgesTruncated = toolChain.length > 3; const badgesElement = (
{toolChain.slice(0, 3).map((tool, index) => ( {getToolName(tool.toolId)} {index < Math.min(toolChain.length - 1, 2) && ( )} ))} {toolChain.length > 3 && ( <> ... {getToolName(toolChain[toolChain.length - 1].toolId)} )}
); return isBadgesTruncated ? ( {badgesElement} ) : badgesElement; } // Text style (default) for file list items const textElement = ( {truncatedText} ); return isTruncated ? ( {textElement} ) : textElement; }; export default ToolChain;