# Botón dividido

> Una acción principal más una flecha que abre más opciones. Un componente nativo de Pyzed para GUIs de escritorio en Python, con vista previa, ejemplos y su API.

Source: https://albakore.github.io/pyzed/es/library/split-button/

:::tip[En pocas palabras]
Un botón con dos partes: la grande hace lo habitual y la flechita muestra otras formas de hacerlo.
:::

Un botón con un chevron separado a la derecha. `on_press` ejecuta la acción principal y `on_menu` suele abrir un `ui.menu` dentro de un `ui.popover` con las alternativas.

`ui.split_button` · Categoría: [Acciones](https://albakore.github.io/pyzed/es/library/#acciones) · [Referencia completa →](https://albakore.github.io/pyzed/es/reference/ui/#split_button)

**Código:**

```python
pz.row([
    ui.split_button("Run", on_run, on_menu, icon="play"),
    ui.split_button("Deploy", on_deploy, on_menu, variant="solid"),
], spacing=12)
```

## Cuándo usarlo

- Cuando una acción es la habitual pero hay algunas variantes (Ejecutar / Ejecutar con argumentos).
- Evítalo si las opciones son igual de importantes: usa un [Select](https://albakore.github.io/pyzed/es/library/select/).

## Uso

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

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

    def view(self):
        button = ui.split_button("Run", self.run, lambda: setattr(self, "menu_open", True), icon="play")
        menu = ui.menu([ui.MenuItem("Run with arguments…", self.run_args),
                        ui.MenuItem("Debug", self.debug, icon="bug")]) if self.menu_open else None
        return ui.popover(button, menu, y=32, on_dismiss=lambda: setattr(self, "menu_open", False))
```

## Variantes

:::note[Sobre estas capturas]
Cada captura la graba pyzed mismo, fuera de pantalla a 2x, en One Dark o One Light según el tema de este sitio, y recortada al componente para que se vea a su tamaño real. El puntero pasa por encima, pulsa o escribe en él; un componente que no reacciona al puntero recorre algunos temas. Con movimiento reducido ves el primer fotograma. Abre **Código** bajo una captura para ver el fragmento que la dibuja; los nombres libres como `on_save` son tus propios callbacks.
:::

### Variante

```python
ui.split_button("Run", on_run, on_menu, icon="play")
```

```python
ui.split_button("Run", on_run, on_menu, icon="play", variant="ghost")
```

```python
ui.split_button("Run", on_run, on_menu, icon="play", variant="outline")
```

```python
ui.split_button("Deploy", on_deploy, on_menu, icon="rocket", variant="solid")
```

### Tamaño

```python
ui.split_button("Build", on_build, on_menu, size="sm")
```

```python
ui.split_button("Build", on_build, on_menu, size="md")
```

```python
ui.split_button("Build", on_build, on_menu, size="lg")
```

### Contenido

```python
ui.split_button("Merge", on_merge, on_menu)
```

```python
ui.split_button("Merge", on_merge, on_menu, icon="git-merge")
```

### Estados y eventos

```python
ui.split_button("Deploy", on_press, on_menu, tint="success")
```

```python
ui.split_button("Run", on_press, on_menu, disabled=True)
```

## Eventos

Botón dividido tiene **2 eventos propios**, en la tabla de abajo. Como todo widget, también tiene los **18 eventos comunes** (`click`, `double_click`, `right_click`, `mouse_enter`, `drag`, `key_down`, `resize`…), que se conectan con `.on(...)`: mira [Eventos](https://albakore.github.io/pyzed/es/guides/events/) y [Eventos de cada componente](https://albakore.github.io/pyzed/es/library/events/).

| Evento | El handler recibe | Cuándo |
| --- | --- | --- |
| `on_press` | `()` | Mensaje o callable que se envía al pulsar. `None` deshabilita el control. |
| `on_menu` | `()` | Mensaje o callable del botón del menú. |

**El handler recibe** es lo que Pyzed le pasa a tu función: `()` es nada. Cualquier handler también puede ser un mensaje (un valor que no se puede llamar), que va a `update()`.

### Manejar los eventos

Los mismos eventos escritos de tres formas. **Imperativa**: métodos de la app que cambian `self`. **Declarativa**: los handlers producen mensajes y un único `update()` decide. **Funcional**: una función pura dibuja un estado inmutable y pide cambios con `set_state(...)`. Mira [Imperativo, declarativo y funcional](https://albakore.github.io/pyzed/es/guides/code-styles/).

**Imperativo:**

```python
class Runner(pz.App):
    def __init__(self):
        self.menu_open = False
        self.last = "nothing yet"

    def run(self, how="run"):
        self.last, self.menu_open = how, False

    def view(self):
        button = ui.split_button("Run", self.run,                     # on_press: the main action
                                 lambda: setattr(self, "menu_open", True),   # on_menu: the arrow
                                 icon="play")
        menu = ui.menu([ui.MenuItem("Debug", lambda: self.run("debug"), icon="bug")])
        return pz.column([
            ui.popover(button, menu if self.menu_open else None, y=32,
                       on_dismiss=lambda: setattr(self, "menu_open", False)),
            ui.label(f"Last: {self.last}"),
        ], spacing=8)
```

**Declarativo:**

```python
from dataclasses import dataclass

@dataclass
class Run:
    how: str = "run"

class Runner(pz.App):
    menu_open = False
    last = "nothing yet"

    def update(self, message):
        match message:
            case Run(how):
                self.last, self.menu_open = how, False
            case "menu":
                self.menu_open = True
            case "dismiss":
                self.menu_open = False

    def view(self):
        menu = ui.menu([ui.MenuItem("Debug", Run("debug"), icon="bug")])
        return ui.popover(ui.split_button("Run", Run(), "menu", icon="play"),
                          menu if self.menu_open else None, y=32, on_dismiss="dismiss")
```

**Funcional:**

```python
from dataclasses import dataclass

@dataclass(frozen=True)
class State:
    menu_open: bool = False
    last: str = "nothing yet"

def view(state, set_state):
    run = lambda how: set_state(last=how, menu_open=False)
    menu = ui.menu([ui.MenuItem("Debug", lambda: run("debug"), icon="bug")])
    return ui.popover(
        ui.split_button("Run", lambda: run("run"), lambda: set_state(menu_open=True), icon="play"),
        menu if state.menu_open else None, y=32, on_dismiss=lambda: set_state(menu_open=False))
```

## Propiedades y API

### `ui.split_button`

```python
split_button(
    content,
    on_press=None,
    on_menu=None,
    *,
    icon=None,
    variant='filled',
    tint=None,
    size='md',
    disabled=False,
    tooltip=None,
    theme=None,
)
```

Un botón con una flecha aparte para más opciones. `on_press` ejecuta la acción principal y `on_menu` normalmente abre un `ui.menu` en un `ui.popover`.

| Propiedad | Por defecto | Descripción |
| --- | --- | --- |
| `content` | *obligatorio* | Texto del botón. |
| `icon` | `None` | Nombre de un icono de Lucide (`pyzed icons` los lista). |
| `variant` | `"filled"` | Como en `ui.button`. |
| `tint` | `None` | Como en `ui.button`. |
| `size` | `"md"` | `"xs"`, `"sm"`, `"md"` o `"lg"`. |
| `disabled` | `False` | Desactiva las dos mitades. |
| `tooltip` | `None` | Tooltip de la mitad principal. |
| `theme` | `None` | Tema a usar en lugar del actual (`pyzed.theme.current()`). |

Eventos: `on_press`, `on_menu` ([eventos](#eventos)).

[Referencia completa →](https://albakore.github.io/pyzed/es/reference/ui/#split_button)

## Relacionados

- [Botón](https://albakore.github.io/pyzed/es/library/button/): El botón con tema: variantes, tamaños, iconos y atajos.
- [Menú](https://albakore.github.io/pyzed/es/library/menu/): Un menú contextual con iconos, atajos y marcas.
- [Popover](https://albakore.github.io/pyzed/es/library/popover/): Contenido flotante en un punto: menús contextuales, selectores de color.
