A file queue with raster previews, per-file progress, cancellation, retry and application-owned upload transport.
Files upload as soon as you add them.
pnpm dlx shadcn@latest add @latheui/upload-managerPart of Lathe Pro. Set up your project once with your license key: npx latheui init --key <key>. See Lathe Pro.
Upload Manager is part of Lathe Pro
The preview is live and free to try. The source, the install and every assembly come with Pro: $79 once, with lifetime updates.
Depends on
| Prop | Type | Default | Description |
|---|---|---|---|
| title | string | "Upload files" | Visible heading and accessible section name. |
| onUpload* (required) | (file: File, context: UploadContext) => Promise<void> | — | Required transport callback. Resolve only when the upload is confirmed; reject with an Error for a retryable message. |
| onEntriesChange | (entries: UploadEntry[]) => void | — | Observe queue changes, including progress. The manager owns the queue; this callback does not control it. |
| accept | string | — | Comma-separated extensions or MIME types, as on a file input. Validate uploads again on your server. |
| maxSize | number | 10485760 | Maximum bytes per file, enforced by FileDropzone. |
| maxFiles | number | 5 | Maximum queue length, including complete, failed and cancelled files. Remove a file to free a slot. |
| hint | string | — | Optional dropzone help. Defaults to text derived from the file and size limits. |
| disabled | boolean | false | Disable adding files and queue actions. Existing uploads continue. |
| className | string | — | Override the max-w-lg card layout. |
| UploadContext | { signal: AbortSignal; onProgress: (percent: number) => void } | — | Respect signal to stop work. Report percentages from 0 to 100 when available; progress is monotonic within an attempt. |
| UploadEntry | { id: string; file: File; state: "uploading" | "complete" | "error" | "cancelled"; progress?: number; error?: string } | — | Queue snapshot supplied to onEntriesChange. IDs remain stable across retries. |
Use an upload client that reports bytes transferred, pass its abort handling the signal, and resolve after the server confirms success. Cancellation and unmount ignore late results from old attempts.
<UploadManager
accept="image/*,.pdf"
maxFiles={3}
hint="Images and PDFs · Up to 3 files"
onUpload={(file, { signal, onProgress }) =>
uploadFile(file, {
signal,
onBytes: (sent, total) => onProgress((sent / total) * 100),
})
}
/>