AssistantLinkPreview Component
The AssistantLinkPreview component provides rich preview cards for AI assistants with tool information and usage statistics.
Overview
This component fetches and displays detailed assistant information in a compact card format. It shows assistant metadata, avatar, tools, documents, and usage statistics with interactive elements for opening the assistant in a new tab.
Location
src/components/AssistantLinkPreview.tsx
Features
Rich Preview Information
- Assistant Details: Name, owner, and initial message
- Avatar Display: Assistant avatar with fallback to initials
- Tool Information: Count and categorized preview of available tools
- Document Count: Number of attached initial documents
- Usage Statistics: Total usage count with proper pluralization
Interactive Elements
- External Link: Opens assistant in new tab
- Tool Tooltip: Hover to see categorized tool preview
- Loading States: Smooth loading animation during data fetch
- Error Handling: Graceful display of error states
Responsive Design
- Compact Layout: Optimized for embedding in various contexts
- Text Truncation: Automatically truncates long descriptions
- Hover Effects: Subtle shadow transition on hover
Props Interface
interface AssistantLinkPreviewProps {
assistantId: string; // Unique identifier for the assistant
className?: string; // Optional CSS classes
}
Usage Example
import { AssistantLinkPreview } from '@/components/AssistantLinkPreview';
function AssistantMention({ assistantId }) {
return (
<div className="my-4">
<AssistantLinkPreview
assistantId={assistantId}
className="max-w-sm"
/>
</div>
);
}
// In markdown or rich text
function MessageContent({ content }) {
// Automatically render assistant previews for links
return (
<div>
{content.includes('/assistant/') && (
<AssistantLinkPreview assistantId={extractAssistantId(content)} />
)}
</div>
);
}
State Management
Loading State
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
const [assistant, setAssistant] = useState<Assistant | null>(null);
Data Fetching
useEffect(() => {
const fetchAssistant = async () => {
try {
setLoading(true);
setError(null);
const assistantData = await FirebaseService.getAssistant(assistantId);
setAssistant(assistantData);
} catch (err) {
console.error('Error fetching assistant preview:', err);
setError('Failed to load assistant');
} finally {
setLoading(false);
}
};
if (assistantId) {
fetchAssistant();
}
}, [assistantId]);
Display Components
Loading State
<Card className="w-full max-w-md">
<CardContent className="flex items-center justify-center p-4">
<Loader2 className="h-4 w-4 animate-spin mr-2" />
<span className="text-sm text-muted-foreground">Loading assistant...</span>
</CardContent>
</Card>
Error State
<Card className="w-full max-w-md border-destructive/20">
<CardContent className="p-4">
<p className="text-sm text-destructive">
{error || 'Assistant not found'}
</p>
</CardContent>
</Card>
Success State Structure
- Header: Avatar, name, owner, external link button
- Content: Initial message (truncated), tool/document counts, usage stats
- Tool Tooltip: Categorized tool preview on hover
Text Truncation
const truncateText = (text: string, maxLength: number) => {
if (text.length <= maxLength) return text;
return text.slice(0, maxLength) + '...';
};
// Applied to initial message
{assistant.initialMessage && (
<p className="text-xs text-foreground leading-relaxed">
{truncateText(assistant.initialMessage, 120)}
</p>
)}
Tool Integration
Tool Count Display
{assistant.tools && assistant.tools.length > 0 && (
<Button variant="outline" size="sm" className="h-6 px-2 text-xs">
<Settings className="h-3 w-3 mr-1" />
{assistant.tools.length} tool{assistant.tools.length !== 1 ? 's' : ''}
</Button>
)}
Tool Preview Tooltip
<TooltipContent side="bottom" className="max-w-sm">
<div className="p-2">
<div className="text-xs font-medium mb-2">Available Tools</div>
<CategorizedToolPreview
tools={assistant.tools}
toolConfigs={assistant.toolConfigs || {}}
/>
</div>
</TooltipContent>
Dependencies
@/lib/firebase- FirebaseService and Assistant type@/components/ui/*- Avatar, Card, Badge, Button, Tooltip components@/components/creator/CategorizedToolPreview- Tool categorizationlucide-react- Icons (ExternalLink, Settings, Loader2)
Firebase Integration
Assistant Data Structure
interface Assistant {
name: string;
ownerEmail: string;
avatar?: string;
initialMessage?: string;
tools?: string[];
toolConfigs?: Record<string, any>;
initialDocuments?: any[];
usageCount?: number;
}
Error Handling
- Network Failures: Displays “Failed to load assistant”
- Missing Assistant: Shows “Assistant not found”
- Permission Issues: Handled gracefully with error message
Accessibility
Semantic Structure
- Card Layout: Proper heading hierarchy
- Button Labels: Clear action descriptions
- Alt Text: Avatar images with fallback
Keyboard Navigation
- Focusable Elements: External link button, tool tooltips
- Tab Order: Logical navigation through interactive elements
Screen Reader Support
- Descriptive Text: Tool counts, usage statistics
- Tooltip Content: Additional context on hover/focus
Performance Considerations
Lazy Loading
- On-Demand Fetching: Only fetches when assistantId provided
- Cleanup: Proper effect cleanup prevents memory leaks
- Caching: Relies on Firebase SDK caching mechanisms
Responsive Images
- Avatar Optimization: Fixed size with responsive scaling
- Fallback Rendering: Initials when avatar unavailable
Related Components
CategorizedToolPreview- Shows organized tool informationSharingStatus- Displays access control informationQRCodeDialog- Provides sharing functionality- Assistant creation and management interfaces
Best Practices
- Provide Valid Assistant IDs: Ensure assistantId exists before rendering
- Handle Loading States: Always show loading feedback
- Graceful Errors: Display helpful error messages
- Responsive Usage: Consider container width constraints
- Accessibility: Ensure keyboard navigation and screen reader support