1# llimphi-widget-select23*Read this in English: [README.md](README.md).*
45Control *select* / dropdown moderno.
67Modelado como un **gradiente de complejidad**: la misma pieza sirve
8desde el select más tonto hasta uno con carga asíncrona y badges, sin
9cambiar de widget — sólo se van encendiendo capas.
10```text11 ┌──────────────────────────────┐
12 │ ◷ Pendiente ● ▾ │ ← disparador (cerrado)
13 └──────────────────────────────┘
14 │ click → view_overlay
15 ▼
16 ┃ ⌕ Buscar… ← caja de búsqueda (capa 2)
17 ┃ ✓ ◷ Pendiente 12 ← ítem rico: check · icono · label · badge (capa 3)
18 ┃ ◔ En curso 3
19 ┃ ◉ Hecho · ← badge dot
20 ┃ ─────────────────────
21 ┃ ⟳ Cargando… ← estado async (capa 4): Loading / Error+reintento / vacío
22```23## Las cuatro capas24251. **Select simple.** `SelectItem::new` + `select_trigger_view` (el
26 botón cerrado que muestra lo elegido) + `select_menu_view` con
27 `SelectPhase::Ready` montado en `App::view_overlay`. `on_pick(idx)`
28 devuelve el índice **original** del ítem elegido; la app lo guarda y
29 cierra el menú. Eso es todo.
302. **Buscable (combobox).** Pon `searchable: true`. La caja de arriba
31 pinta `query`; el tecleo lo rutea la app por `on_key` a un
32 `TextInputState` y re-filtra con `filter`. `step_active` mueve el
33 resaltado con ↑/↓ saltando deshabilitados; `resolve` traduce la
34 posición resaltada al índice original para Enter.
353. **Ítems ricos + badges.** Cada `SelectItem` lleva `icon`, `sublabel`
36 y un `SelectBadge` (conteo `12`, chip de texto `beta`, o dot de
37 estado) — reusa `llimphi-widget-badge`. La selección múltiple sale
38 sola: pasa varios índices en `selected` y el menú pinta el check ✓ en
39 cada uno (la semántica toggle/cerrar la decide la app).
404. **Carga asíncrona.** El menú no exige tener los datos: `SelectPhase`
41 distingue `Loading` (fila "Cargando…"), `Error` (mensaje + acción
42 `on_retry`) y `Ready`. El patrón: la app abre el menú, lanza
43 `Handle::spawn`, pinta `Loading`, y al volver el worker cambia a
44 `Ready`. Una *generación* (`u64`) descarta respuestas viejas si el
45 usuario reabrió/retecleó — ver el ejemplo `select_demo`.
4647El look es el de `context-menu`: panel redondeado con borde hairline,
48filas como píldoras con hover suave, indicador accent en la fila activa,
49scrim full-screen que dismissa al click-fuera.
5051---
5253Parte de **llimphi** — ver [llimphi](../../LEEME.md).
Modelado como un gradiente de complejidad: la misma pieza sirve
desde el select más tonto hasta uno con carga asíncrona y badges, sin
cambiar de widget — sólo se van encendiendo capas.
Select simple.SelectItem::new + select_trigger_view (el
botón cerrado que muestra lo elegido) + select_menu_view con
SelectPhase::Ready montado en App::view_overlay. on_pick(idx)
devuelve el índice original del ítem elegido; la app lo guarda y
cierra el menú. Eso es todo.
Buscable (combobox). Pon searchable: true. La caja de arriba
pinta query; el tecleo lo rutea la app por on_key a un
TextInputState y re-filtra con filter. step_active mueve el
resaltado con ↑/↓ saltando deshabilitados; resolve traduce la
posición resaltada al índice original para Enter.
Ítems ricos + badges. Cada SelectItem lleva icon, sublabel
y un SelectBadge (conteo 12, chip de texto beta, o dot de
estado) — reusa llimphi-widget-badge. La selección múltiple sale
sola: pasa varios índices en selected y el menú pinta el check ✓ en
cada uno (la semántica toggle/cerrar la decide la app).
Carga asíncrona. El menú no exige tener los datos: SelectPhase
distingue Loading (fila "Cargando…"), Error (mensaje + acción
on_retry) y Ready. El patrón: la app abre el menú, lanza
Handle::spawn, pinta Loading, y al volver el worker cambia a
Ready. Una generación (u64) descarta respuestas viejas si el
usuario reabrió/retecleó — ver el ejemplo select_demo.
El look es el de context-menu: panel redondeado con borde hairline,
filas como píldoras con hover suave, indicador accent en la fila activa,
scrim full-screen que dismissa al click-fuera.