Checkbox
Em andamentoCaixa de marcar com rótulo, para escolhas independentes — cada uma liga ou desliga sozinha. Tem o estado parcialmente marcado, para o item-pai de um grupo, e a variante aceite, para o "Li e aceito os termos".
- Função
- Formulário e ação
- Também chamado de
- caixa de seleção, checkbox, aceite, termos de uso
- Mora em
- app/components/atoms/Checkbox.tsx
- Última mudança
- 2026-09-30
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
Quando cada opção vale por si e a pessoa pode marcar várias, ou nenhuma — e quando a escolha só vale ao enviar o formulário.
Faça
- Escreva o rótulo como afirmação que a marca torna verdadeira: "Quero receber novidades".
- Agrupe opções relacionadas num
<fieldset>com<legend>. - Use
indeterminadono item-pai quando só parte dos filhos está marcada. - Use
variant="aceite"só no aceite que libera o envio.
Evite
- Usar
aceiteem opção comum: o vermelho diz "ainda falta", e opção comum não tem lado certo. - Passar
aria-invalidsem mensagem de erro: a caixa fica vermelha e muda. O erro vem do FormField, com o texto. - Rótulo negativo ("Não quero receber…") — marcar para desligar confunde.
Quando não usar. Para uma escolha só entre várias, use o Radio. Para ligar algo com efeito imediato, o Toggle. Para filtrar uma lista na hora, o FilterGroup.
Nota de uso
O estado de erro é visível, e não só anunciado: sai do mesmo aria-invalid que o FormField usa como fonte única. Passar aria-invalid sem passar a mensagem deixa o campo vermelho e mudo — as duas coisas andam juntas. indeterminado desenha um traço e o leitor anuncia "parcialmente marcado": é o item-pai de um grupo. A linha inteira é o <label>, com 44px de altura — a caixa continua com 16px. Nos três controles de marcação a className vai para o invólucro. `variant="aceite"` é para o aceite que libera o envio (termos de uso, contrato): vermelha enquanto falta, verde quando aceita. O vermelho ali é "ainda falta", não erro — não emite aria-invalid; o erro, se o envio for tentado, vem do FormField. Não use em opção comum, que não tem lado certo.
Anatomia
As partes, na ordem em que o olho — e o teclado — passam.
- Caixa — 16px, borda de controle; marcada, fundo vermelho de interface (ou verde, no `aceite`) com o visto branco.
- Rótulo — Texto `text-sm` ao lado. A linha inteira é o `<label>`: tocar em qualquer ponto marca.
Estados
Os estados que a peça tem no código, e o que muda em cada um.
| Estado | O que muda |
|---|---|
| Desmarcada | Caixa vazia, borda --border-interactive. No aceite: borda e fundo vermelhos claros. |
| Marcada | Fundo --primary com visto branco. No aceite: fundo --success. |
| Parcialmente marcada | indeterminado: traço no lugar do visto; o leitor anuncia "parcialmente marcado". |
| Foco | Anel ring-ring de 2px em volta da caixa, só no teclado. |
| Erro | aria-invalid (vindo do FormField): borda vermelha. |
| Desabilitada | Linha inteira a 50% de opacidade, cursor proibido e fora da ordem de Tab. |
Comportamento
| Situação | O que acontece |
|---|---|
| Link dentro do rótulo | Clicar no link abre o destino e não marca a caixa: o label não ativa o controle quando o clique é num link (é o HTML). A prop rotuloInterativo que a E73 previa não foi criada por isso — conferido no teste da Newsletter. |
| Clique na caixa ou no texto | Marca ou desmarca — o rótulo é o <label> da caixa. |
| `indeterminado` muda | O componente liga a propriedade indeterminate do <input> por JavaScript — não existe atributo HTML para ela. |
| Aceite marcado | A caixa passa do vermelho ao verde; não emite aria-invalid em nenhum dos dois. |
Relacionados
Como usar no código
A importação e o menor uso, lidos do arquivo. O … marca as props obrigatórias.
import { Checkbox } from '@/app/components/atoms/Checkbox';
<Checkbox />Propriedades
Lidas do código da peça no build — não escritas à mão.
| Prop | Tipo | Padrão | Obrigatória | Descrição |
|---|---|---|---|---|
variant | 'padrao' | 'aceite' | 'padrao' | não | Variante do cva. |
label | React.ReactNode | — | não | — |
indeterminado | boolean | false | não | Estado intermediário: "alguns marcados", no item-pai de um grupo. Liga o indeterminate do <input> — que só existe por JavaScript, não há atributo HTML — e o leitor de tela anuncia "parcialmente marcado". |
Aceita também: Omit<React.InputHTMLAttributes<HTMLInputElement>, 'type'>.
Medidas
| Parte | Valor | Classe |
|---|---|---|
| Caixa | 16 × 16px | h-4 w-4 |
| Linha (alvo de toque) | 44px de altura | min-h-alvo-toque |
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 |
|---|---|---|
--primary | #D42B2B | bg-primaryborder-primary |
--success | #2E844A | bg-successborder-success |
--background | #FAFAFA | bg-background |
--border-interactive | #8C8C8C | border-border-interactive |
--destructive | #BA0517 | border-destructive |
--destructive-subtle | #F9EBEC | bg-destructive-subtle |
--foreground | #1A1A1A | text-ink |
--primary-foreground | #FFFFFF | text-primary-foreground |
Teclado
| Tecla | Faz |
|---|---|
| Tab | Vai de caixa em caixa — num grupo, cada uma é uma parada (medido: Presencial, Ao vivo online, EAD, Semipresencial). |
| Espaço | Marca ou desmarca a caixa em foco. |
| Enter | Não faz nada — medido. Numa caixa, só o Espaço marca. |
| ↑↓ | Não andam entre as caixas de um grupo — medido. Setas são do Radio. |
Leitor de tela
O que é anunciado, e por quê.
- O nome acessível é o rótulo: a caixa e o texto estão no mesmo
<label>. - O visto e o traço são
aria-hidden; o estado lido vem do<input>(marcado, não marcado, parcialmente marcado).
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/Checkbox.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.
0298af82026-09-30E147: fechamento da Entrega 11 — REPORT.md, verificação cross-agent e o gate estático estrito
O histórico completo está no GitHub (abre em outra aba).