# Combobox

> Picker con búsqueda: el valor tiene que ser uno de la lista. Simple, múltiple con chips y async.

```tsx
import { Combobox, ComboboxChip, ComboboxChips, ComboboxChipsInput, … } from "sebs7n-ui/combobox"
```

## Ejemplos

### Elegir uno

El valor tiene que ser uno de la lista: escribir filtra, no crea.

```tsx
import { Combobox, ComboboxContent, ComboboxEmpty, ComboboxInput, ComboboxItem, ComboboxList } from "sebs7n-ui/combobox"
import { Label } from "sebs7n-ui/label"
import { useState } from "react"

function Basico() {
  const [pais, setPais] = useState<string | null>(null)
  return (
    <div className="flex w-full max-w-sm flex-col gap-2">
      <Label htmlFor="pais">País</Label>
      <Combobox items={PAISES} onValueChange={setPais} value={pais}>
        <ComboboxInput id="pais" placeholder="Elegí un país" />
        <ComboboxContent>
          <ComboboxEmpty />
          <ComboboxList>{(item: string) => <ComboboxItem key={item} value={item}>{item}</ComboboxItem>}</ComboboxList>
        </ComboboxContent>
      </Combobox>
    </div>
  )
}
```

### Varios, con chips

`multiple` y `ComboboxChips` en vez de `ComboboxInput`. Backspace con el input vacío borra el último.

```tsx
import { Combobox, ComboboxChip, ComboboxChips, ComboboxChipsInput, ComboboxContent, ComboboxEmpty, ComboboxItem, ComboboxList, ComboboxValue } from "sebs7n-ui/combobox"
import { Label } from "sebs7n-ui/label"

function Multiple() {
  return (
    <div className="flex w-full max-w-sm flex-col gap-2">
      <Label htmlFor="paises">Países donde operás</Label>
      <Combobox items={PAISES} multiple>
        <ComboboxChips>
          <ComboboxValue>
            {(values: string[]) => (
              <>
                {values.map((value) => (
                  <ComboboxChip key={value}>{value}</ComboboxChip>
                ))}
                <ComboboxChipsInput id="paises" />
              </>
            )}
          </ComboboxValue>
        </ComboboxChips>
        <ComboboxContent>
          <ComboboxEmpty />
          <ComboboxList>{(item: string) => <ComboboxItem key={item} value={item}>{item}</ComboboxItem>}</ComboboxList>
        </ComboboxContent>
      </Combobox>
    </div>
  )
}
```

## Props

### Combobox

Hereda las props de `Combobox.Root`.

Sin props propias: pasa todo al primitivo.

### ComboboxChip

Hereda las props de `Combobox.Chip`.

| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
| `removeLabel` | `string` | `"Quitar"` | Prefijo del nombre del botón de quitar: "Quitar Chile". |
| `textValue` | `string` | — | Texto para el nombre accesible cuando children no es texto. |
| `className` | `string` | — | — |

### ComboboxChips

Hereda las props de `Combobox.Chips`.

| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
| `disabled` | `boolean` | — | — |
| `labels` | `{ clear?: string; trigger?: string }` | — | — |
| `showClear` | `boolean` | `false` | — |
| `showTrigger` | `boolean` | `true` | — |
| `size` | `"sm" \| "md" \| "lg"` | `"md"` | — |
| `className` | `string` | — | — |

### ComboboxChipsInput

Hereda las props de `Combobox.Input`.

| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
| `className` | `string` | — | — |

### ComboboxCollection

Hereda las props de `Combobox.Collection`.

Sin props propias: pasa todo al primitivo.

### ComboboxContent

Hereda las props de `Combobox.Popup` y `Combobox.Positioner`.

| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
| `align` | `"center" \| "start" \| "end"` | `"start"` | How to align the popup relative to the specified side. |
| `alignOffset` | `number \| OffsetFunction` | `0` | Additional offset along the alignment axis in pixels. Also accepts a function that returns the offset to read the dimensions of the anchor and positioner elements, along with its side and alignment. The function takes a `data` object parameter with the following properties: - `data.anchor`: the dimensions of the anchor element with properties `width` and `height`. - `data.positioner`: the dimensions of the positioner element with properties `width` and `height`. - `data.side`: which side of the anchor element the positioner is aligned against. - `data.align`: how the positioner is aligned relative to the specified side. |
| `anchor` | `Element \| VirtualElement \| React.RefObject<Element \| null> \| (() => Element \| VirtualElement \| null)` | — | An element to position the popup against. By default, the popup will be positioned against the trigger. |
| `side` | `"top" \| "bottom" \| "left" \| "right" \| "inline-end" \| "inline-start"` | `"bottom"` | Which side of the anchor element to align the popup against. May automatically change to avoid collisions. |
| `sideOffset` | `number \| OffsetFunction` | `6` | Distance between the anchor and the popup in pixels. Also accepts a function that returns the distance to read the dimensions of the anchor and positioner elements, along with its side and alignment. The function takes a `data` object parameter with the following properties: - `data.anchor`: the dimensions of the anchor element with properties `width` and `height`. - `data.positioner`: the dimensions of the positioner element with properties `width` and `height`. - `data.side`: which side of the anchor element the positioner is aligned against. - `data.align`: how the positioner is aligned relative to the specified side. |
| `className` | `string` | — | — |

### ComboboxEmpty

Hereda las props de `Combobox.Empty`.

| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
| `className` | `string` | — | — |

### ComboboxGroup

Hereda las props de `Combobox.Group`.

| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
| `className` | `string` | — | — |

### ComboboxInput

Hereda las props de `Combobox.Input`.

| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
| `disabled` | `boolean` | — | Whether the component should ignore user interaction. |
| `groupClassName` | `string` | — | Clases del contenedor (la superficie con borde). |
| `labels` | `{ clear?: string; trigger?: string }` | — | — |
| `showClear` | `boolean` | `true` | La cruz de limpiar. Aparece sola cuando hay valor. |
| `showTrigger` | `boolean` | `true` | El chevron que abre la lista. |
| `size` | `"sm" \| "md" \| "lg"` | `"md"` | — |
| `className` | `string` | — | — |

### ComboboxItem

Hereda las props de `Combobox.Item`.

| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
| `className` | `string` | — | — |

### ComboboxLabel

Hereda las props de `Combobox.GroupLabel`.

| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
| `className` | `string` | — | — |

### ComboboxList

Hereda las props de `Combobox.List`.

| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
| `className` | `string` | — | — |

### ComboboxSeparator

Hereda las props de `Combobox.Separator`.

| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
| `className` | `string` | — | — |

### ComboboxStatus

Hereda las props de `Combobox.Status`.

| Prop | Tipo | Por defecto | Descripción |
|---|---|---|---|
| `labels` | `{ loading?: string }` | — | — |
| `loading` | `boolean` | `false` | Búsqueda async en curso: fila con spinner. |
| `className` | `string` | — | — |

### ComboboxValue

Hereda las props de `Combobox.Value`.

Sin props propias: pasa todo al primitivo.

## Teclado

| Tecla | Qué hace |
|---|---|
| Escribir | Filtra la lista y la abre. |
| ↑ ↓ | Recorre los resultados. |
| Enter | Elige el resaltado. |
| Escape | Cierra; si está cerrado, limpia el texto. |
| Backspace | En modo chips y con el input vacío, borra el último chip. |

## Accesibilidad

- `ComboboxStatus` es una región `aria-live`: con `loading` anuncia «Buscando…» sin robar el foco.
- `ComboboxEmpty` sin children dice «Sin resultados»; con `{null}` no muestra nada (para el estado de carga).
- Cada chip trae un botón «Quitar …» con nombre accesible propio (`removeLabel`).
- El input hereda los estados de `Input`: `aria-invalid`, `disabled` y el mismo `focus-border`.

## Reglas de uso

- **`Combobox` si el valor tiene que ser uno de la lista; `Autocomplete` si se acepta texto libre.** País y cliente van en Combobox; ciudad y dirección, en Autocomplete.
- `disabled` va en el root para bloquear todo; en el input solo apaga la superficie.
- Para búsqueda contra el servidor: `filter={null}`, buscá en `onInputValueChange` (salteando `reason === "item-press"`) y mostrá `<ComboboxStatus loading />` mientras tanto.
- Objetos `{ value, label }` andan solos; para otra forma, `itemToStringLabel`.

## Relacionados

[autocomplete](/docs/components/autocomplete.md) · [select](/docs/components/select.md) · [input](/docs/components/input.md)
