Attachmentstandard
첨부 파일 한 개를 보여 주는 카드(첨부, attachment)입니다. 그림 또는 아이콘, 이름, 설명, 동작 버튼을 조합하고 올리는 중·실패 같은 상태를 색과 테두리로 구분합니다. shadcn base-nova 의 원본을 그대로 담은 아이템입니다. 업스트림 메타데이터에 문서 링크가 없습니다.
설치
pnpm
pnpm dlx shadcn@4.23.0 add @uikit/attachment의존 아이템button
Default
attachment-example.tsx
"use client"
import * as React from "react"
import { Example, ExampleWrapper,} from "@/components/example"import { Attachment, AttachmentAction, AttachmentActions, AttachmentContent, AttachmentDescription, AttachmentGroup, AttachmentMedia, AttachmentTitle, AttachmentTrigger,} from "@/components/ui/attachment"import { Button } from "@/components/ui/button"import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger,} from "@/components/ui/dialog"import { Spinner } from "@/components/ui/spinner"import { CheckIcon, ClockIcon, CopyIcon, DownloadIcon, FileArchiveIcon, FileCodeIcon, FileSearchIcon, FileTextIcon, FileWarningIcon, PresentationIcon, RefreshCwIcon, TableIcon, XIcon } from "lucide-react"
export default function AttachmentExample() { return ( <ExampleWrapper> <AttachmentFiles /> <AttachmentContentOnly /> <AttachmentStates /> <AttachmentImages /> <AttachmentImageStates /> <AttachmentSizes /> <AttachmentScrollableGroup /> <AttachmentTriggers /> </ExampleWrapper> )}
function AttachmentFiles() { return ( <Example title="Files" className="gap-8"> <div className="flex w-full flex-col gap-2"> <div className="px-1 text-xs font-medium text-muted-foreground"> Horizontal </div> <div className="flex flex-col gap-3"> <Attachment className="w-full"> <AttachmentMedia> <FileTextIcon /> </AttachmentMedia> <AttachmentContent> <AttachmentTitle>sales-dashboard.pdf</AttachmentTitle> <AttachmentDescription>PDF · 2.4 MB</AttachmentDescription> </AttachmentContent> <AttachmentActions> <AttachmentAction aria-label="Remove sales-dashboard.pdf"> <XIcon /> </AttachmentAction> </AttachmentActions> </Attachment> <Attachment className="w-full"> <AttachmentMedia> <TableIcon /> </AttachmentMedia> <AttachmentContent> <AttachmentTitle>customer-import.csv</AttachmentTitle> <AttachmentDescription>CSV · 18 KB</AttachmentDescription> </AttachmentContent> <AttachmentActions> <AttachmentAction aria-label="Remove customer-import.csv"> <XIcon /> </AttachmentAction> </AttachmentActions> </Attachment> <Attachment className="w-full"> <AttachmentMedia> <FileCodeIcon /> </AttachmentMedia> <AttachmentContent> <AttachmentTitle>message-renderer.tsx</AttachmentTitle> <AttachmentDescription>TypeScript · 12 KB</AttachmentDescription> </AttachmentContent> <AttachmentActions> <AttachmentAction aria-label="Remove message-renderer.tsx"> <XIcon /> </AttachmentAction> </AttachmentActions> </Attachment> </div> </div> <div className="flex w-full flex-col gap-2"> <div className="px-1 text-xs font-medium text-muted-foreground"> Vertical </div> <AttachmentGroup className="w-full"> <Attachment orientation="vertical"> <AttachmentMedia> <FileTextIcon /> </AttachmentMedia> <AttachmentContent> <AttachmentTitle>sales-dashboard.pdf</AttachmentTitle> <AttachmentDescription>PDF · 2.4 MB</AttachmentDescription> </AttachmentContent> <AttachmentActions> <AttachmentAction aria-label="Remove sales-dashboard.pdf"> <XIcon /> </AttachmentAction> </AttachmentActions> </Attachment> <Attachment orientation="vertical"> <AttachmentMedia> <TableIcon /> </AttachmentMedia> <AttachmentContent> <AttachmentTitle>customer-import.csv</AttachmentTitle> <AttachmentDescription>CSV · 18 KB</AttachmentDescription> </AttachmentContent> <AttachmentActions> <AttachmentAction aria-label="Remove customer-import.csv"> <XIcon /> </AttachmentAction> </AttachmentActions> </Attachment> <Attachment orientation="vertical"> <AttachmentMedia> <FileCodeIcon /> </AttachmentMedia> <AttachmentContent> <AttachmentTitle>message-renderer.tsx</AttachmentTitle> <AttachmentDescription>TypeScript · 12 KB</AttachmentDescription> </AttachmentContent> <AttachmentActions> <AttachmentAction aria-label="Remove message-renderer.tsx"> <XIcon /> </AttachmentAction> </AttachmentActions> </Attachment> <Attachment orientation="vertical"> <AttachmentMedia> <FileArchiveIcon /> </AttachmentMedia> <AttachmentContent> <AttachmentTitle>source-assets.zip</AttachmentTitle> <AttachmentDescription>ZIP · 4.2 MB</AttachmentDescription> </AttachmentContent> <AttachmentActions> <AttachmentAction aria-label="Remove source-assets.zip"> <XIcon /> </AttachmentAction> </AttachmentActions> </Attachment> <Attachment orientation="vertical"> <AttachmentMedia> <PresentationIcon /> </AttachmentMedia> <AttachmentContent> <AttachmentTitle>quarterly-review.key</AttachmentTitle> <AttachmentDescription>Keynote · 9 MB</AttachmentDescription> </AttachmentContent> <AttachmentActions> <AttachmentAction aria-label="Remove quarterly-review.key"> <XIcon /> </AttachmentAction> </AttachmentActions> </Attachment> </AttachmentGroup> </div> </Example> )}
function AttachmentContentOnly() { return ( <Example title="Content Only" className="gap-8"> <div className="flex w-full flex-col gap-2"> <div className="px-1 text-xs font-medium text-muted-foreground"> Title </div> <div className="flex flex-col gap-3"> <Attachment className="w-full"> <AttachmentContent> <AttachmentTitle>React Documentation</AttachmentTitle> </AttachmentContent> <AttachmentActions> <AttachmentAction aria-label="Remove React Documentation"> <XIcon /> </AttachmentAction> </AttachmentActions> </Attachment> <Attachment className="w-full"> <AttachmentContent> <AttachmentTitle>Tailwind CSS</AttachmentTitle> </AttachmentContent> <AttachmentActions> <AttachmentAction aria-label="Remove Tailwind CSS"> <XIcon /> </AttachmentAction> </AttachmentActions> </Attachment> <Attachment size="sm" className="w-48"> <AttachmentContent> <AttachmentTitle>shadcn/ui</AttachmentTitle> </AttachmentContent> <AttachmentTrigger render={ <a href="https://ui.shadcn.com" target="_blank" rel="noopener noreferrer" aria-label="Open shadcn/ui" /> } /> </Attachment> </div> </div> <div className="flex w-full flex-col gap-2"> <div className="px-1 text-xs font-medium text-muted-foreground"> Title and Description </div> <div className="flex flex-col gap-3"> <Attachment className="w-full"> <AttachmentContent> <AttachmentTitle>Building accessible components</AttachmentTitle> <AttachmentDescription> react.dev · 8 min read </AttachmentDescription> </AttachmentContent> <AttachmentActions> <AttachmentAction aria-label="Remove Building accessible components"> <XIcon /> </AttachmentAction> </AttachmentActions> </Attachment> <Attachment className="w-full"> <AttachmentContent> <AttachmentTitle>Utility-first CSS framework</AttachmentTitle> <AttachmentDescription>tailwindcss.com</AttachmentDescription> </AttachmentContent> <AttachmentActions> <AttachmentAction aria-label="Remove Utility-first CSS framework"> <XIcon /> </AttachmentAction> </AttachmentActions> </Attachment> <Attachment size="sm" className="w-full max-w-80"> <AttachmentContent> <AttachmentTitle>Compound components in React</AttachmentTitle> <AttachmentDescription>ui.shadcn.com/docs</AttachmentDescription> </AttachmentContent> <AttachmentTrigger render={ <a href="https://ui.shadcn.com/docs" target="_blank" rel="noopener noreferrer" aria-label="Open Compound components in React" /> } /> </Attachment> </div> </div> </Example> )}
function AttachmentStates() { return ( <Example title="States" className="gap-8"> <div className="flex w-full flex-col gap-3"> <div className="px-1 text-xs font-medium text-muted-foreground"> Horizontal </div> <div className="flex flex-col gap-2"> <Attachment state="idle" className="w-full"> <AttachmentMedia> <ClockIcon /> </AttachmentMedia> <AttachmentContent> <AttachmentTitle>selected-file.pdf</AttachmentTitle> <AttachmentDescription>Ready to upload</AttachmentDescription> </AttachmentContent> <AttachmentActions> <AttachmentAction aria-label="Remove selected-file.pdf"> <XIcon /> </AttachmentAction> </AttachmentActions> </Attachment> <Attachment state="uploading" className="w-full"> <AttachmentMedia> <Spinner /> </AttachmentMedia> <AttachmentContent> <AttachmentTitle>design-system.zip</AttachmentTitle> <AttachmentDescription>Uploading · 64%</AttachmentDescription> </AttachmentContent> <AttachmentActions> <AttachmentAction aria-label="Remove design-system.zip"> <XIcon /> </AttachmentAction> </AttachmentActions> </Attachment> <Attachment state="processing" className="w-full"> <AttachmentMedia> <FileTextIcon /> </AttachmentMedia> <AttachmentContent> <AttachmentTitle>market-research.pdf</AttachmentTitle> <AttachmentDescription>Processing document</AttachmentDescription> </AttachmentContent> <AttachmentActions> <AttachmentAction aria-label="Remove market-research.pdf"> <XIcon /> </AttachmentAction> </AttachmentActions> </Attachment> <Attachment state="error" className="w-full"> <AttachmentMedia> <FileWarningIcon /> </AttachmentMedia> <AttachmentContent> <AttachmentTitle>financial-model.xlsx</AttachmentTitle> <AttachmentDescription> Upload failed. Try again. </AttachmentDescription> </AttachmentContent> <AttachmentActions> <AttachmentAction aria-label="Retry upload"> <RefreshCwIcon /> </AttachmentAction> <AttachmentAction aria-label="Remove attachment"> <XIcon /> </AttachmentAction> </AttachmentActions> </Attachment> <Attachment state="done" className="w-full"> <AttachmentMedia> <CheckIcon /> </AttachmentMedia> <AttachmentContent> <AttachmentTitle>uploaded-report.pdf</AttachmentTitle> <AttachmentDescription>Uploaded · 1.8 MB</AttachmentDescription> </AttachmentContent> <AttachmentActions> <AttachmentAction aria-label="Remove uploaded-report.pdf"> <XIcon /> </AttachmentAction> </AttachmentActions> </Attachment> </div> </div> <div className="flex w-full flex-col gap-3"> <div className="px-1 text-xs font-medium text-muted-foreground"> Vertical </div> <AttachmentGroup className="w-full"> <Attachment state="idle" orientation="vertical"> <AttachmentMedia> <ClockIcon /> </AttachmentMedia> <AttachmentContent> <AttachmentTitle>selected-file.pdf</AttachmentTitle> <AttachmentDescription>Ready</AttachmentDescription> </AttachmentContent> <AttachmentActions> <AttachmentAction aria-label="Remove selected-file.pdf"> <XIcon /> </AttachmentAction> </AttachmentActions> </Attachment> <Attachment state="uploading" orientation="vertical"> <AttachmentMedia> <Spinner /> </AttachmentMedia> <AttachmentContent> <AttachmentTitle>design-system.zip</AttachmentTitle> <AttachmentDescription>Uploading</AttachmentDescription> </AttachmentContent> <AttachmentActions> <AttachmentAction aria-label="Remove design-system.zip"> <XIcon /> </AttachmentAction> </AttachmentActions> </Attachment> <Attachment state="processing" orientation="vertical"> <AttachmentMedia> <FileTextIcon /> </AttachmentMedia> <AttachmentContent> <AttachmentTitle>market-research.pdf</AttachmentTitle> <AttachmentDescription>Processing</AttachmentDescription> </AttachmentContent> <AttachmentActions> <AttachmentAction aria-label="Remove market-research.pdf"> <XIcon /> </AttachmentAction> </AttachmentActions> </Attachment> <Attachment state="error" orientation="vertical"> <AttachmentMedia> <FileWarningIcon /> </AttachmentMedia> <AttachmentContent> <AttachmentTitle>financial-model.xlsx</AttachmentTitle> <AttachmentDescription>Failed</AttachmentDescription> </AttachmentContent> <AttachmentActions> <AttachmentAction aria-label="Retry financial-model.xlsx"> <RefreshCwIcon /> </AttachmentAction> <AttachmentAction aria-label="Remove financial-model.xlsx"> <XIcon /> </AttachmentAction> </AttachmentActions> </Attachment> <Attachment state="done" orientation="vertical"> <AttachmentMedia> <CheckIcon /> </AttachmentMedia> <AttachmentContent> <AttachmentTitle>uploaded-report.pdf</AttachmentTitle> <AttachmentDescription>Done</AttachmentDescription> </AttachmentContent> <AttachmentActions> <AttachmentAction aria-label="Remove uploaded-report.pdf"> <XIcon /> </AttachmentAction> </AttachmentActions> </Attachment> </AttachmentGroup> </div> </Example> )}
function AttachmentImages() { return ( <Example title="Images" className="gap-8"> <div className="flex w-full flex-col gap-3"> <div className="px-1 text-xs font-medium text-muted-foreground"> Horizontal </div> <div className="flex flex-col gap-2"> <Attachment className="w-full"> <AttachmentMedia variant="image"> <img src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%208%206'%3E%3Crect%20width='8'%20height='6'%20fill='%23a3a3a3'/%3E%3C/svg%3E" alt="Workspace" /> </AttachmentMedia> <AttachmentContent> <AttachmentTitle>workspace.png</AttachmentTitle> <AttachmentDescription>PNG · 820 KB</AttachmentDescription> </AttachmentContent> <AttachmentActions> <AttachmentAction aria-label="Remove workspace.png"> <XIcon /> </AttachmentAction> </AttachmentActions> <AttachmentTrigger render={ <a href="https://images.unsplash.com/photo-1497366754035-f200968a6e72?w=900&auto=format&fit=crop&q=80" target="_blank" rel="noreferrer" aria-label="Open workspace.png" /> } /> </Attachment> <Attachment className="w-full"> <AttachmentMedia variant="image"> <img src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%208%206'%3E%3Crect%20width='8'%20height='6'%20fill='%2394a3b8'/%3E%3C/svg%3E" alt="Desk" /> </AttachmentMedia> <AttachmentContent> <AttachmentTitle>desk-reference.jpg</AttachmentTitle> <AttachmentDescription>JPG · 1.1 MB</AttachmentDescription> </AttachmentContent> <AttachmentActions> <AttachmentAction aria-label="Remove desk-reference.jpg"> <XIcon /> </AttachmentAction> </AttachmentActions> <AttachmentTrigger render={ <a href="https://images.unsplash.com/photo-1497215728101-856f4ea42174?w=900&auto=format&fit=crop&q=80" target="_blank" rel="noreferrer" aria-label="Open desk-reference.jpg" /> } /> </Attachment> <Attachment className="w-full"> <AttachmentMedia variant="image"> <img src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%208%206'%3E%3Crect%20width='8'%20height='6'%20fill='%2378716c'/%3E%3C/svg%3E" alt="Office" /> </AttachmentMedia> <AttachmentContent> <AttachmentTitle>office-reference.jpg</AttachmentTitle> <AttachmentDescription>JPG · 940 KB</AttachmentDescription> </AttachmentContent> <AttachmentActions> <AttachmentAction aria-label="Remove office-reference.jpg"> <XIcon /> </AttachmentAction> </AttachmentActions> <AttachmentTrigger render={ <a href="https://images.unsplash.com/photo-1497366811353-6870744d04b2?w=900&auto=format&fit=crop&q=80" target="_blank" rel="noreferrer" aria-label="Open office-reference.jpg" /> } /> </Attachment> </div> </div> <div className="flex w-full flex-col gap-2"> <div className="px-1 text-xs font-medium text-muted-foreground"> Vertical </div> <AttachmentGroup className="w-full"> <Attachment orientation="vertical"> <AttachmentMedia variant="image"> <img src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%208%206'%3E%3Crect%20width='8'%20height='6'%20fill='%23a3a3a3'/%3E%3C/svg%3E" alt="Workspace" /> </AttachmentMedia> <AttachmentContent> <AttachmentTitle>workspace.png</AttachmentTitle> <AttachmentDescription>PNG · 820 KB</AttachmentDescription> </AttachmentContent> <AttachmentActions> <AttachmentAction aria-label="Remove workspace.png"> <XIcon /> </AttachmentAction> </AttachmentActions> <AttachmentTrigger render={ <a href="https://images.unsplash.com/photo-1497366754035-f200968a6e72?w=900&auto=format&fit=crop&q=80" target="_blank" rel="noreferrer" aria-label="Open workspace.png" /> } /> </Attachment> <Attachment orientation="vertical"> <AttachmentMedia variant="image"> <img src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%208%206'%3E%3Crect%20width='8'%20height='6'%20fill='%2394a3b8'/%3E%3C/svg%3E" alt="Desk" /> </AttachmentMedia> <AttachmentContent> <AttachmentTitle>desk-reference.jpg</AttachmentTitle> <AttachmentDescription>JPG · 1.1 MB</AttachmentDescription> </AttachmentContent> <AttachmentActions> <AttachmentAction aria-label="Remove desk-reference.jpg"> <XIcon /> </AttachmentAction> </AttachmentActions> <AttachmentTrigger render={ <a href="https://images.unsplash.com/photo-1497215728101-856f4ea42174?w=900&auto=format&fit=crop&q=80" target="_blank" rel="noreferrer" aria-label="Open desk-reference.jpg" /> } /> </Attachment> <Attachment orientation="vertical"> <AttachmentMedia variant="image"> <img src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%208%206'%3E%3Crect%20width='8'%20height='6'%20fill='%2378716c'/%3E%3C/svg%3E" alt="Office" /> </AttachmentMedia> <AttachmentContent> <AttachmentTitle>office-reference.jpg</AttachmentTitle> <AttachmentDescription>JPG · 940 KB</AttachmentDescription> </AttachmentContent> <AttachmentActions> <AttachmentAction aria-label="Remove office-reference.jpg"> <XIcon /> </AttachmentAction> </AttachmentActions> <AttachmentTrigger render={ <a href="https://images.unsplash.com/photo-1497366811353-6870744d04b2?w=900&auto=format&fit=crop&q=80" target="_blank" rel="noreferrer" aria-label="Open office-reference.jpg" /> } /> </Attachment> <Attachment orientation="vertical"> <AttachmentMedia variant="image"> <img src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%208%206'%3E%3Crect%20width='8'%20height='6'%20fill='%23737373'/%3E%3C/svg%3E" alt="Outdoor patio" /> </AttachmentMedia> <AttachmentContent> <AttachmentTitle>patio-reference.jpg</AttachmentTitle> <AttachmentDescription>JPG · 1.6 MB</AttachmentDescription> </AttachmentContent> <AttachmentActions> <AttachmentAction aria-label="Remove patio-reference.jpg"> <XIcon /> </AttachmentAction> </AttachmentActions> <AttachmentTrigger render={ <a href="https://images.unsplash.com/photo-1500530855697-b586d89ba3ee?w=900&auto=format&fit=crop&q=80" target="_blank" rel="noreferrer" aria-label="Open patio-reference.jpg" /> } /> </Attachment> <Attachment orientation="vertical"> <AttachmentMedia variant="image"> <img src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%208%206'%3E%3Crect%20width='8'%20height='6'%20fill='%236b7280'/%3E%3C/svg%3E" alt="House exterior" /> </AttachmentMedia> <AttachmentContent> <AttachmentTitle>house-exterior.jpg</AttachmentTitle> <AttachmentDescription>JPG · 1.4 MB</AttachmentDescription> </AttachmentContent> <AttachmentActions> <AttachmentAction aria-label="Remove house-exterior.jpg"> <XIcon /> </AttachmentAction> </AttachmentActions> <AttachmentTrigger render={ <a href="https://images.unsplash.com/photo-1494526585095-c41746248156?w=900&auto=format&fit=crop&q=80" target="_blank" rel="noreferrer" aria-label="Open house-exterior.jpg" /> } /> </Attachment> </AttachmentGroup> </div> </Example> )}
function AttachmentImageStates() { return ( <Example title="Image States" className="gap-8"> <div className="flex w-full flex-col gap-3"> <div className="px-1 text-xs font-medium text-muted-foreground"> Horizontal </div> <div className="flex flex-col gap-2"> <Attachment state="idle" className="w-full"> <AttachmentMedia variant="image"> <img src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%208%206'%3E%3Crect%20width='8'%20height='6'%20fill='%2378716c'/%3E%3C/svg%3E" alt="Office" /> </AttachmentMedia> <AttachmentContent> <AttachmentTitle>office-reference.jpg</AttachmentTitle> <AttachmentDescription>Ready to upload</AttachmentDescription> </AttachmentContent> <AttachmentActions> <AttachmentAction aria-label="Remove office-reference.jpg"> <XIcon /> </AttachmentAction> </AttachmentActions> </Attachment> <Attachment state="uploading" className="w-full"> <AttachmentMedia variant="image"> <img src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%208%206'%3E%3Crect%20width='8'%20height='6'%20fill='%23a3a3a3'/%3E%3C/svg%3E" alt="Workspace" /> </AttachmentMedia> <AttachmentContent> <AttachmentTitle>workspace.png</AttachmentTitle> <AttachmentDescription>Uploading · 72%</AttachmentDescription> </AttachmentContent> <AttachmentActions> <AttachmentAction aria-label="Remove workspace.png"> <XIcon /> </AttachmentAction> </AttachmentActions> </Attachment> <Attachment state="processing" className="w-full"> <AttachmentMedia variant="image"> <img src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%208%206'%3E%3Crect%20width='8'%20height='6'%20fill='%2394a3b8'/%3E%3C/svg%3E" alt="Desk" /> </AttachmentMedia> <AttachmentContent> <AttachmentTitle>desk-reference.jpg</AttachmentTitle> <AttachmentDescription>Processing image</AttachmentDescription> </AttachmentContent> <AttachmentActions> <AttachmentAction aria-label="Remove desk-reference.jpg"> <XIcon /> </AttachmentAction> </AttachmentActions> </Attachment> <Attachment state="error" className="w-full"> <AttachmentMedia variant="image"> <img src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%208%206'%3E%3Crect%20width='8'%20height='6'%20fill='%2378716c'/%3E%3C/svg%3E" alt="Office" /> </AttachmentMedia> <AttachmentContent> <AttachmentTitle>office-reference.jpg</AttachmentTitle> <AttachmentDescription>Upload failed</AttachmentDescription> </AttachmentContent> <AttachmentActions> <AttachmentAction aria-label="Retry image upload"> <RefreshCwIcon /> </AttachmentAction> <AttachmentAction aria-label="Remove attachment"> <XIcon /> </AttachmentAction> </AttachmentActions> </Attachment> <Attachment state="done" className="w-full"> <AttachmentMedia variant="image"> <img src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%208%206'%3E%3Crect%20width='8'%20height='6'%20fill='%23a3a3a3'/%3E%3C/svg%3E" alt="Workspace" /> </AttachmentMedia> <AttachmentContent> <AttachmentTitle>workspace.png</AttachmentTitle> <AttachmentDescription>Uploaded · 1.2 MB</AttachmentDescription> </AttachmentContent> <AttachmentActions> <AttachmentAction aria-label="Remove workspace.png"> <XIcon /> </AttachmentAction> </AttachmentActions> </Attachment> </div> </div> <div className="flex w-full flex-col gap-2"> <div className="px-1 text-xs font-medium text-muted-foreground"> Vertical </div> <AttachmentGroup className="w-full"> <Attachment state="idle" orientation="vertical"> <AttachmentMedia variant="image"> <img src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%208%206'%3E%3Crect%20width='8'%20height='6'%20fill='%2378716c'/%3E%3C/svg%3E" alt="Office" /> </AttachmentMedia> <AttachmentContent> <AttachmentTitle>office-reference.jpg</AttachmentTitle> <AttachmentDescription>Ready</AttachmentDescription> </AttachmentContent> <AttachmentActions> <AttachmentAction aria-label="Remove office-reference.jpg"> <XIcon /> </AttachmentAction> </AttachmentActions> </Attachment> <Attachment state="uploading" orientation="vertical"> <AttachmentMedia variant="image"> <img src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%208%206'%3E%3Crect%20width='8'%20height='6'%20fill='%23a3a3a3'/%3E%3C/svg%3E" alt="Workspace" /> </AttachmentMedia> <AttachmentContent> <AttachmentTitle>workspace.png</AttachmentTitle> <AttachmentDescription>Uploading</AttachmentDescription> </AttachmentContent> <AttachmentActions> <AttachmentAction aria-label="Remove workspace.png"> <XIcon /> </AttachmentAction> </AttachmentActions> </Attachment> <Attachment state="processing" orientation="vertical"> <AttachmentMedia variant="image"> <img src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%208%206'%3E%3Crect%20width='8'%20height='6'%20fill='%2394a3b8'/%3E%3C/svg%3E" alt="Desk" /> </AttachmentMedia> <AttachmentContent> <AttachmentTitle>desk-reference.jpg</AttachmentTitle> <AttachmentDescription>Processing</AttachmentDescription> </AttachmentContent> <AttachmentActions> <AttachmentAction aria-label="Remove desk-reference.jpg"> <XIcon /> </AttachmentAction> </AttachmentActions> </Attachment> <Attachment state="error" orientation="vertical"> <AttachmentMedia variant="image"> <img src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%208%206'%3E%3Crect%20width='8'%20height='6'%20fill='%2378716c'/%3E%3C/svg%3E" alt="Office" /> </AttachmentMedia> <AttachmentContent> <AttachmentTitle>office-reference.jpg</AttachmentTitle> <AttachmentDescription>Failed</AttachmentDescription> </AttachmentContent> <AttachmentActions> <AttachmentAction aria-label="Retry office-reference.jpg"> <RefreshCwIcon /> </AttachmentAction> <AttachmentAction aria-label="Remove office-reference.jpg"> <XIcon /> </AttachmentAction> </AttachmentActions> </Attachment> <Attachment state="done" orientation="vertical"> <AttachmentMedia variant="image"> <img src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%208%206'%3E%3Crect%20width='8'%20height='6'%20fill='%23a3a3a3'/%3E%3C/svg%3E" alt="Workspace" /> </AttachmentMedia> <AttachmentContent> <AttachmentTitle>workspace.png</AttachmentTitle> <AttachmentDescription>Done</AttachmentDescription> </AttachmentContent> <AttachmentActions> <AttachmentAction aria-label="Remove workspace.png"> <XIcon /> </AttachmentAction> </AttachmentActions> </Attachment> </AttachmentGroup> </div> </Example> )}
function AttachmentSizes() { return ( <Example title="Sizes" className="gap-3"> <Attachment size="default" className="w-full"> <AttachmentMedia> <FileTextIcon /> </AttachmentMedia> <AttachmentContent> <AttachmentTitle>Default attachment</AttachmentTitle> <AttachmentDescription>PDF · 2.4 MB</AttachmentDescription> </AttachmentContent> </Attachment> <Attachment size="sm" className="w-full"> <AttachmentMedia> <FileTextIcon /> </AttachmentMedia> <AttachmentContent> <AttachmentTitle>Small attachment</AttachmentTitle> <AttachmentDescription>PDF · 2.4 MB</AttachmentDescription> </AttachmentContent> </Attachment> <Attachment size="xs" className="w-full"> <AttachmentMedia> <FileTextIcon /> </AttachmentMedia> <AttachmentContent> <AttachmentTitle>Extra small attachment</AttachmentTitle> </AttachmentContent> </Attachment> </Example> )}
function AttachmentScrollableGroup() { return ( <Example title="Scrollable Group" className="gap-4"> <AttachmentGroup className="w-full"> <Attachment className="w-64"> <AttachmentMedia> <FileTextIcon /> </AttachmentMedia> <AttachmentContent> <AttachmentTitle>briefing-notes.pdf</AttachmentTitle> <AttachmentDescription>PDF · 1.4 MB</AttachmentDescription> </AttachmentContent> <AttachmentActions> <AttachmentAction aria-label="Remove briefing-notes.pdf"> <XIcon /> </AttachmentAction> </AttachmentActions> </Attachment> <Attachment className="w-64"> <AttachmentMedia variant="image"> <img src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%208%206'%3E%3Crect%20width='8'%20height='6'%20fill='%23a3a3a3'/%3E%3C/svg%3E" alt="Workspace" /> </AttachmentMedia> <AttachmentContent> <AttachmentTitle>workspace.png</AttachmentTitle> <AttachmentDescription>PNG · 820 KB</AttachmentDescription> </AttachmentContent> <AttachmentActions> <AttachmentAction aria-label="Remove workspace.png"> <XIcon /> </AttachmentAction> </AttachmentActions> </Attachment> <Attachment className="w-64"> <AttachmentMedia> <TableIcon /> </AttachmentMedia> <AttachmentContent> <AttachmentTitle>customers.csv</AttachmentTitle> <AttachmentDescription>CSV · 18 KB</AttachmentDescription> </AttachmentContent> <AttachmentActions> <AttachmentAction aria-label="Remove customers.csv"> <XIcon /> </AttachmentAction> </AttachmentActions> </Attachment> <Attachment className="w-64"> <AttachmentMedia> <FileCodeIcon /> </AttachmentMedia> <AttachmentContent> <AttachmentTitle>renderer.tsx</AttachmentTitle> <AttachmentDescription>TSX · 12 KB</AttachmentDescription> </AttachmentContent> <AttachmentActions> <AttachmentAction aria-label="Remove renderer.tsx"> <XIcon /> </AttachmentAction> </AttachmentActions> </Attachment> </AttachmentGroup> <AttachmentGroup className="w-full"> <Attachment orientation="vertical"> <AttachmentMedia> <FileTextIcon /> </AttachmentMedia> <AttachmentContent> <AttachmentTitle>invoice.pdf</AttachmentTitle> <AttachmentDescription>PDF</AttachmentDescription> </AttachmentContent> <AttachmentActions> <AttachmentAction aria-label="Remove invoice.pdf"> <XIcon /> </AttachmentAction> </AttachmentActions> </Attachment> <Attachment orientation="vertical"> <AttachmentMedia variant="image" className="aspect-square w-full"> <img src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%208%206'%3E%3Crect%20width='8'%20height='6'%20fill='%2394a3b8'/%3E%3C/svg%3E" alt="Desk" /> </AttachmentMedia> <AttachmentContent> <AttachmentTitle>desk.jpg</AttachmentTitle> <AttachmentDescription>JPG</AttachmentDescription> </AttachmentContent> <AttachmentActions> <AttachmentAction aria-label="Remove desk.jpg"> <XIcon /> </AttachmentAction> </AttachmentActions> </Attachment> <Attachment orientation="vertical"> <AttachmentMedia> <FileArchiveIcon /> </AttachmentMedia> <AttachmentContent> <AttachmentTitle>assets.zip</AttachmentTitle> <AttachmentDescription>ZIP</AttachmentDescription> </AttachmentContent> <AttachmentActions> <AttachmentAction aria-label="Remove assets.zip"> <XIcon /> </AttachmentAction> </AttachmentActions> </Attachment> <Attachment orientation="vertical"> <AttachmentMedia variant="image" className="aspect-square w-full"> <img src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%208%206'%3E%3Crect%20width='8'%20height='6'%20fill='%2378716c'/%3E%3C/svg%3E" alt="Office" /> </AttachmentMedia> <AttachmentContent> <AttachmentTitle>office.jpg</AttachmentTitle> <AttachmentDescription>JPG</AttachmentDescription> </AttachmentContent> <AttachmentActions> <AttachmentAction aria-label="Remove office.jpg"> <XIcon /> </AttachmentAction> </AttachmentActions> </Attachment> <Attachment orientation="vertical"> <AttachmentMedia> <FileTextIcon /> </AttachmentMedia> <AttachmentContent> <AttachmentTitle>notes.pdf</AttachmentTitle> <AttachmentDescription>PDF</AttachmentDescription> </AttachmentContent> <AttachmentActions> <AttachmentAction aria-label="Remove notes.pdf"> <XIcon /> </AttachmentAction> </AttachmentActions> </Attachment> </AttachmentGroup> </Example> )}
function AttachmentTriggers() { const [isVisible, setIsVisible] = React.useState(true)
return ( <Example title="Triggers" className="gap-3"> {isVisible ? ( <Attachment className="w-full"> <AttachmentMedia> <FileTextIcon /> </AttachmentMedia> <AttachmentContent> <AttachmentTitle>contract-review.pdf</AttachmentTitle> <AttachmentDescription>PDF · 820 KB</AttachmentDescription> </AttachmentContent> <AttachmentActions> <AttachmentAction aria-label="Download attachment"> <DownloadIcon /> </AttachmentAction> <AttachmentAction aria-label="Remove attachment" onClick={() => setIsVisible(false)} > <XIcon /> </AttachmentAction> </AttachmentActions> <AttachmentTrigger render={ <a href="#" target="_blank" rel="noreferrer" aria-label="Open contract-review.pdf" /> } /> </Attachment> ) : ( <Button variant="outline" onClick={() => setIsVisible(true)}> Restore attachment </Button> )} <Dialog> <Attachment className="w-full"> <AttachmentMedia> <FileSearchIcon /> </AttachmentMedia> <AttachmentContent> <AttachmentTitle>research-summary.pdf</AttachmentTitle> <AttachmentDescription>Open preview dialog</AttachmentDescription> </AttachmentContent> <AttachmentActions> <AttachmentAction aria-label="Copy link"> <CopyIcon /> </AttachmentAction> <AttachmentAction aria-label="Remove research-summary.pdf"> <XIcon /> </AttachmentAction> </AttachmentActions> <DialogTrigger render={ <AttachmentTrigger aria-label="Preview research-summary.pdf" /> } /> </Attachment> <DialogContent className="sm:max-w-md"> <DialogHeader> <DialogTitle>research-summary.pdf</DialogTitle> <DialogDescription> Attachment triggers can open dialogs while actions remain independently reachable. </DialogDescription> </DialogHeader> </DialogContent> </Dialog> </Example> )}