File Upload
A drop zone with a browse button and the list of chosen files, with size and type checks.
Preview
Installation
pnpm add @syntara/react @syntara/tokensimport { FileUpload } from '@syntara/react';Usage
import { FileUpload } from '@syntara/react';
export function Receipts() {
return (
<FileUpload
label="Receipts"
acceptedFileTypes={['image/png', 'image/jpeg', 'application/pdf']}
maxSize={10 * 1024 * 1024}
allowsMultiple
onChange={(files) => console.log(files)}
/>
);
}Examples
Progress and errors
Pass FileUploadEntry objects to show upload progress, a finished state, or a per-file error.
- invoice-march.pdf842 kBUploaded
- site-photo-01.jpg2.3 MB64%
- site-photo-02.jpg1.9 MBUpload failed. Check your connection and try again.
Single file
Without allowsMultiple a new file replaces the current one. Prompt copy is customisable.
Invalid and disabled
A field-level error, and a disabled upload.
Accessibility
| Keys | Action |
|---|---|
| Tab | Focuses the drop zone, then the browse button, then each file's remove button. |
| EnterorSpace (browse) | Opens the system file dialog. |
| Ctrl/⌘V (drop zone) | Pastes files from the clipboard. |
| Enter (drop zone) | Drops the item being dragged with keyboard drag and drop. |
| EnterorSpace (remove) | Removes that file (or dismisses a rejected one). |
- The drop zone is labelled by the field label; the browse button is described by the hint, description and error.
- Rejected files are listed with their reason in a role="alert" so the refusal is announced.
- Upload progress is a labelled progressbar ("Uploading invoice.pdf"); finished and failed files show an icon and text, not colour alone.
- Remove buttons are named per file ("Remove invoice.pdf").
- Drag-over is shown by a solid brand border, tint, halo and a filled upload badge, not motion alone. The swell, badge lift, staggered row rise and progress glide only run without prefers-reduced-motion; fades remain.
Guidelines
Do
- State accepted types and the size limit up front (the default hint does this).
- Show progress and a clear per-file error with a way to remove and retry.
- Validate again on the server — the client checks are for fast feedback, not security.
Don’t
- Don't make the drop zone the only way in — keep the browse button.
- Don't silently drop files that fail a check — say why.
API reference
FileUpload
labelReactNodeVisible label; also names the drop zone and the file list.
descriptionReactNodeHelp text under the drop zone, linked to the browse button.
errorMessageReactNodeField-level error, shown under the drop zone when isInvalid is true.
acceptedFileTypesstring[]MIME types or extensions, e.g. ['image/*', '.pdf']. Filters the file dialog; dropped files that don't match are rejected with a message.
allowsMultiplebooleanAllow more than one file. Without it a new file replaces the current one.
Default
falsemaxSizenumberMaximum bytes per file. Larger files are rejected with a message. Sizes display 1024-based (1 MB = 1,048,576 bytes).
filesReadonlyArray<File | FileUploadEntry>Controlled list. FileUploadEntry = { file, progress?: 0–100, error?: string } adds a progress bar, an "Uploaded" state at 100, or an error.
defaultFilesFile[]Initial files when uncontrolled.
onChange(files: File[]) => voidCalled with the full list of accepted files after every add or remove.
onReject(rejections: FileRejection[]) => voidCalled with files that were refused: { file, reason: 'type' | 'size' | 'count', message }.
hintReactNodeText under the prompt. Defaults to the accepted types and max size, e.g. "PNG, PDF, up to 10 MB".
dropLabelReactNodePrompt text before the browse link.
Default
'Drag files here or'browseLabelReactNodeText of the browse link that opens the file dialog.
Default
'browse'isInvalid / isDisabledbooleanField states.
Default
false
Tokens
The semantic tokens this component reads, grouped by what they control. Swatches show this site’s theme; change a tenant’s brand and the component follows with no code change.
- Colour17
border.strongsurface.defaulttext.defaulttext.subtlefocus.ringaction.primary.bgsurface.selectedfeedback.danger.solidborder.defaultsurface.sunkentext.disabledsurface.raisedaction.primary.fgfeedback.danger.borderfeedback.danger.bgfeedback.danger.fgfeedback.success.fg- Type5
font.size.mdfont.weight.mediumline-height.snugfont.size.smfont.size.xs- Space and size6
space.2space.6space.4control-heightspace.1space.3- Shape3
radius.containerradius.pillradius.field- Depth3
shadow.raisedshadow.highlightshadow.overlay- Motion6
motion.duration.fastmotion.easingmotion.duration.slowmotion.easing-outmotion.duration.springmotion.spring