File Dropzone
Drag files in and the dashed tube border powers up. Lists files with progress.
Built on Icons.
Launch assets
Everything here ships with the Aurora press release.
Drop files here or browse
Images, video, PDF or ZIP · up to 200 MB each
aurora-hero@2x.png
2.7 MB, Uploaded
launch-keynote.mov
84 MB, 6%
press-kit.zip
14 MB, Queued
aurora-brief.pdf
819 KB, Queued
Installation
npx shadcn@latest add https://neonkit.heyaadi.com/r/file-dropzone.jsonUsage
import { FileDropzone, FileList } from "@/components/ui/file-dropzone"
<FileDropzone
accept="image/*,.pdf"
maxSize={10 * 1024 * 1024}
description="Images or PDF · up to 10 MB"
onFilesChange={(files) => upload(files)}
/>
<FileList files={uploads} onRetry={retry} onRemove={remove} />Examples
Single image
With multiple off and custom children, the zone becomes a profile photo picker with a live preview.
Limits and rejections
Rejections come back with a reason and a message. maxFiles applies per drop, so pass the slots that are left.
File list states
Queued, uploading, done and failed, with type icons picked from the MIME type or extension.
API reference
FileDropzone
Also accepts native div attributes, and the ref points at the zone. Files come in by click, Enter or Space (the system picker), drag and drop, or paste while focused.
| Prop | Type | Default |
|---|---|---|
accept | stringSame format as the input attribute: ".png,.pdf", "image/*", "application/zip". | None |
multiple | booleanAllow more than one file per drop or selection. | true |
maxSize | numberLargest accepted file, in bytes. | None |
maxFiles | numberMost files accepted per drop or selection. Extra files are rejected. | None |
disabled | booleanIgnores clicks, drops and paste. | false |
name | stringSubmits the last accepted files under this name with a surrounding form. Use encType="multipart/form-data". | None |
required | booleanWith name, stops the submit until a file is accepted. | false |
onFilesChange | (files: File[]) => voidCalled with the files that passed every check. | None |
onReject | (rejections: FileRejection[]) => voidCalled with each refused file and why. | None |
label | ReactNodeMain line of the default content. | "Drop files here or browse" |
description | ReactNodeSecond line, e.g. accepted types and size limit. | None |
children | ReactNodeReplaces the default content. Keep it non-interactive; the whole zone is the button. | None |
color | NeonColorPalette name or hex. Falls back to --neon-accent, then cyan. | inherited |
FileRejection
| Prop | Type | Default |
|---|---|---|
file | FileThe refused file. | None |
reason | "file-type"Which check it failed. | None |
message | stringA short sentence you can show as is, like "Larger than 10 MB". | None |
FileList
Renders a list. Also accepts native ul attributes; pass aria-label to name it.
| Prop | Type | Default |
|---|---|---|
files | FileListItem[]The rows, in order. | None |
onRemove | (id: string) => voidShows a remove button on every row (labelled Cancel while uploading). | None |
onRetry | (id: string) => voidShows a retry button on rows that failed. Other rows keep the slot empty, so the tubes end in one column. | None |
color | NeonColorPalette name or hex for the progress tubes. | inherited |
FileListItem
| Prop | Type | Default |
|---|---|---|
id | stringUnique id, also the React key. | None |
name | stringFile name. The icon falls back to its extension. | None |
size | numberSize in bytes. | None |
type | stringMIME type, used to pick the icon. | None |
progress | number0 to 100. | None |
status | "queued"Drives the tube, the status text and the actions. | None |
error | ReactNodeShown in place of the status when it failed. | "Upload failed" |
formatBytes
The size formatter the list uses, exported for your own copy.
| Prop | Type | Default |
|---|---|---|
bytes | numberReturns "2.4 MB", "512 KB" or "18 B". | None |
Accessibility
- The zone is a role="button": Enter and Space open the system file picker, which is a hidden native file input.
- Focus the zone and paste to add files from the clipboard.
- A polite live region announces how many files were added and why any were refused. The list announces finished and failed uploads, not every progress tick.
- Each row's progress tube is a role="progressbar" named after the file.
- The border is drawn in SVG with the dash period fitted to the perimeter, so the loop has no seam. Marching and the drop bloom turn off with reduced motion.