Skip to content

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.

Layout & Display9 propsAccessibility notes

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

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

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

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.