How to build an accessible FileUploader in React
The drop zone is a real <button> so it is keyboard-operable (Enter/Space open the native file picker), the hidden file input is removed from the tab order and labelled via aria-describedby, and the file list uses aria-live="polite" so status changes are announced; each remove control carries an aria-label naming its file.
When to use a FileUploader
- Letting users attach one or more files via click-to-browse or drag-and-drop
- Showing per-file upload progress and status (uploading, complete, error) in a list
- Enforcing client-side accept/maxSize constraints with a callback for rejected files
When not to use it
- A single short text value — use Input
- Choosing from a fixed set of options rather than supplying a file — use Select or MultiSelect
Keyboard interactions
Role button, verified at WCAG 2.2-AA.
EnterSpace
Common mistakes
Avoid: Treating the component as uncontrolled and ignoring onFilesAdded
Prefer: Track accepted files in state and pass them back via the files prop
The file list is controlled — without wiring files/onFilesAdded/onRemove nothing renders in the list and status cannot update
Avoid: Relying only on accept/maxSize for security
Prefer: Re-validate type and size on the server after upload
Client-side accept/maxSize are UX filters, not enforcement; a determined user can bypass them
Example
<FileUploader onFilesAdded={console.log} />