# Acordeón

> Secciones plegables apiladas, como los paneles de una pantalla de ajustes. Componente de Pyzed para GUIs de escritorio en Python, con ejemplos y API.

Source: https://albakore.github.io/pyzed/es/library/accordion/

:::tip[En pocas palabras]
Varias secciones apiladas; cada una se abre o se cierra al pulsar su título.
:::

Secciones plegables apiladas separadas por divisores. Las secciones son tuplas `(key, title, content)` u objetos `ui.AccordionSection` (con `icon` y un widget `end` en la cabecera). El estado abierto es tuyo: `open` es un conjunto de claves, un dict `{clave: bool}` o `True`, y `on_toggle` recibe la clave.

`ui.accordion` · Categoría: [Listas y menús](https://albakore.github.io/pyzed/es/library/#listas-y-menús) · [Referencia completa →](https://albakore.github.io/pyzed/es/reference/ui/#accordion)

**Código:**

```python
rows = lambda *items: pz.column([ui.field(k, ui.switch(v, on_toggle)) for k, v in items], spacing=8)
pz.container(ui.accordion([
    ("editor", "Editor", rows(("Soft wrap", True), ("Minimap", False))),
    ("files", "Files", rows(("Autosave", True))),
    ("git", "Git", ui.muted("Collapsed sections only show their header.")),
], open={"editor", "files"}, on_toggle=on_toggle,
   icons={"editor": "file-code", "files": "folder", "git": "git-branch"}), width=400)
```

## Cuándo usarlo

- Para paneles largos de ajustes o propiedades en los que solo hacen falta algunas secciones a la vez.
- Para un solo bloque plegable, usa un [Desplegable](https://albakore.github.io/pyzed/es/library/disclosure/).

## Uso

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

class Settings(pz.App):
    def __init__(self):
        self.open = {"editor"}

    def view(self):
        return ui.accordion(
            [("editor", "Editor", ui.muted("…")), ("files", "Files", ui.muted("…"))],
            open=self.open, on_toggle=lambda key: self.open.symmetric_difference_update({key}),
        )
```

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

### Secciones abiertas

```python
pz.container(ui.accordion([("a", "Editor", ui.muted("…")), ("b", "Files", ui.muted("…")),
                           ("c", "Git", ui.muted("…"))], open=set(), on_toggle=on_toggle), width=320)
```

```python
pz.container(ui.accordion([("a", "Editor", ui.muted("Font, wrapping, minimap.")),
                           ("b", "Files", ui.muted("…"))], open={"a"}, on_toggle=on_toggle), width=320)
```

```python
pz.container(ui.accordion([("a", "Editor", ui.muted("Font, wrapping.")),
                           ("b", "Files", ui.muted("Autosave."))], open=True, on_toggle=on_toggle), width=320)
```

### Contenido

```python
pz.container(ui.accordion([("e", "Editor", ui.muted("…")), ("g", "Git", ui.muted("…"))], open=set(),
                          icons={"e": "file-code", "g": "git-branch"}, on_toggle=on_toggle), width=320)
```

```python
pz.container(ui.accordion([ui.AccordionSection("p", "Problems", ui.muted("…"), icon="circle-x",
                                              end=ui.count_badge(3, tint="error"))],
                          open=set(), on_toggle=on_toggle), width=320)
```

## Eventos

Acordeón tiene **1 evento 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_toggle` | `(key)` | Se llama con la clave de la cabecera pulsada. |

**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 Settings(pz.App):
    def __init__(self):
        self.open = {"editor"}

    def toggle(self, key):               # on_toggle: the key of the clicked header
        self.open ^= {key}

    def view(self):
        return ui.accordion([("editor", "Editor", ui.muted("Font, tabs, wrapping")),
                             ("files", "Files", ui.muted("Autosave, encoding"))],
                            open=self.open, on_toggle=self.toggle)
```

**Declarativo:**

```python
from dataclasses import dataclass

@dataclass
class Toggle:
    key: str

class Settings(pz.App):
    open = frozenset({"editor"})

    def update(self, message):
        match message:
            case Toggle(key):
                self.open = self.open ^ {key}

    def view(self):
        return ui.accordion([("editor", "Editor", ui.muted("…")), ("files", "Files", ui.muted("…"))],
                            open=self.open, on_toggle=Toggle)
```

**Funcional:**

```python
from dataclasses import dataclass

@dataclass(frozen=True)
class State:
    open: frozenset = frozenset({"editor"})

def view(state, set_state):
    return ui.accordion([("editor", "Editor", ui.muted("…")), ("files", "Files", ui.muted("…"))],
                        open=state.open, on_toggle=lambda key: set_state(open=state.open ^ {key}))
```

## Propiedades y API

### `ui.accordion`

```python
accordion(
    sections,
    *,
    open=(),
    on_toggle=None,
    icons=None,
    spacing=8,
    padding=(6, 12, 10, 12),
    theme=None,
)
```

Secciones plegables apiladas y separadas por divisores, como los paneles de una pantalla de ajustes. Cada cabecera ocupa todo el ancho, así que el contenido queda alineado con el resto del panel. El estado abierto es tuyo: cámbialo en `on_toggle`.

| Propiedad | Por defecto | Descripción |
| --- | --- | --- |
| `sections` | *obligatorio* | Elementos `ui.AccordionSection(key, title, content, icon=None, end=None)` (o tuplas `(key, title, content)`). |
| `open` | `()` | El conjunto de ids abiertos, un dict `{id: bool}` o `True` para todos. |
| `icons` | `None` | `{id: icono}`: un icono de Lucide para cada cabecera. |
| `spacing` | `8` | Espacio alrededor de los divisores entre secciones. |
| `padding` | `(6, 12, 10, 12)` | Relleno alrededor del contenido de una sección abierta. |
| `theme` | `None` | Tema a usar en lugar del actual (`pyzed.theme.current()`). |

Eventos: `on_toggle` ([eventos](#eventos)).

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

### `ui.AccordionSection`

```python
class AccordionSection
```

Una sección de `ui.accordion`: `key`, `title`, `content` y, opcionales, `icon` y un widget `end` en la cabecera.

| Propiedad | Por defecto | Descripción |
| --- | --- | --- |
| `key` | *obligatorio* | Clave que identifica la suscripción (por defecto, el mensaje o la función). |
| `title` | *obligatorio* | Título. |
| `content` | *obligatorio* | Contenido: un `Widget`, un texto o un número (se convierte en texto). |
| `icon` | `None` | Nombre de un icono de Lucide (`pyzed icons` los lista). |
| `end` | `None` | Widgets al final (derecha). |

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

## Relacionados

- [Desplegable](https://albakore.github.io/pyzed/es/library/disclosure/): Una sección plegable con flecha.
- [Grupo de ajustes](https://albakore.github.io/pyzed/es/library/settings-group/): Un bloque con título de filas de ajustes, para pantallas de ajustes.
