/** * ArtifactsSidebar - Floating list of all artifacts in current conversation * * Appears in bottom-right of the side panel. * Lists all artifacts with download buttons and click-to-switch functionality. */ import { useArtifacts } from '@/hooks/useArtifacts' import { cn } from '@/lib/utils' import { IconDownload, IconFileText, IconCode } from '@tabler/icons-react' type ArtifactsSidebarProps = { threadId: string } export function ArtifactsSidebar({ threadId }: ArtifactsSidebarProps) { const artifacts = useArtifacts() const threadArtifacts = artifacts.threadArtifacts[threadId] || [] const activeArtifactId = artifacts.threadIndex[threadId]?.active_artifact_id const handleDownloadAll = () => { // Download all artifacts as individual files threadArtifacts.forEach((artifact: any) => { const blob = new Blob([artifact.content], { type: 'text/plain' }) const url = URL.createObjectURL(blob) const a = document.createElement('a') a.href = url a.download = artifact.file_path.split('/').pop() || 'artifact.txt' document.body.appendChild(a) a.click() document.body.removeChild(a) URL.revokeObjectURL(url) }) } const handleSelectArtifact = (artifactId: string) => { artifacts.setActiveArtifact(threadId, artifactId) } const handleDownloadSingle = (artifact: any, e: React.MouseEvent) => { e.stopPropagation() // Prevent selecting the artifact const blob = new Blob([artifact.content], { type: 'text/plain' }) const url = URL.createObjectURL(blob) const a = document.createElement('a') a.href = url a.download = artifact.file_path.split('/').pop() || 'artifact.txt' document.body.appendChild(a) a.click() document.body.removeChild(a) URL.revokeObjectURL(url) } const getArtifactIcon = (artifact: any) => { if (artifact.content_type.startsWith('text/x-')) { return } return } const getFileType = (artifact: any) => { const ext = artifact.file_path.split('.').pop() return ext?.toUpperCase() || 'TXT' } if (threadArtifacts.length === 0) { return null } return (
{/* Header */}

Artifacts

{threadArtifacts.length > 1 && ( )}
{/* Artifact List */}
{threadArtifacts.map((artifact) => ( ))}
) }