File Drop
betaFiles in: an empty slot with a dashed edge. While a file is over it, it takes the selection look and says "Drop to add". A press anywhere on it opens the picker.
Preview
drop
Drop your member list here or
size
Drop a photo here, sm or
Drop a photo here, md or
Drop a photo here, lg or
states
Drop the order list here or
Drop a file here or
Install
1. Add the registry to
components.json, once per app. Without it, the shadcn CLI looks up@txbrendanin a public list that txbrendan/ui does not control.npx shadcn@latest registry add "@txbrendan=https://txbrendan.dev/r/{name}.json"2. Add the theme, once per app. It replaces your color tokens with ones checked for contrast.
npx shadcn@latest add @txbrendan/theme3. Add the component.
npx shadcn@latest add @txbrendan/file-drop
Use it for
- Bringing files in, like a member list, an order list, or a team photo.
- Say what it is in title: "Drop your member list here". Say the types and the limit in hint: "CSV or Excel · up to 10 MB".
- The parent keeps the file list and does the uploading. Show each file in a file row.
- accept is checked for dropped files too, and multiple keeps only the first when it is off. Files of another type are left out, and it says so in red.
- Check size and contents on your server too. It only reads what the browser gives it.
Avoid it for
- A person's own photo. Use a photo field, which places and crops it.
- A link or text to paste. Use an input.
Props
- onFiles
The files picked or dropped, already checked against accept and multiple.
(files: File[]) => void
- accept
The types it takes, like ".csv,.xlsx" or "image/*". The picker shows only these, and drops are checked too.
string
- multiple
Takes several files at once. Off, it keeps the first.
boolean · default false
- title
Say what it is: "Drop your member list here".
ReactNode · default "Drop a file here"
- action
The words of the button that opens the picker.
ReactNode · default "choose a file"
- dropTitle
Shown while a file is over it.
ReactNode · default "Drop to add"
- hint
The types and the limit, like "CSV or Excel · up to 10 MB".
ReactNode
- size
Padding and text size.
"sm" | "md" | "lg" · default "md"
- disabled
Blocks the picker and drops. A file dropped on it is still caught, so the browser never opens it instead.
boolean · default false
- className
Classes for the zone.
string
| Prop | Type | Default | What it does |
|---|---|---|---|
| onFiles | (files: File[]) => void | - | The files picked or dropped, already checked against accept and multiple. |
| accept | string | - | The types it takes, like ".csv,.xlsx" or "image/*". The picker shows only these, and drops are checked too. |
| multiple | boolean | false | Takes several files at once. Off, it keeps the first. |
| title | ReactNode | "Drop a file here" | Say what it is: "Drop your member list here". |
| action | ReactNode | "choose a file" | The words of the button that opens the picker. |
| dropTitle | ReactNode | "Drop to add" | Shown while a file is over it. |
| hint | ReactNode | - | The types and the limit, like "CSV or Excel · up to 10 MB". |
| size | "sm" | "md" | "lg" | "md" | Padding and text size. |
| disabled | boolean | false | Blocks the picker and drops. A file dropped on it is still caught, so the browser never opens it instead. |
| className | string | - | Classes for the zone. |
Accessibility
- The one Tab stop is the "choose a file" button. Its description is the title and the hint, so it is heard as "choose a file, Drop your member list here".
- A press anywhere on the zone opens the same picker, for the mouse and touch.
- A polite status says what was added, like "Added Members 2026.csv".
- Files of another type are left out, and a red message says so once.
- While a file is over it, the dashed edge turns solid, so forced-colors mode shows the change too.
Examples
A member list
<FileDrop
title="Drop your member list here"
hint="CSV or Excel · up to 10 MB"
accept=".csv,.xlsx"
multiple
onFiles={(files) => console.log(files)}
/>