Forms
File Upload
File Upload is a native file input with drag-and-drop dropzone, advisory validation, selected-file list, and multipart form submission — selection only, not network upload.
State (Empty/Dragging/Filled/Error/Disabled) — 5 variants
- React last updated
- 2026-07-13
- Documentation last updated
- 2026-06-01
- Accessibility target
- WCAG 2.2 AA (target)
- Version
- 0.1.0-beta
Known open questions
- Controlled files prop is intentionally unsupported in this MVP.
- Upload progress, retry, preview, and async behavior are deferred.
Purpose
Anatomy
Variants and states
When to use
When not to use
Accessibility
Keyboard behavior
Common mistakes
Properties
What does File Upload own?
Does File Upload perform the network upload?
Can File Upload submit through a native form?
How are rejected files reported?
Why is server-side validation still required?
Tokens used
Known limitation
Component API
| Prop | Type | Default | Description |
|---|---|---|---|
| name | string | — | Native file input name for multipart submission. |
| label | string | — | Visible field label via FormField. |
| accept | string | — | Native accept attribute (MIME, wildcard, or extension). |
| multiple | boolean | false | Allows selecting more than one file. |
| maxFiles | number | — | Maximum accepted files in multiple mode. |
| maxSize | number | — | Maximum file size in bytes. |
| required | boolean | — | Native required validation on the file input. |
| disabled | boolean | — | Disables selection, drop, and remove actions. |
| error | string | — | Consumer-owned field error via FormField. |
| onFilesChange | (files: File[]) => void | — | Fires once with accepted files after each replacement selection. |
| onRejectedFiles | (rejections) => void | — | Fires once with advisory rejection details. |
React example
import { FileUpload } from "@/components/ui/FileUpload";
export function Example() {
return (
<FileUpload
label="Upload documents"
name="documents"
accept="image/png,image/jpeg,.pdf"
multiple
maxFiles={3}
maxSize={5_000_000}
supportingText="PNG, JPG, or PDF up to 5 MB. Your app owns the upload request."
/>
);
}