01 — Foundation

Uploads need progress and honesty

Users should know what they selected, what is uploading, and what happened when it finishes.

File uploads are high-anxiety interactions — large files, slow networks, and silent failures make people repeat attempts or abandon tasks. Good upload UI shows selection, progress, success, and recoverable errors without hiding behind a generic spinner.

02 — Input

Accessible file selection

Start with a native file input before custom drag-and-drop chrome.

  • visible label and button — not a hidden input on a div alone
  • state accepted types and size limits in plain language before selection — see GOV.UK file upload
  • show selected file names, sizes, and remove controls before upload starts
  • drag-and-drop as enhancement — keyboard users must reach the same control
<label for="invoice-file">Invoice (PDF, max 10 MB)</label>
<input id="invoice-file" name="invoice" type="file" accept=".pdf,application/pdf" />

03 — Progress

Progress, success, and failure

Long uploads need percentage or stage text — not an endless spinner.

  • progress bar or status text for uploads users will wait on
  • disable duplicate submits while uploading — see Async Actions
  • specific errors — “File too large”, “Unsupported type”, “Upload timed out”
  • allow retry without forcing users to re-select unless the file was rejected

04 — Safety

Validation and security basics

Client checks help UX; server validation is non-negotiable.

  • validate type and size on the server — never trust the browser alone
  • virus scanning and storage policies belong in backend docs — UI sets expectations
  • multiple files — show per-file status; one failure should not erase others silently

05 — Review

Before you approve

A short checklist for file uploads in code review.

  • labelled input, clear constraints, and visible selected files
  • progress and outcomes are specific; retry is obvious on failure
  • drag-and-drop does not replace keyboard access