26 / 59 · Agents
Artifact card
A generated document as a tangible object, written live and versioned.
Draft persistence RFC
Writing·0 words
Installation
npx shadcn@latest add "@assistant-ui/elements-artifact-card"
Usage
import { ArtifactCard } from "@/components/elements/artifact-card";
<ArtifactCard
title="Draft persistence RFC"
meta="Document · v3 · just now"
generating={isWriting}
words={wordCount}
/>Props
title*stringName of the generated artifact.
meta*stringResting meta line shown once generation finishes, for example kind, version, and recency.
generatingbooleanWhile true the icon pulses and the meta line shows a live word count with a shimmer.
wordsnumberLive word count shown while generating.
classNamestringExtra classes merged onto the card.
Source
artifact-card.tsx"use client";
import { ArrowUpRightIcon, FileTextIcon } from "lucide-react";
import { cn } from "@/lib/utils";
import { mono, paper } from "./surfaces";
export function ArtifactCard({
title,
meta,
generating = false,
words = 0,
className,
}: {
title: string;
meta: string;
generating?: boolean;
words?: number;
className?: string;
}) {
return (
<div
className={cn(
paper,
"group flex w-full max-w-xs cursor-pointer items-center gap-3 rounded-[20px] p-3.5 transition-transform duration-150 hover:-translate-y-px active:scale-[0.98]",
className,
)}
>
<span className="bg-foreground/[0.05] text-foreground/45 flex size-9 shrink-0 items-center justify-center rounded-xl">
<FileTextIcon
className={cn(
"size-4",
generating && "animate-pulse motion-reduce:animate-none",
)}
/>
</span>
<div className="min-w-0 flex-1">
<p className="truncate text-[13.5px] font-medium">{title}</p>
{generating ? (
<p className={cn(mono, "text-foreground/40 flex items-center gap-1")}>
<span className="relative inline-block leading-none">
<span>Writing</span>
<span
aria-hidden
className="shimmer pointer-events-none absolute inset-0 motion-reduce:animate-none"
>
Writing
</span>
</span>
<span>·</span>
<span className="tabular-nums">{words} words</span>
</p>
) : (
<p
className={cn(
mono,
"fade-in blur-in-[2px] animate-in text-foreground/40 duration-300 motion-reduce:animate-none",
)}
>
{meta}
</p>
)}
</div>
<ArrowUpRightIcon className="text-foreground/35 size-3.5 opacity-0 transition-opacity group-hover:opacity-100" />
</div>
);
}