Usage
FileUploadArea and FileUploadCard collect files under enforced constraints and surface progress, success, and failure honestly. Dispatch uses the pair for supervisor onboarding (bulk user CSV), protocol document imports, and evidence-grade audio attachments—contexts where a silent failure or an opaque error becomes an operational problem. The mental model is "drop it, see it, fix it": constraints are visible before the drop, progress is visible during, and the resulting status card stays on the page until the operator removes or retries it. Quiet auto-dismiss is the wrong shape for any file that matters.
Evidence audio, protocol PDFs, user-roster CSVs, incident images. Upload UI is the place where the policy lives—surface it in the copy so operators aren't surprised by a server rejection.
Uploading five files and having one fail: each should render as its own FileUploadCard with an independent status (uploading, success, error, removable) so the operator can retry or replace without starting over.
Client-side checks for type, size, and count fail fast; server-side checks for content (audio duration, CSV schema, malware scans) arrive later. The card surface is where both conversations happen.
Use Input. A drop target is overkill for text entry.
If there's no user in the loop, skip the UI and process server-side. File-upload UI exists to give a human a chance to see and fix.
Use a plain drop target. FileUpload pairs a drop affordance with a browse button because dispatch operators frequently paste file paths or pick from dialogs rather than drag from the desktop.
| Variant | Purpose | Emphasis |
|---|---|---|
FileUploadArea | Drop target + browse trigger | One per surface; the copy names what's allowed |
FileUploadCard | One card per file-in-flight | Keep it visible until the operator removes or confirms |
Custom limitationsText | Domain-specific rules beyond defaults | Use when the policy isn't obvious from MIME and size alone ("No audio over 10 minutes") |
The area holds a headline, optional limitationsText (allowed types, size cap, count cap), and a browse button that triggers the native file picker. Cards render below or alongside the area, one per file, each with a status badge, filename, optional thumbnail, removal control, and—when applicable—a retry affordance.
Lead with what's allowed, in plain language: "Drop a CSV up to 5 MB" rather than "application/csv, max 5000000 bytes". Spell out per-file and total caps separately; operators read one limit, not two unless you show two.
Explain remediation in the same sentence as the failure ("File is 12 MB; try a smaller PDF or split it"). Include HTTP status only when it helps the user; prefer human-readable explanations backed by a dev log.
formatMessage; test the longest translation inside the card's width.Do
Don't
Drop targets, per-card status, and progress updates need deliberate labelling so screen readers can follow the state machine. Associate errors with the upload region; make the remove button keyboard operable; provide text alternatives for icon-only status. See Accessibility for the full contract including live-region patterns for progress and failure.
On this page