Prodular UI

File upload

Pro

A dropzone with drag-over state, click or keyboard to browse and type and size checks, plus a file list with type icons, progress, success and error states, remove and retry.

npx prodular-ui add file-upload

Part of Prodular UI Pro. Preview and read the docs freely, install with a license. See pricing

Attachments

Simulated uploads. Every third new file fails halfway so you can try Retry. Files over 10 MB or of other types are rejected with a message.

Drop files here or browsePDF, CSV, XLSX or images, up to 10 MB each
  • q3-revenue-report.pdf
    2.4 MB · Uploaded
  • customers-export-oct.csv38%
    x
    2.5 MB of 6.6 MB
  • signed-msa-northwind.png
    Connection lost at 64%. Try again.

Single file import

One CSV at a time. The dropzone is replaced by the file once it is picked.

Import customers

One customer per row. We match on email and update existing records.

Drop a CSV here or browseCSV only, up to 25 MB

Anatomy

<FileUpload accept=".pdf,.csv" maxSize={10_000_000} onFilesAccepted={startUploads}>  <FileUploadDropzone hint="PDF or CSV, up to 10 MB" />  <FileUploadList>    {files.map((f) => (      <FileUploadItem key={f.id} name={f.name} size={f.size} progress={f.progress} status={f.status} onRemove={() => remove(f.id)} />    ))}  </FileUploadList></FileUpload>

Guidance

Use it when

  • Attaching documents to a record, importing a CSV, uploading a logo.
  • The list on its own to show files that are already attached.

Avoid

  • Hiding the limits. Always say which types and how large in the hint.
  • Removing failed files automatically. Keep them with a reason and a retry.

Rules for AI agents

Published in llms-full.txt, the registry and the MCP server, so coding agents follow them when they build with this component.

  • FileUpload validates and hands you files in onFilesAccepted; it does not upload. Keep your own list state with progress and status, and render a FileUploadItem per file.
  • Set accept and maxSize, and repeat them in plain words in the dropzone hint, for example PDF or CSV, up to 10 MB.
  • Show onFilesRejected messages near the dropzone in a role="alert" paragraph using text-destructive-subtle-foreground.
  • Pass currentCount together with maxFiles so the limit counts files already in the list.
  • On failure set status="error" with an error message that says what happened, and pass onRetry.
  • Use multiple={false} and hide the dropzone after a pick for single-file flows.

API

FileUpload

PropTypeDefaultDescription
acceptstringInput accept syntax: ".pdf,.csv,image/*".
maxSizenumberLargest file in bytes.
maxFiles / currentCountnumberTotal file limit and how many are already listed.
multiplebooleantrueAllow several files per pick.
onFilesAccepted(files: File[]) => voidFiles that passed validation.
onFilesRejected(rejections: FileRejection[]) => voidEach rejected file with reason and message.

FileUploadDropzone

PropTypeDefaultDescription
hint / title / browseLabelReactNodeCopy inside the default dropzone. Pass children to replace it entirely.

FileUploadItem

PropTypeDefaultDescription
status"queued" | "uploading" | "complete" | "error""queued"Drives the icon, progress bar and meta text.
progressnumber00 to 100 while uploading.
onRemove / onRetry() => voidShow remove (or cancel while uploading) and retry on error.

Installation

The Prodular UI CLI adds the source to components/ui with everything it depends on. In a project that already uses shadcn/ui, the shadcn CLI installs it from the Prodular registry too. See Installation for the first setup.

npx prodular-ui add file-upload# or, with the registry in components.jsonnpx shadcn@latest add @prodular/file-upload