# Dialog layer

> Centers a dialog over your view with a dimmed backdrop. A native Pyzed component for Python desktop GUIs, with a live preview, code examples and its API.

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

:::tip[In plain words]
Darkens the app and shows a dialog in the middle, so the question can't be missed.
:::

Shows a dialog centered over `base` with a dimmed backdrop; clicking the backdrop calls `on_dismiss`. With `dialog=None` it returns `base` unchanged, so keep which dialog is open in your state and always wrap the view with it.

`ui.dialog_layer` · Category: [Dialogs](https://albakore.github.io/pyzed/library/#dialogs) · [Full reference →](https://albakore.github.io/pyzed/reference/ui/#dialog_layer)

**Code:**

```python
ui.dialog_layer(
    main_view(),
    ui.confirm("Delete notes.py? This can't be undone.", on_delete, on_cancel,
               title="Delete file", danger=True, width=340),
    on_dismiss=on_cancel,
)
```

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

- Around your whole view, to show any of the dialogs on this page or a `ui.modal`.

## Usage

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

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

    def close(self):
        self.asking = False

    def view(self):
        dialog = None
        if self.asking:
            dialog = ui.confirm("Delete main.py?", self.delete, self.close, title="Delete file", danger=True)
        return ui.dialog_layer(self.main_view(), dialog, on_dismiss=self.close)
```

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

### Dialog

```python
ui.dialog_layer(main_view(), ui.alert("Export finished.", on_close, kind="success", width=280))
```

```python
ui.dialog_layer(main_view(), ui.modal(ui.muted("Any content."), title="Modal", on_close=on_close,
                                       width=280), on_dismiss=on_close)
```

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

## Events

Dialog 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` | `()` | Sent when the backdrop is clicked. |

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

    def close(self):
        self.asking = False

    def view(self):
        dialog = ui.confirm("Delete main.py?", self.close, self.close, danger=True) if self.asking else None
        return ui.dialog_layer(main_view(), dialog, on_dismiss=self.close)   # click on the backdrop
```

**Declarative:**

```python
class Files(pz.App):
    asking = True

    def update(self, message):
        if message in ("delete", "cancel"):
            self.asking = False

    def view(self):
        dialog = ui.confirm("Delete main.py?", "delete", "cancel", danger=True) if self.asking else None
        return ui.dialog_layer(main_view(), dialog, on_dismiss="cancel")
```

**Functional:**

```python
from dataclasses import dataclass

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

def view(state, set_state):
    close = lambda: set_state(asking=False)
    dialog = ui.confirm("Delete main.py?", close, close, danger=True) if state.asking else None
    return ui.dialog_layer(main_view(), dialog, on_dismiss=close)
```

## Tips

:::tip
Button labels (OK, Cancel, Save…) are translated with [`pyzed.i18n`](https://albakore.github.io/pyzed/guides/i18n/).
:::

## Properties and API

### `ui.dialog_layer`

```python
dialog_layer(base, dialog=None, *, on_dismiss=None, theme=None)
```

Shows a dialog centered over `base` with a dimmed backdrop. With `dialog=None` it returns `base` unchanged, so it can always wrap the view. See [Dialogs](https://albakore.github.io/pyzed/guides/i18n/#dialogs).

| Property | Default | Description |
| --- | --- | --- |
| `base` | *required* | The UI underneath. |
| `dialog` | `None` | A dialog from the functions below, or `ui.modal`. |
| `theme` | `None` | Theme to use instead of the current one (`pyzed.theme.current()`). |

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

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

## Related

- [Alert](https://albakore.github.io/pyzed/library/alert/): A message with one button.
- [Confirm](https://albakore.github.io/pyzed/library/confirm/): A yes/no question, red for destructive actions.
- [Prompt](https://albakore.github.io/pyzed/library/prompt/): Asks for a line of text.
- [Modal](https://albakore.github.io/pyzed/library/modal/): A dialog surface with title, content and footer buttons.
