ComponentsData display
Files attached to a record — contracts on a deal, an employee's documents, a post's downloads. Mime icons tinted per file family, sizes in the current locale, upload progress, processing and error states, preview, download, remove with undo, and an add button or your own upload slot.
Native list semantics + Intl.NumberFormat (bytes) components/attachment-list.tsx, styles/data.csstheme · material · accent · density · font
Installation
$ pnpm add @vamos-ui/react
The whole kit as one package — get updates by bumping the version. Add the styles to globals.css: @import "@vamos-ui/react/styles.css";
Usage
import { AttachmentList } from "@vamos-ui/react";
<AttachmentList
items={files}
onPreview={(file) => openLightbox(file)}
onRemove={(file) => removeWithUndo(file)}
onAddFiles={(files) => upload(files)}
/>Examples
Thumbnail grid
layout="grid": image thumbnails, or a tinted tile with the extension for other files.
Uploading, processing, error (HR)
Progress is a progressbar with aria-valuetext like "45%, contract.pdf"; errors offer Retry.
Employment contract — Selin Arslan.pdfUploading… 12%
Passport scan.pngProcessing…
Diploma (notarised).tiffFile is larger than 10 MB
Bank details form.pdf96 kB · Selin Arslan · Nov 9, 2026
Inline chips and empty
layout="chips" for comments and forms; readOnly hides remove and add.
No files on this ticket yet
API
AttachmentList
| Prop | Type | Default |
|---|---|---|
itemsFiles to show. | AttachmentData[] | — |
layoutRows with meta, thumbnail tiles or inline chips. | "list" | "grid" | "chips" | "list" |
sizeRow height and text size (list). | "sm" | "md" | "md" |
onPreviewMakes the name a button (open a Lightbox). Without it a file with url links to it. | (file) => void | — |
onDownloadDownload button. Default: a native download link when url is set. | (file) => void | — |
onRemoveRemove button; the row fades until the promise settles. | (file) => void | Promise<void> | — |
onRetryRetry on failed uploads. | (file) => void | — |
onAddFilesBuilt-in "Add files" button with a file chooser. | (files: File[]) => void | — |
acceptaccept for the built-in chooser. | string | — |
uploadSlotYour own upload control after the files (File upload drop zone). | ReactNode | — |
readOnlyHides remove, retry and add. | boolean | false |
emptyShown when there is nothing to list or add. | ReactNode | "No files attached" |
labelslist, empty, preview, download, remove, retry, uploading, progress, processing, failed, add. | Partial<AttachmentListLabels> | — |
AttachmentData
| Prop | Type | Default |
|---|---|---|
id / name / size / mimeIdentity, file name with extension, bytes, MIME type. | string / string / number / string | — |
url / thumbUrlOpen/download URL and image thumbnail. | string | — |
uploadedBy / uploadedAtMeta line: "1.2 MB · Ayşe Kaya · Nov 4, 2026". | string | — |
statusUpload state. | "uploading" | "processing" | "ready" | "error" | "ready" |
progress / error0–100 while uploading; message on error. | number / string | — |
Helpers
| Prop | Type | Default |
|---|---|---|
AttachmentIconThe tinted mime tile on its own. | { mime, name, size } | — |
AttachmentNameFile name that truncates its base but keeps the extension. | { name } | — |
attachmentKind(mime, name)pdf, image, document, spreadsheet, presentation, archive, audio, video, code, text, other. | AttachmentKind | — |
splitFileName(name)"contract.final.pdf" → ["contract.final", ".pdf"]. | [base, ext] | — |