affectUI › Components › Inputs
Dropzone
Drag files in and watch them upload – fanning documents, colored type badges, progress with time left, errors with retry.
Part of affectUI Pro. Install: npx shadcn@latest add https://www.affectui.com/r/dropzone.json · Import from @/components/ui/dropzone
When to use
- Uploading documents, images or media – attachments, imports, asset libraries, onboarding
- Several files at once, where people want to see what's done, what's still running and what failed
When not to use
- A single avatar or logo – a simple picker with a preview is lighter
- Huge uploads that run in the background for minutes – show them in a separate transfer panel
Usage
import { Dropzone } from "@/components/ui/dropzone";
export function Attachments() {
return (
<Dropzone
accept={[".pdf", ".png", ".jpg", ".xlsx"]}
maxSize={25 * 1024 * 1024}
onUpload={(file, onProgress) =>
new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.upload.onprogress = (e) => onProgress(e.loaded / e.total);
xhr.onload = () => (xhr.status < 300 ? resolve() : reject(new Error("Upload failed")));
xhr.onerror = () => reject(new Error("Upload failed – connection lost"));
xhr.open("POST", "/api/upload");
xhr.send(file);
})
}
onChange={(items) => setAttachments(items.filter((i) => i.status === "done"))}
/>
);
}Props
| Name | Type | Default | Description |
|---|---|---|---|
accept | string[] | Allowed extensions, e.g. [".pdf", ".png"]; any file when left out. Other files get a row with an error | |
maxSize | number | 25 MB | Largest file in bytes; bigger files get a "Too large" row |
onUpload | (file: File, onProgress: (p: number) => void) => Promise<void> | Uploads one file and reports progress from 0 to 1; reject to mark it as failed (the message is shown, Retry calls it again). Simulated when left out | |
onChange | (items: UploadItem[]) => void | Every change of the list: { id, name, size, status, progress, error?, file? } | |
hint | string | Text under the title; defaults to the accepted types and the size limit | |
autoplay | boolean | false | Plays a sample drop of four files – for previews and landing pages |
className | string | Extra class on the root |
Keyboard
- Tab: Reaches the drop area, then Retry and Remove in every row
- ↵: On the drop area: opens the file picker (Space works too)
Accessibility
- The drop area is a button that opens the file picker, described by the accepted types and size
- Every row has a progress bar with its value; Retry and Remove are named after the file
- Finished, failed and rejected files are announced in a polite live region
Responsive
- Fills its container up to 520px; long file names are cut with an ellipsis
- Dark mode built in: switches when an ancestor (usually <html>) has the class dark or data-theme="dark"
Requirements
- React 19
Related
- Chat Composer – Prompt composer with model picker, voice input, app connections and approval request
- AI Answer – Streamed answer with source cards, citation chips that preview their source, copy, regenerate, feedback and follow-ups
- Glass Folder – Glassy blue folder with documents behind a frosted pocket that tips open on hover