{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "elements-message-attachment",
  "type": "registry:component",
  "title": "Attachments in a message",
  "description": "Files as received rather than staged: an image to open, a document with its page count.",
  "registryDependencies": [
    "https://r.assistant-ui.com/elements-surfaces.json"
  ],
  "dependencies": [
    "lucide-react"
  ],
  "files": [
    {
      "type": "registry:component",
      "path": "components/assistant-ui/elements/message-attachment.tsx",
      "sourcePath": "packages/ui/src/components/react/assistant-ui/elements/message-attachment.tsx",
      "content": "\"use client\";\n\nimport type { ComponentProps } from \"react\";\nimport { FileTextIcon, ImageIcon, PaperclipIcon } from \"lucide-react\";\nimport { cn } from \"@/lib/utils\";\nimport { field, mono, paper } from \"./surfaces\";\n\nexport interface MessageAttachmentItem {\n  id: string;\n  name: string;\n  size: string;\n  kind: \"image\" | \"document\" | \"file\";\n  pages?: number;\n  swatch?: string;\n}\n\nexport function MessageAttachments({\n  attachments,\n  onOpen,\n  className,\n  ...props\n}: Omit<ComponentProps<\"div\">, \"children\" | \"attachments\" | \"onOpen\"> & {\n  attachments: readonly MessageAttachmentItem[];\n  onOpen?: (id: string) => void;\n}) {\n  return (\n    <div\n      data-slot=\"message-attachments\"\n      className={cn(\"flex w-full max-w-sm flex-col gap-1.5\", className)}\n\n      {...props}\n    >\n      {attachments.map((item) =>\n        item.kind === \"image\" ? (\n          <button\n            key={item.id}\n            type=\"button\"\n            onClick={() => onOpen?.(item.id)}\n            className={cn(\n              paper,\n              \"fade-in animate-in fill-mode-both group flex w-full items-center gap-3 overflow-hidden rounded-2xl p-2 text-start duration-300\",\n            )}\n          >\n            <span\n              aria-hidden\n              className=\"size-12 shrink-0 rounded-xl bg-cover bg-center transition-transform duration-300 group-hover:scale-[1.04] motion-reduce:transition-none\"\n              style={{\n                backgroundImage: item.swatch,\n                backgroundColor: \"var(--color-foreground)\",\n              }}\n            />\n            <span className=\"flex min-w-0 flex-1 flex-col gap-0.5 pe-2\">\n              <span className=\"text-foreground/90 truncate text-[13.5px]\">\n                {item.name}\n              </span>\n              <span className={cn(mono, \"text-foreground/35\")}>\n                {item.size}\n              </span>\n            </span>\n            <ImageIcon className=\"text-foreground/25 me-2 size-3.5 shrink-0\" />\n          </button>\n        ) : (\n          <button\n            key={item.id}\n            type=\"button\"\n            onClick={() => onOpen?.(item.id)}\n            className={cn(\n              field,\n              \"fade-in animate-in fill-mode-both hover:bg-foreground/[0.07] flex w-full items-center gap-2.5 rounded-2xl px-3 py-2.5 text-start transition-colors duration-300\",\n            )}\n          >\n            <span className=\"bg-background/70 text-foreground/45 flex size-8 shrink-0 items-center justify-center rounded-lg\">\n              {item.kind === \"document\" ? (\n                <FileTextIcon className=\"size-3.5\" />\n              ) : (\n                <PaperclipIcon className=\"size-3.5\" />\n              )}\n            </span>\n            <span className=\"flex min-w-0 flex-1 flex-col gap-0.5\">\n              <span className=\"text-foreground/90 truncate text-[13.5px]\">\n                {item.name}\n              </span>\n              <span className={cn(mono, \"text-foreground/35\")}>\n                {item.size}\n                {item.pages !== undefined && ` · ${item.pages} pages`}\n              </span>\n            </span>\n          </button>\n        ),\n      )}\n    </div>\n  );\n}\n"
    }
  ]
}