Capítulo 34 de 108

Combobox

Core Idea

Input de autocomplete com lista de sugestões filtrável, suportando seleção única, múltipla (com chips), agrupamento e itens customizados; construído sobre Base UI Combobox.

Key Concepts

  • items: array de opções passado ao Combobox raiz (strings, objetos, ou grupos com { value, items }).
  • itemToStringValue: função que converte um item objeto na string exibida/filtrada; obrigatória quando items não são strings simples.
  • multiple: habilita seleção múltipla; requer ComboboxChips/ComboboxChipsInput/ComboboxValue/ComboboxChip em vez de ComboboxInput simples.
  • value / onValueChange / defaultValue: controle do(s) valor(es) selecionado(s) (array quando multiple).
  • autoHighlight: destaca automaticamente o primeiro item ao filtrar.
  • showClear (em ComboboxInput): exibe botão para limpar a seleção.
  • showTrigger (em ComboboxInput): controla se o botão de abrir/trigger aparece dentro do input (usado como false no padrão "Popup").
  • ComboboxGroup / ComboboxLabel / ComboboxCollection / ComboboxSeparator: estrutura para itens agrupados com cabeçalho e separador.
  • ComboboxTrigger + render: permite abrir o combobox a partir de um botão externo (padrão popup), movendo o ComboboxInput para dentro do ComboboxContent.
  • useComboboxAnchor: hook que retorna um ref compartilhado entre o elemento de ancoragem (ex: ComboboxChips) e ComboboxContent, usado em combobox multiple/customizado.
  • aria-invalid: em ComboboxInput, marca estado de erro visual.
  • disabled: desabilita o combobox inteiro.

Code Examples

const frameworks = ["Next.js", "SvelteKit", "Nuxt.js", "Remix", "Astro"] as const

<Combobox items={frameworks}>
  <ComboboxInput placeholder="Select a framework" />
  <ComboboxContent>
    <ComboboxEmpty>No items found.</ComboboxEmpty>
    <ComboboxList>
      {(item) => <ComboboxItem key={item} value={item}>{item}</ComboboxItem>}
    </ComboboxList>
  </ComboboxContent>
</Combobox>
  • O que demonstra: composição mínima (simples): Combobox > ComboboxInput + ComboboxContent > ComboboxEmpty + ComboboxList.
<Combobox items={frameworks} itemToStringValue={(f) => f.label}>
  <ComboboxInput placeholder="Select a framework" />
  <ComboboxContent>
    <ComboboxList>
      {(f) => <ComboboxItem key={f.value} value={f}>{f.label}</ComboboxItem>}
    </ComboboxList>
  </ComboboxContent>
</Combobox>
  • O que demonstra: itens como objetos {label, value} exigindo itemToStringValue para filtragem/exibição correta.
const [value, setValue] = React.useState<string[]>([])

<Combobox items={frameworks} multiple value={value} onValueChange={setValue}>
  <ComboboxChips>
    <ComboboxValue>
      {value.map((item) => <ComboboxChip key={item}>{item}</ComboboxChip>)}
    </ComboboxValue>
    <ComboboxChipsInput placeholder="Add framework" />
  </ComboboxChips>
  <ComboboxContent>
    <ComboboxList>
      {(item) => <ComboboxItem key={item} value={item}>{item}</ComboboxItem>}
    </ComboboxList>
  </ComboboxContent>
</Combobox>
  • O que demonstra: seleção múltipla controlada com chips visuais.
<Combobox items={timezones}>
  <ComboboxInput placeholder="Select a timezone" />
  <ComboboxContent>
    <ComboboxList>
      {(group, index) => (
        <ComboboxGroup key={group.value} items={group.items}>
          <ComboboxLabel>{group.value}</ComboboxLabel>
          <ComboboxCollection>
            {(item) => <ComboboxItem key={item} value={item}>{item}</ComboboxItem>}
          </ComboboxCollection>
          {index < timezones.length - 1 && <ComboboxSeparator />}
        </ComboboxGroup>
      )}
    </ComboboxList>
  </ComboboxContent>
</Combobox>
  • O que demonstra: agrupamento com ComboboxGroup/ComboboxCollection/ComboboxSeparator, cada item do items sendo um grupo { value, items }.
<Combobox items={countries} defaultValue={countries[0]}>
  <ComboboxTrigger render={<Button variant="outline" className="w-64 justify-between font-normal" />}>
    <ComboboxValue />
  </ComboboxTrigger>
  <ComboboxContent>
    <ComboboxInput showTrigger={false} placeholder="Search" />
    ...
  </ComboboxContent>
</Combobox>
  • O que demonstra: padrão "Popup" — abrir o combobox a partir de um Button externo via ComboboxTrigger + render, com o input de busca movido para dentro do content.

Reference Tables

ComposiçãoEstrutura
SimplesCombobox > ComboboxInput, ComboboxContent > ComboboxEmpty, ComboboxList > ComboboxItem
Com chips (multiple)Combobox > ComboboxChips > ComboboxValue > ComboboxChip, ComboboxChipsInput; ComboboxContent > ComboboxList
Com gruposComboboxList > ComboboxGroup > ComboboxLabel, ComboboxCollection > ComboboxItem; ComboboxSeparator entre grupos

Anti-patterns

  • Passar objetos em items sem itemToStringValue: quebra a filtragem por texto digitado, pois o combobox não sabe extrair a string de comparação.
  • Usar multiple sem trocar ComboboxInput por ComboboxChips/ComboboxChipsInput: a UI de chips não aparece; a composição muda estruturalmente, não é apenas uma prop.
  • Esquecer useComboboxAnchor/prop anchor ao customizar o container de chips: o ComboboxContent pode não se posicionar corretamente em relação ao ComboboxChips.

Code Examples (adicional)

<ComboboxInput placeholder="Select a timezone">
  <InputGroupAddon>
    <GlobeIcon />
  </InputGroupAddon>
</ComboboxInput>
  • O que demonstra: adicionar ícone/addon dentro do input via InputGroupAddon (composição com Input Group).

Key Takeaways

  1. Combobox tem três formas de composição distintas (simples, chips/multiple, grupos) que trocam componentes filhos, não apenas props.
  2. itemToStringValue é obrigatório sempre que items não são strings puras — é o ponto central para dados de objeto/API real.
  3. multiple + ComboboxChips é o padrão de multi-seleção; value/onValueChange viram arrays.
  4. ComboboxTrigger com render permite desacoplar o gatilho visual (ex: um Button) do input de busca, útil para combobox tipo "select popup".
  5. Custom items (renderizar componentes ricos como Item/ItemTitle/ItemDescription dentro de ComboboxItem) funciona porque ComboboxItem aceita qualquer children.

Connects To

  • Popover: Combobox compartilha a mesma base de posicionamento de conteúdo flutuante (Base UI) usada pelo Date Picker.
  • Input Group: usado para adicionar ícones/addons ao ComboboxInput.
  • Item: usado para compor itens ricos (título + descrição) dentro de ComboboxItem.
  • Button: usado como trigger externo no padrão Popup via ComboboxTrigger/render.