Select
Em andamentoLista de opções nativa (<select>) para escolher um valor, com sugestão inicial que não pode ser devolvida como resposta e estado de erro. No Chrome e no Edge a lista aberta ganha o estilo do sistema; nos outros navegadores, é a do sistema operacional.
- Função
- Formulário e ação
- Também chamado de
- lista suspensa, seletor, combo, select, dropdown de formulário
- Mora em
- app/components/atoms/Select.tsx
- Última mudança
- 2026-09-28
Prévia
A peça ao vivo, vinda da ficha, na largura escolhida. Em larguras fixas, ela roda num quadro do tamanho de uma tela de verdade.
Na largura da página: 0px
Variantes na ficha
Lidas da ficha no build, na ordem do palco. Cada uma abre sozinha, sem o styleguide em volta — é o endereço que o palco carrega.
Quando usar
Para escolher um valor entre muitas opções conhecidas — estado, curso, modalidade —, dentro de um FormField.
Faça
- Use
placeholder("Selecione…"): vira uma opção desabilitada, que aparece enquanto nada foi escolhido. - Use dentro de um FormField, que liga rótulo, dica e erro.
- Largura e margem pela
className(vão para o invólucro, que posiciona a seta).
Evite
- Trocar o
<select>por uma lista feita à mão: o nativo traz teclado, leitor de tela e celular prontos. - Pôr a largura no
<select>porclassNameDoCampo: o invólucro continua na linha toda e a seta fica fora do campo. - Opção vazia escolhível como "nenhuma" — use o
placeholder, que não volta como resposta.
Quando não usar. Para poucas opções que valem ser vistas juntas, use o Radio. Para ações (editar, excluir), o Dropdown. Para filtrar uma lista na hora, o FilterGroup.
Nota de uso
A lista aberta é estilizada só no Chrome e no Edge, que suportam appearance: base-select. No Safari e no Firefox ela continua sendo a do sistema operacional — de propósito: estilo progressivo, sem trocar o <select> nativo por uma lista feita à mão. O foco é o do Input: borda de 2px em --border-focus, não mais vermelho. placeholder vira uma opção desabilitada, que não pode ser devolvida como resposta; error emite aria-invalid. Dê largura e margem pela className, que vai para o invólucro; para o <select> em si, classNameDoCampo.
Anatomia
As partes, na ordem em que o olho — e o teclado — passam.
- Campo — O `<select>`, com o mesmo contrato visual do Input (`campoVariants`) e espaço à direita para a seta.
- Seta — Ícone `ChevronDown`, decorativo, sobre o campo.
- Lista — As opções; a primeira, com `placeholder`, é desabilitada.
Estados
Os estados que a peça tem no código, e o que muda em cada um.
| Estado | O que muda |
|---|---|
| Padrão | Borda --border-interactive; com placeholder, começa na sugestão. |
| Foco | Borda --border-focus de 2px, por CSS — não mais vermelha. |
| Aberto | No Chrome e no Edge, a lista estilizada (appearance: base-select) sob o campo. |
| Erro | error ou aria-invalid: borda vermelha e aria-invalid no campo. |
| Desabilitado | 50% de opacidade, cursor proibido e fora do Tab — medido. |
Comportamento
| Situação | O que acontece |
|---|---|
| Sem `value` nem `defaultValue`, com `placeholder` | Começa na sugestão, que não pode ser escolhida de volta. |
| Lista aberta e Tab | Fecha sem mudar o valor — medido. |
Relacionados
Como usar no código
A importação e o menor uso, lidos do arquivo. O … marca as props obrigatórias.
import { Select } from '@/app/components/atoms/Select';
<Select>…</Select>Propriedades
Lidas do código da peça no build — não escritas à mão.
| Prop | Tipo | Padrão | Obrigatória | Descrição |
|---|---|---|---|---|
error | boolean | — | não | Pinta a borda de erro e emite aria-invalid, como no Input. |
placeholder | string | — | não | Texto de sugestão ("Selecione…"). Vira a primeira opção, desabilitada: aparece enquanto nada foi escolhido e não pode ser devolvida como resposta. Sem value nem defaultValue, o campo começa nela. |
classNameDoCampo | string | — | não | Classes do <select> em si. A className vai para a caixa externa. |
Aceita também: React.SelectHTMLAttributes<HTMLSelectElement>.
Medidas
| Parte | Valor | Classe |
|---|---|---|
| Altura com texto `text-sm` | 46px (medido) | px-4 py-3 |
| Espaço da seta | 40px à direita | pr-10 |
Tokens de cor
Os tokens semânticos que o código da peça usa, com o valor de hoje em app/globals.css.
| Token | Valor | Usado como |
|---|---|---|
--muted-foreground | #595959 | text-muted-foreground |
Teclado
| Tecla | Faz |
|---|---|
| Tab | Leva o foco ao campo. Desabilitado é pulado. |
| EnterEspaço↓ | Com a lista fechada, abre a lista na opção atual (ou na primeira escolhível) — medido no Chrome. |
| ↑↓HomeEnd | Com a lista aberta, andam pelas opções **sem escolher**. |
| EnterEspaço | Com a lista aberta, escolhem a opção em foco e fecham a lista. |
| Esc | Fecha a lista sem mudar o valor. |
| Letra | Com a lista fechada, escolhe direto a opção que começa com ela — medido: "e" escolhe EAD. |
Leitor de tela
O que é anunciado, e por quê.
- É o
<select>nativo: papel, valor e lista são anunciados pelo navegador e pelo leitor, sem ARIA de reforço. - A tabela de teclado foi medida no Chrome, com a lista estilizada; no Safari e no Firefox vale o teclado da lista do sistema.
O que sustenta o estado
Esta peça usa formulario. O estado dela é o de quem já foi ouvido com leitor de tela nesses padrões — e não uma passada sobre esta peça em específico.
Falta ouvir: formulario — ver docs/a11y-screen-reader-checklist.md.
Status e recursos
| Tipo | Recurso | Status |
|---|---|---|
| Código | app/components/atoms/Select.tsx | Disponível |
| Ficha | Storybook (abre em outra aba) | Disponível |
| Teste de acessibilidade | axe em npm run test | No gate de todo commit |
| Leitor de tela | Passada da E33 | Falta ouvir |
| Design | Figma | Desativado até a Fase 2 |
Histórico
Os últimos commits que tocaram o arquivo, lidos do git no build.
bcf95412026-09-28Merge pull request #13 from srbunnie/ds/roteiro-final
O histórico completo está no GitHub (abre em outra aba).