# Layer

> Draws an overlay over your view; clicking outside dismisses it. A Pyzed component for Python desktop GUIs, with examples and its API.

Source: https://albakore.github.io/pyzed/library/layer/

:::tip[In plain words]
Puts something on top of the screen, like a search box, and closes it if you click outside.
:::

Stacks `overlay` on top of `base`. Clicking outside the overlay sends `on_dismiss`, and `backdrop` dims the view behind it. With `overlay=None` it returns `base` unchanged, so it can always wrap your view. `align_x`, `align_y` and `offset` place the overlay (by default centered at the top, like a command palette).

`ui.layer` · Category: [Overlays](https://albakore.github.io/pyzed/library/#overlays) · [Full reference →](https://albakore.github.io/pyzed/reference/ui/#layer)

**Code:**

```python
ui.layer(
    main_view(),
    ui.picker("", on_query, [(ui.PaletteItem("notes.py", on_open, icon="file-code"), []),
                             (ui.PaletteItem("README.md", on_open, icon="file-text"), [])],
              placeholder="Search files…", width=420),
    on_dismiss=on_close, backdrop="#00000055", offset=40,
)
```

## When to use

- To show palettes, pickers, modals and menus above everything else.
- For dialogs, [Dialog layer](https://albakore.github.io/pyzed/library/dialog-layer/) already centers them over a dimmed backdrop.

## Usage

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

class App(pz.App):
    def __init__(self):
        self.finder_open = False

    def view(self):
        overlay = self.finder() if self.finder_open else None
        return ui.layer(self.main_view(), overlay,
                        on_dismiss=lambda: setattr(self, "finder_open", False))
```

## 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.
:::

### Placement

```python
ui.layer(main_view(), ui.card(ui.label("Overlay"), width=200), on_dismiss=on_close)
```

```python
ui.layer(main_view(), ui.card(ui.label("Overlay"), width=200), align_y="center",
         on_dismiss=on_close)
```

```python
ui.layer(main_view(), ui.card(ui.label("Overlay"), width=200), align_x="end", align_y="end",
         offset=16, on_dismiss=on_close)
```

### Backdrop

With `overlay=None` the layer returns your view unchanged.

```python
ui.layer(main_view(), ui.card(ui.label("Overlay"), width=200), backdrop="#00000088",
         align_y="center", on_dismiss=on_close)
```

```python
ui.layer(main_view(), None)
```

## Events

Layer has **1 event 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/).

| Event | Handler gets | When |
| --- | --- | --- |
| `on_dismiss` | `()` | Message or callable sent on close. |

**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 App(pz.App):
    def __init__(self):
        self.finder_open = True

    def view(self):
        finder = ui.card(ui.muted("Search files…"), width=320)
        return ui.layer(main_view(), finder if self.finder_open else None,
                        on_dismiss=lambda: setattr(self, "finder_open", False))   # click outside
```

**Declarative:**

```python
class App(pz.App):
    finder_open = True

    def update(self, message):
        match message:
            case "open finder":
                self.finder_open = True
            case "close finder":
                self.finder_open = False

    def view(self):
        overlay = ui.card(ui.muted("Search files…"), width=320) if self.finder_open else None
        return ui.layer(main_view(), overlay, on_dismiss="close finder")
```

**Functional:**

```python
from dataclasses import dataclass

@dataclass(frozen=True)
class State:
    finder_open: bool = True

def view(state, set_state):
    overlay = ui.card(ui.muted("Search files…"), width=320) if state.finder_open else None
    return ui.layer(main_view(), overlay, on_dismiss=lambda: set_state(finder_open=False))
```

## Properties and API

### `ui.layer`

```python
layer(
    base,
    overlay=None,
    *,
    on_dismiss=None,
    backdrop=None,
    align_x='center',
    align_y='start',
    offset=72,
)
```

Stacks `overlay` on top of `base`. Clicking outside sends `on_dismiss`. With `overlay=None` it returns `base` unchanged.

| Property | Default | Description |
| --- | --- | --- |
| `base` | *required* | The UI underneath. |
| `overlay` | `None` | What floats on top (modal, palette, menu). |
| `backdrop` | `None` | Color of the backdrop that dims the UI. |
| `align_x` | `"center"` | Horizontal alignment: `"start"`/`"left"`, `"center"`, `"end"`/`"right"`. |
| `align_y` | `"start"` | Vertical alignment: `"start"`/`"top"`, `"center"`, `"end"`/`"bottom"`. |
| `offset` | `72` | Distance from the top when `align_y` is `"start"`. |

Events: `on_dismiss` ([events](#events)).

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

## Related

- [Modal](https://albakore.github.io/pyzed/library/modal/): A dialog surface with title, content and footer buttons.
- [Popover](https://albakore.github.io/pyzed/library/popover/): Floating content at a point: context menus, color pickers.
- [Dialog layer](https://albakore.github.io/pyzed/library/dialog-layer/): Centers a dialog over your view with a dimmed backdrop.
