✨ Working with PDFs, images or videos? Discover 145+ free web apps built for everyday tasks

Attachment

A file attachment row with a status-driven icon (ready, uploading, processing, uploaded, failed), shimmering title while busy, image thumbnail cards, and a smooth remove animation.

Loading preview...

Examples

Practical examples and common states for the same installable component.

Compact

Minimal file attachment for dense interfaces.

examples/attachment-compact.tsx
import { Attachment } from "@/components/wensity/attachment";
export function AttachmentCompact() {
return (
<div className="flex flex-col gap-2">
<Attachment variant="compact" fileName="invoice-2024-q4.pdf" fileSize={182_000} />
<Attachment variant="compact" fileName="brand-assets.zip" fileSize={8_400_000} />
<Attachment variant="compact" fileName="notes.txt" fileSize={4_200} />
</div>
);
}

Preview

Rich attachment with image or file preview.

examples/attachment-preview.tsx
import { Attachment } from "@/components/wensity/attachment";
export function AttachmentPreview() {
return (
<div className="flex flex-wrap gap-3">
<Attachment
variant="preview"
fileName="workspace.png"
fileSize={820_000}
thumbnailSrc="https://images.unsplash.com/photo-1497366216548-37526070297c?auto=format&fit=crop&w=300&q=80"
/>
<Attachment
variant="preview"
fileName="desk-reference.jpg"
fileSize={1_100_000}
thumbnailSrc="https://images.unsplash.com/photo-1497215728101-856f4ea42174?auto=format&fit=crop&w=300&q=80"
/>
</div>
);
}

Upload

Attachment with uploading progress and status.

examples/attachment-upload.tsx
import { Attachment } from "@/components/wensity/attachment";
export function AttachmentUpload() {
return (
<div className="flex flex-col gap-2">
<Attachment variant="upload" fileName="selected-file.pdf" status="pending" />
<Attachment
variant="upload"
fileName="design-system.zip"
status="uploading"
progress={64}
/>
<Attachment variant="upload" fileName="market-research.pdf" status="processing" />
<Attachment
variant="upload"
fileName="financial-model.xlsx"
status="error"
errorMessage="Upload failed. Try again."
onRetry={() => {}}
/>
<Attachment
variant="upload"
fileName="uploaded-report.pdf"
status="success"
fileSize={1_800_000}
/>
</div>
);
}

Removable

Attachment with clear remove action.

examples/attachment-removable.tsx
import { useState } from "react";
import { Attachment } from "@/components/wensity/attachment";
export function AttachmentRemovable() {
const [files, setFiles] = useState([
{ id: "1", name: "design-system.fig", size: 5_800_000 },
{ id: "2", name: "user-research.pdf", size: 1_100_000 },
]);
return (
<div className="flex flex-col gap-2">
{files.map((file) => (
<Attachment
key={file.id}
variant="removable"
fileName={file.name}
fileSize={file.size}
onRemove={() => setFiles((prev) => prev.filter((f) => f.id !== file.id))}
/>
))}
</div>
);
}

Download

File attachment optimized for downloading.

examples/attachment-download.tsx
import { Attachment } from "@/components/wensity/attachment";
export function AttachmentDownload() {
return (
<Attachment
variant="download"
fileName="onboarding-guide.pdf"
fileSize={960_000}
downloadHref="https://example.com/onboarding-guide.pdf"
/>
);
}