Dropzone

Takes files you drop in or pick, and tells you which ones won't work.

Examples

Add a receipt

Several at once

Small, with your own words

Content

  • defaultdefault

  • children

States

  • rest

  • hover

  • focus-visible

  • dragging over

  • disabled

Usage

When to use it
Use
The person brings a file in: a receipt, a statement, a proof of address.
Use
Several files at once, where dragging from a folder is the quick way.
Not for
A small attach action in a message. Use a button that opens the picker. Use Button.
Not for
The file is chosen from saved receipts. Use List.

Rules

8 rules
Must
Read onReject and say which file and why in a role="alert" line; the zone draws no error. Because files that miss accept or maxSize go only to onReject, so without it they vanish.
Must
State the types and size limit in hint. Because the check runs after the drop, so the person learns the limit only once it fails.
Should
Start the title with a verb and name the thing, such as "Drop a receipt to start"; never "Upload".
Should
Leave multiple off for one file; extras are rejected with reason count.
Never
Style a bare file input by hand. Because it loses the label wiring, the lime drag wash and the type and size checks.
Must
Set maxSize in bytes and check size again on the server. Because maxSize={10} rejects every file over 10 bytes, and a client check is easy to bypass.
Must
Put results in a role="status" or role="alert" line beside the zone. Because the zone has no live region, so a drop or a reject is silent to a screen reader.
Should
Show upload progress in a list below the zone; Dropzone only hands files over.

Accessibility

4 checks
A label around a visually hidden file input; the input takes focus and the zone shows the ring.
Enter and Space open the picker.
Name comes from the title and hint.
Report accepted and rejected files in a status or alert line.

Edge cases

7 edge cases
Long title
Wraps in the centred column.
Narrow to 160px
It is w-full; the text wraps in several lines.
Right to left
Content is centred and mirrors with no change. The default "or choose from your device" line is English; pass children for another language.
Dropped text, not a file
The zone highlights then does nothing; no onFiles or onReject.
Drag over inner element
The over state can flicker; count enters and leaves.
Phone
No drag; pressing the zone opens the picker.
Forced colors
The dashed border stays; data-over adds a Highlight outline.

API

8 props
onFiles
(files: File[]) => void
onReject
(rejected: {file, reason}[]) => void
accept
string
maxSize
number
multiple
boolean default false
title, hint
string default 'Drop files here'
children
ReactNode
disabled
boolean default false

Tokens

15 tokens
--surface
#f6f5f2
--surface-2
#efeeea
--control
#85827a
--radius-panel
16px
--fg
#0f0f0d
--fg-2
#4a4943
--fg-3
#6b6a63
--accent-wash
#f5f9c4
--accent-line
#7c8700
--ring
var(--accent-line)
--line-focus
2px
--focus-offset
2px
--line-strong
#cfcdc6
--fg-disabled
#a6a49b
--page
#ffffff

Install

For your coding agent

GitHub

Please star me pookie

141

A new design system every week

Leave your email before you copy the prompt.