File Upload
Dropzone, file list, and per-file item. Storage-agnostic; app owns the upload pipeline.
react-dropzone docsSingle image
Constrain the dropzone to images and a single file. The library handles the UI; the app owns the upload pipeline (here it's a 2-second mock). Thumbnail previews come from the `preview` prop on FileItem.
Drag files here or click to browse
Accepts .png, .jpg, .jpeg, .webp
<FileDropzone
onFilesSelected={start}
accept={{ "image/*": [".png", ".jpg", ".jpeg", ".webp"] }}
multiple={false}
/>
<FileList>
{rows.map((r) => (
<FileItem
key={r.id}
name={r.file.name}
size={r.file.size}
type={r.file.type}
preview={r.preview}
status={r.status}
progress={r.progress}
onRemove={() => remove(r.id)}
/>
))}
</FileList>Multiple PDFs
Accept only PDFs with a file cap. Non-image files fall back to a document icon thumbnail.
Drag files here or click to browse
Accepts .pdf
<FileDropzone
onFilesSelected={start}
accept={{ "application/pdf": [".pdf"] }}
maxFiles={5}
/>Any file type
No `accept` constraint means the dropzone allows any file. Images get thumbnails, everything else gets a type-appropriate icon.
Drag files here or click to browse
<FileDropzone onFilesSelected={start} />Button with thumbnail
Compact pattern for forms. `FileButton` opens the picker without the drop area. Compose with `FileThumbnail` for an inline preview.
<FileThumbnail preview={preview} type={selected?.type} />
<FileButton
variant="outline"
onFilesSelected={(files) => setSelected(files[0])}
accept={{ "image/*": [".png", ".jpg", ".jpeg", ".webp"] }}
>
{selected ? "Change image" : "Upload image"}
</FileButton>Avatar upload (circle)
Compact circular dropzone for profile photos. Shows the selected image, or an icon fallback. Click or drag to upload. Remove button appears when an image is set.
<AvatarUpload
src={src}
onFilesSelected={(files) => setSrc(URL.createObjectURL(files[0]))}
onRemove={() => setSrc(undefined)}
/>Avatar upload (square)
Same component with `shape="square"` for rounded-square tiles (app icons, thumbnail previews).
<AvatarUpload
src={src}
shape="square"
onFilesSelected={(files) => setSrc(URL.createObjectURL(files[0]))}
onRemove={() => setSrc(undefined)}
/>