# Drop zone

> An area that takes files dragged from the desktop or the file manager. A Pyzed component for Python desktop GUIs, with examples and its API.

Source: https://albakore.github.io/pyzed/library/drop-zone/

:::tip[In plain words]
A dashed area where you drag files from your desktop and let go to add them.
:::

`ui.DropZone` lights up when files are dragged over the window and receives them when they are dropped: `on_drop` gets each path and `on_files` the whole list. `accept` limits the types (`["png", "jpg"]`, `["*.tar.gz"]`, `["folder"]`) and files of other types go to `on_reject`. With `browse=True` (the default) a click opens the file dialog too. When a window has several zones, the one under the pointer gets the files, or else the one that accepts their type.

`ui.DropZone` · Category: [System](https://albakore.github.io/pyzed/library/#system) · [Full reference →](https://albakore.github.io/pyzed/reference/ui/#dropzone)

**Code:**

```python
pz.row([
    ui.DropZone(text="Drop images here", hint="PNG or JPG, up to 10 MB", accept=["png", "jpg"],
                on_files=on_files),
    ui.DropZone(icon_name="file-spreadsheet", text="Import a CSV", accept=["csv"], multiple=False,
                show_files=True, files=["~/data/sales-2026.csv"], on_files=on_files),
], spacing=16, width=600)
```

:::note[New]
This component was added recently. Tell us how it works for you in the [issue tracker](https://github.com/albakore/pyzed/issues).
:::

## When to use

- For importing images, documents or data files, and attaching files to a message.
- `show_files=True` lists what was dropped, with a button to remove each one; `multiple=False` keeps only the last file.
- Dropped files also reach `on_file_drop(path)` of the window, for apps that don't need a zone.

## Usage

```python
import pyzed as pz
from pyzed import ui

class Gallery(pz.App):
    def __init__(self):
        self.images = []

    def view(self):
        return pz.column([
            ui.DropZone(text="Drop photos", accept=["png", "jpg", "webp"],
                        on_files=lambda e: setattr(self, "images", list(e.value))),
            pz.row([pz.image(path, width=96, height=96) for path in self.images], spacing=8),
        ], spacing=12)
```

## Variants

:::note[About these captures]
Each capture is recorded by pyzed itself, off-screen at 2x, in One Dark or One Light to match this site's theme, and cropped to the component so it shows at its real size. The pointer hovers, presses or types into it; a component that does not react to the pointer cycles through a few themes. With reduced motion you see the first frame. Open **Code** under a capture to see the snippet that draws it; free names such as `on_save` stand for your own callbacks.
:::

### States

```python
ui.DropZone(text="Drop files here", on_files=on_files)
```

```python
ui.DropZone(text="Drop files here", on_files=on_files)
```

```python
ui.DropZone(text="Drop images here", accept=["png", "jpg"], on_files=on_files)
```

```python
ui.DropZone(text="Drop files here", disabled=True, on_files=on_files)
```

### Files

```python
ui.DropZone(text="Attach files", show_files=True, files=["~/docs/brief.pdf", "~/img/cover.png"], on_files=on_files)
```

```python
ui.DropZone(icon_name="image", text="Drag a picture", hint="Only by dragging", browse=False, on_files=on_files)
```

## Events

Drop zone has **5 events of its own**, listed below. Like every widget it also has the **18 common events** (`click`, `double_click`, `right_click`, `mouse_enter`, `drag`, `key_down`, `resize`…), attached with `.on(...)`: see [Events](https://albakore.github.io/pyzed/guides/events/) and [Events of every component](https://albakore.github.io/pyzed/library/events/).

It is a `pz.Component`, so it also raises `on_mount` and `on_unmount`, and its handlers get a `pz.Event` whose `value` holds the data.

| Event | Handler gets | When |
| --- | --- | --- |
| `on_drop` | `(event)` | Receives `event.value`: one dropped path (once per file). |
| `on_files` | `(event)` | Receives `event.value`: the list of files. |
| `on_reject` | `(event)` | Receives a path it does not accept. |
| `on_enter` | `(event)` | Files are dragged over the window. |
| `on_leave` | `(event)` | The drag left without dropping. |

**Handler gets** is what Pyzed passes to your callable: `()` means nothing. Any handler can also be a message (a value that is not callable), which goes to `update()`.

### Handling the events

The same events written three ways. **Imperative**: methods of the app change `self`. **Declarative**: the handlers produce messages and one `update()` decides. **Functional**: a pure function draws an immutable state and asks for changes with `set_state(...)`. See [Imperative, declarative and functional](https://albakore.github.io/pyzed/guides/code-styles/).

**Imperative:**

```python
class Attach(pz.App):
    def __init__(self):
        self.files = []

    def received(self, event):           # on_files: event.value is every file so far
        self.files = list(event.value)

    def view(self):
        return pz.column([
            ui.DropZone(text="Drop files to attach", on_files=self.received),
            ui.label(f"{len(self.files)} files"),
        ], spacing=8, width=320)
```

**Declarative:**

```python
from dataclasses import dataclass

@dataclass
class Dropped:
    path: str

class Attach(pz.App):
    files = ()

    def update(self, message):
        match message:
            case Dropped(path):
                self.files = (*self.files, path)

    def view(self):
        # on_drop runs once per file
        return ui.DropZone(accept=["png", "jpg"], on_drop=lambda e: Dropped(e.value))
```

**Functional:**

```python
from dataclasses import dataclass

@dataclass(frozen=True)
class State:
    rejected: str = ""

def view(state, set_state):
    return pz.column([
        ui.DropZone(text="Drop a CSV", accept=["csv"], multiple=False,
                    on_reject=lambda e: set_state(rejected=e.value)),
        ui.label(f"Not a CSV: {state.rejected}" if state.rejected else ""),
    ], spacing=8, width=320)
```

## Tips

:::tip
Pyzed Design has a Drop zone in the System section of the toolbox, next to the non-visual helpers of the operating system (system information, launcher, network and battery monitors).
:::

## Properties and API

### `ui.DropZone`

```python
class DropZone
```

A component that takes files dragged from the system's file manager and dropped on the window, and opens the file dialog on a click. It lights up while files are dragged over the window and keeps the dropped paths in `files`. The window's `on_file_drop` hook hands each file to the zone under the pointer, else to one whose `accept` lists its type. See the [Drop zone](https://albakore.github.io/pyzed/library/drop-zone/) page.

| Property | Default | Description |
| --- | --- | --- |
| `text` | `""` | The main text (default: Drop files here). |
| `hint` | `""` | The line under it. |
| `icon_name` | `"upload"` | Its icon. |
| `accept` | `()` | Extensions (`["png", "jpg"]`), patterns (`"*.tar.gz"`) or `"folder"`; empty takes everything. |
| `multiple` | `True` | `False` keeps only the last file. |
| `browse` | `True` | A click opens the file dialog. |
| `show_files` | `False` | Lists the files under the text (each with an x). |
| `files` | `()` | The dropped paths. |
| `disabled` | `False` | Takes nothing. |
| `live` | `True` | `False` draws it without taking files (the designer's canvas). |

Events: `on_drop`, `on_files`, `on_reject`, `on_enter`, `on_leave` ([events](#events)).

[Full reference →](https://albakore.github.io/pyzed/reference/ui/#dropzone)

## Related

- [File picker](https://albakore.github.io/pyzed/library/file-input/): A path field with a button that opens the system's file or folder dialog.
- [Card](https://albakore.github.io/pyzed/library/card/): A bordered surface with an optional title and actions.
