/**
* 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