DropZone component
Draggable and DropZone move things from one place to another with a pointer, a finger or the keyboard: a block type from a palette onto a page column, a card into a folder. A DropZone takes what it accepts and calls onDrop with the dragged data, and it can also take files dropped from the computer. To put the items of one list in a new order, use Sortable.
Playground
Change a prop on the right and the preview updates. Switch to Code to copy what you see.
Dragging items into an area
A Draggable has data (what the zone receives) and a label (its name for screen readers and the pointer). A DropZone has a label, an optional accepts function, and onDrop. While something it accepts is dragged, the zone shows its outline, and under the pointer it lights up.
<Draggable data={{ type: "heading" }} label="Heading">Heading</Draggable>
<Draggable data={{ type: "image" }} label="Image">Image</Draggable>
<DropZone
label="Main column"
accepts={(data) => typeof data === "object" && data !== null && "type" in data}
onDrop={(data) => addBlock(data as { type: string })}
>
{blocks.length ? blocks.map(renderBlock) : null}
</DropZone>Files from the computer
Give a DropZone onDropFiles and, optionally, accept, and files dragged from the desktop are handed to you (only those matching accept).
<DropZone label="Upload images" accept="image/*" onDropFiles={(files) => upload(files)} />Props
The full public API for DropZone. Every prop is stable and intentionally typed.
Data
| Prop | Type | Default | Description |
|---|---|---|---|
| data | unknown | — | Draggable. What a DropZone receives in onDrop. |
| onDrop | (data: unknown) => void | — | DropZone. Something from a Draggable was dropped here. Without it the zone takes no items. |
| onDropFiles | (files: File[]) => void | — | DropZone. Files were dropped here from the computer (only those matching accept). |
| accept | string | — | DropZone. File types for onDropFiles, like an input's accept: "image/*,.pdf". |
data
unknown
default: —
Draggable. What a DropZone receives in onDrop.
onDrop
(data: unknown) => void
default: —
DropZone. Something from a Draggable was dropped here. Without it the zone takes no items.
onDropFiles
(files: File[]) => void
default: —
DropZone. Files were dropped here from the computer (only those matching accept).
accept
string
default: —
DropZone. File types for onDropFiles, like an input's accept: "image/*,.pdf".
Content
| Prop | Type | Default | Description |
|---|---|---|---|
| label | string | — | Draggable: its name, read by screen readers and shown next to the pointer. DropZone: names the zone, read when dropping from the keyboard and shown when it is empty. |
| children | ReactNode | label | Draggable: what it looks like. DropZone: what is in the zone. |
| labels | Partial<DropZoneLabels> | English | roleDescription, hint, pickedUp, dropHere(zone), dropped, cancelled. Also set app-wide with LocaleProvider. |
label
string
default: —
Draggable: its name, read by screen readers and shown next to the pointer. DropZone: names the zone, read when dropping from the keyboard and shown when it is empty.
children
ReactNode
default: label
Draggable: what it looks like. DropZone: what is in the zone.
labels
Partial<DropZoneLabels>
default: English
roleDescription, hint, pickedUp, dropHere(zone), dropped, cancelled. Also set app-wide with LocaleProvider.
Behavior & states
| Prop | Type | Default | Description |
|---|---|---|---|
| accepts | (data: unknown) => boolean | anything | DropZone. Which dragged data it takes. Zones that take the dragged item show their outline. |
| isDisabled | boolean | false | A disabled Draggable cannot be picked up; a disabled DropZone takes nothing. |
accepts
(data: unknown) => boolean
default: anything
DropZone. Which dragged data it takes. Zones that take the dragged item show their outline.
isDisabled
boolean
default: false
A disabled Draggable cannot be picked up; a disabled DropZone takes nothing.
Accessibility
- A Draggable is a button with a draggable role description, a hidden hint linked through aria-describedby, and aria-pressed while carried from the keyboard.
- Keyboard: Space or Enter picks it up. Every zone that takes it then shows a Drop here button, so Tab reaches them in page order; Space or Enter on one drops there. Escape cancels and returns focus.
- A DropZone is a group named by its label. Pick up, drop and cancel are announced through a status region.
- A pointer drag starts after 5px; a finger holds first so the page still scrolls. Escape cancels a pointer drag.
Best practices
- Keep buttons and links out of a Draggable; the whole item is the control.
- Give every zone a clear label: it is read when someone drops from the keyboard.
- Offer a normal button for the same action (for example Add block) as well, for people who prefer it.