# Select

> A dropdown to choose one option. A native Pyzed component for Python desktop GUIs, with a live preview, code examples and its API.

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

:::tip[In plain words]
A box that opens a list so you can pick one option from it.
:::

A dropdown in the theme style. Options are shown with `str()`, so strings, enums or dataclasses all work, and `on_select` receives the chosen object.

`ui.select` · Category: [Forms](https://albakore.github.io/pyzed/library/#forms) · [Full reference →](https://albakore.github.io/pyzed/reference/ui/#select)

**Code:**

```python
pz.row([
    ui.select(["Python", "Rust", "TypeScript"], "Rust", on_select, width=180),
    ui.select(["UTF-8", "Latin-1"], None, on_select, placeholder="Encoding…", width=180),
], spacing=12)
```

## When to use

- To pick one of many options when there is no room to show them all (language, theme, encoding).
- With two to five short options, [Segmented](https://albakore.github.io/pyzed/library/segmented/) or a [Radio group](https://albakore.github.io/pyzed/library/radio-group/) shows them at a glance.

## Usage

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

class Settings(pz.App):
    def __init__(self):
        self.language = "Python"

    def view(self):
        return ui.select(["Python", "Rust", "TypeScript"], self.language,
                         lambda value: setattr(self, "language", value), width=180)
```

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

### State

```python
ui.select(["Python", "Rust", "TypeScript"], "Rust", on_select, width=200)
```

```python
ui.select(["UTF-8", "Latin-1"], None, on_select, placeholder="Encoding…", width=200)
```

```python
ui.select(["One Dark"], "One Dark", width=200)
```

### Size

```python
ui.select(["Python", "Rust"], "Python", on_select, size="sm", width=200)
```

```python
ui.select(["Python", "Rust"], "Python", on_select, size="md", width=200)
```

```python
ui.select(["Python", "Rust"], "Python", on_select, size="lg", width=200)
```

### States and events

`on_open` and `on_close` run when the menu opens and closes.

```python
ui.select(["One Dark"], "One Dark", on_select, disabled=True, width=200)
```

```python
ui.select(["UTF-8", "Latin-1"], None, on_select, placeholder="Encoding…", invalid=True, width=200)
```

### Base widget

The `pz.*` widget underneath: no theme, every color and size is yours.

```python
pz.pick_list(["Small", "Medium", "Large"], "Medium", on_select, width=200,
             bg="#2b2140", color="#e9d5ff", border_color="#c678dd", radius=8)
```

## Events

Select has **3 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/).

| Event | Of | Handler gets | When |
| --- | --- | --- | --- |
| `on_select` | `ui.select`, `pz.pick_list` | `(item)` | Callable that receives the chosen item. |
| `on_open` | `ui.select`, `pz.pick_list` | `()` | Sent when the menu opens. |
| `on_close` | `ui.select`, `pz.pick_list` | `()` | Sent when the menu closes. |

**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 Settings(pz.App):
    def __init__(self):
        self.language = "Python"
        self.open = False

    def view(self):
        return pz.column([
            ui.select(["Python", "Rust", "TypeScript"], self.language,
                      lambda value: setattr(self, "language", value),       # on_select: the option
                      on_open=lambda: setattr(self, "open", True),
                      on_close=lambda: setattr(self, "open", False), width=180),
            ui.muted("Choosing…" if self.open else f"Language: {self.language}"),
        ], spacing=8)
```

**Declarative:**

```python
from dataclasses import dataclass

@dataclass
class Language:
    name: str

class Settings(pz.App):
    language = "Python"

    def update(self, message):
        match message:
            case Language(name):
                self.language = name

    def view(self):
        return ui.select(["Python", "Rust", "TypeScript"], self.language, Language, width=180)
```

**Functional:**

```python
from dataclasses import dataclass

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

def view(state, set_state):
    return ui.select(["Python", "Rust", "TypeScript"], state.language,
                     lambda value: set_state(language=value), width=180)
```

## Tips

:::tip
It takes the keyboard focus like a text field (a click or Tab) and keeps it after you pick an option: then ↓/↑ choose the next or previous option without opening the menu, Home/End the first and last, and typing jumps to the option that starts with those letters. Enter, Space, Alt+↓ or F4 open the menu; there ↑/↓ move, Enter picks and Esc closes. Pass `id=` to focus it with `pz.Command.focus(id)`.
:::

## Properties and API

### `ui.select`

```python
select(
    options,
    selected=None,
    on_select=None,
    *,
    placeholder='Select…',
    width=None,
    size='md',
    disabled=False,
    invalid=False,
    on_open=None,
    on_close=None,
    id=None,
    theme=None,
)
```

A dropdown with the theme style. Options are displayed with `str()`, so strings, enums, dataclasses or database models all work; `on_select` receives the chosen object, not its label.

| Property | Default | Description |
| --- | --- | --- |
| `options` | *required* | List of options. |
| `selected` | `None` | Current option. |
| `placeholder` | `"Select…"` | Hint text shown when empty. |
| `width` | `None` | Width: pixels, `"fill"`, `"shrink"` or `"fill:N"` (proportion). |
| `size` | `"md"` | `"sm"`, `"md"` or `"lg"`. |
| `disabled` | `False` | Greys it out. |
| `invalid` | `False` | Paints the border in the error color. |
| `id` | `None` | Stable identifier used to focus or scroll it with a `Command`. |
| `theme` | `None` | Theme to use instead of the current one (`pyzed.theme.current()`). |

Events: `on_select`, `on_open`, `on_close` ([events](#events)).

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

### `pz.pick_list`

```python
pick_list(
    options,
    selected=None,
    on_select=None,
    *,
    on_open=None,
    on_close=None,
    placeholder=None,
    width=None,
    padding=None,
    text_size=None,
    font=None,
    handle=None,
    handle_size=12.0,
    menu_height=None,
    bg=None,
    color=None,
    placeholder_color=None,
    handle_color=None,
    border_color=None,
    hover_border_color=None,
    radius=None,
    menu_bg=None,
    menu_color=None,
    menu_border_color=None,
    selected_bg=None,
    selected_color=None,
    focus_border_color=None,
    id=None,
)
```

A dropdown to choose one of `options`. `on_select(option)` receives the chosen one. For the themed dropdown use `ui.select`. It takes the keyboard focus like a text field (a click, Tab or `Command.focus(id)`) and keeps it after a choice: ↑/↓ then pick the previous or next option without opening it, Home/End the first and last and typing jumps to an option; Enter, Space, Alt+↓ or F4 open the menu, where ↑/↓ move, Enter picks and Esc closes.

| Property | Default | Description |
| --- | --- | --- |
| `options` | *required* | List of options. |
| `selected` | `None` | Current option. |
| `placeholder` | `None` | Hint text shown when empty. |
| `width` | `None` | Width: pixels, `"fill"`, `"shrink"` or `"fill:N"` (proportion). |
| `padding` | `None` | Inner padding: `8`, `(vertical, horizontal)` or `(top, right, bottom, left)`. |
| `text_size` | `None` | Text size. |
| `font` | `None` | Font family. |
| `handle` | `None` | Arrow icon character. |
| `handle_size` | `12.0` | Arrow size. |
| `menu_height` | `None` | Maximum menu height. |
| `bg` | `None` | Background color (`"#rrggbb[aa]"`, `(r, g, b[, a])` or `"transparent"`). |
| `color` | `None` | Text or icon color. |
| `placeholder_color` | `None` | Placeholder color. |
| `handle_color` | `None` | Arrow color. |
| `border_color` | `None` | Border color. |
| `hover_border_color` | `None` | Border color on hover. |
| `radius` | `None` | Corner radius: a number or `(top_left, top_right, bottom_right, bottom_left)`. |
| `menu_bg` | `None` | Menu background. |
| `menu_color` | `None` | Menu text. |
| `menu_border_color` | `None` | Menu border. |
| `selected_bg` | `None` | Background of the highlighted option. |
| `selected_color` | `None` | Text of the highlighted option. |
| `focus_border_color` | `None` | Border color while it has the keyboard focus. |
| `id` | `None` | Stable identifier used to focus or scroll it with a `Command`. |

Events: `on_select`, `on_open`, `on_close` ([events](#events)).

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

## Related

- [Segmented](https://albakore.github.io/pyzed/library/segmented/): A group of mutually exclusive text buttons.
- [Radio group](https://albakore.github.io/pyzed/library/radio-group/): Mutually exclusive options as radio buttons.
- [Picker](https://albakore.github.io/pyzed/library/picker/): A searchable list on a floating surface, with fuzzy matching.
