KDS
Forms

Select

Dropdown de seleção única — listbox portalada com keyboard navigation completa.

Overview

Select é o componente compound do Radix Select com tokens KDS. O trigger fica no fluxo da página; o listbox é portalado e animado (slide / fade) quando aberto. Suporta agrupamento (SelectGroup + SelectLabel) e separação (SelectSeparator) — use isso para listas longas que se beneficiam de seções nomeadas (Américas, Europa, Ásia).

Para listas curtas onde ver todas as opções facilita a decisão (≤5 opções), RadioGroup é melhor — Radio mostra tudo visualmente. Select esconde até abrir, o que penaliza decisões rápidas mas economiza espaço vertical.

Preview
Select básico com placeholder.

Anatomy

<Select>
  <SelectTrigger>           ← visível, no fluxo
    <SelectValue />          ← mostra valor ou placeholder
  </SelectTrigger>
  <SelectContent>            ← portalado, animado
    <SelectGroup>            ← opcional
      <SelectLabel />
      <SelectItem value="a">A</SelectItem>
      ...
    </SelectGroup>
    <SelectSeparator />      ← opcional, entre grupos
  </SelectContent>
</Select>

Subcomponents

ComponenteDescrição
SelectRaiz que controla open/closed e value.
SelectTriggerBotão visível que abre o listbox.
SelectValueRenderiza o valor atual ou placeholder.
SelectContentContainer portalado com a lista.
SelectGroupAgrupa items relacionados.
SelectLabelTítulo de um SelectGroup.
SelectItemCada opção individual.
SelectSeparatorLinha divisória entre grupos.
SelectScrollUpButton / ScrollDownButtonBotões de scroll quando a lista é maior que o popover.

Usage

import {
  Select,
  SelectTrigger,
  SelectValue,
  SelectContent,
  SelectItem
} from "@kalvner/kds/forms/select";

export function FrameworkPicker() {
  return (
    <Select>
      <SelectTrigger className="w-60">
        <SelectValue placeholder="Selecione" />
      </SelectTrigger>
      <SelectContent>
        <SelectItem value="next">Next.js</SelectItem>
        <SelectItem value="remix">Remix</SelectItem>
      </SelectContent>
    </Select>
  );
}

Props

Select (Root)

PropTipoDefaultDescrição
valuestringValor selecionado (controlado).
defaultValuestringNão controlado.
onValueChange(v: string) => voidCallback.
disabledbooleanfalseBloqueia trigger.
namestringNome do form, para FormData.

SelectTrigger

PropTipoDefaultDescrição
size'sm' | 'default''default'Altura.
aria-invalidbooleanAciona ring vermelho.

States

With placeholder
Texto muted enquanto vazio.
Disabled
Trigger sem pointer events.
Sizes
sm vs default.
Error
aria-invalid no trigger + mensagem abaixo.
Selecione um país.

Composition

Grouped countries
Listas longas se beneficiam de SelectGroup + SelectLabel + SelectSeparator.

When to use

  • Escolha única entre 5–~30 opções fixas.
  • Quando o espaço vertical importa (forms longos, sidebars).
  • Para listas onde agrupamento facilita (continentes, categorias).

When not to use

  • ≤5 opções — RadioGroup deixa visíveis e acelera escolha.
  • Listas com >50 opções ou onde o usuário sabe o que digitar — use Combobox (Cmdk) com busca.
  • Múltipla seleção — Select aqui é single. Use uma lista de Checkboxes ou um MultiSelect dedicado.
  • Ações (Salvar, Excluir) — use Button, não Select.

Best practices

  • Sempre tenha placeholder ou defaultValue. Trigger vazio sem texto fica confuso.
  • Itens devem ser short, single-line. Se o texto vai quebrar, o Select não é o componente certo.
  • Agrupe quando há >10 opções. SelectGroup + SelectLabel reduz carga cognitiva.
  • Não use ícones decorativos sem affordance. Ícones devem diferenciar items, não decorar.

Accessibility

ConcernComportamento
RolesRadix expõe role="combobox" no trigger, role="listbox" no content, role="option" em cada item.
KeyboardTab foca trigger; Space ou Enter ou abre; ↑↓ navega; Enter seleciona; Esc fecha; type-ahead funciona (digite "B" para pular pra Brasil).
Focus managementFoco volta ao trigger ao fechar.
Anúncio"Combobox, [valor atual], collapsed/expanded, [N de M]".
Erroaria-invalid no trigger; mensagem com aria-describedby.
Touch targetTrigger 36px default — borderline mobile. Para mobile crítico, considere h-10.
  • RadioGroup — listas curtas visíveis.
  • Form — wrappers de RHF + Zod.
  • Combobox (próxima fase) — quando busca ajuda.

On this page