Capítulo 26 de 108

Checkbox

Core Idea

Controle que alterna entre marcado e não marcado. Use para aceitar termos, opções de configuração e seleção múltipla em listas ou tabelas (select-all + linha a linha).

Key Concepts

  • checked / onCheckedChange: par controlado; onCheckedChange recebe o novo estado (boolean).
  • defaultChecked: define estado inicial em uso não controlado (uncontrolled).
  • disabled: desabilita interação com o checkbox.
  • aria-invalid: marca o checkbox como inválido (usar junto com data-invalid no Field).
  • Composição com Field: Checkbox normalmente é pareado com Field/FieldLabel/FieldContent/FieldDescription para layout e acessibilidade corretos, não com <label> solto.
  • Base: construído sobre @base-ui/react (Base UI Checkbox).

Code Examples

import { Checkbox } from "@/components/ui/checkbox"
import { Field, FieldGroup, FieldLabel } from "@/components/ui/field"

export function CheckboxBasic() {
  return (
    <FieldGroup className="mx-auto w-56">
      <Field orientation="horizontal">
        <Checkbox id="terms-checkbox-basic" name="terms-checkbox-basic" />
        <FieldLabel htmlFor="terms-checkbox-basic">
          Accept terms and conditions
        </FieldLabel>
      </Field>
    </FieldGroup>
  )
}
  • O que demonstra: composição mínima recomendada com Field + FieldLabel (orientação horizontal).
import * as React from "react"

export function Example() {
  const [checked, setChecked] = React.useState(false)
  return <Checkbox checked={checked} onCheckedChange={setChecked} />
}
  • O que demonstra: uso controlado do estado com checked/onCheckedChange.
const handleSelectAll = (checked: boolean) => {
  if (checked) setSelectedRows(new Set(tableData.map((row) => row.id)))
  else setSelectedRows(new Set())
}
// <Checkbox checked={selectAll} onCheckedChange={handleSelectAll} />
  • O que demonstra: padrão "select all" em cabeçalho de tabela sincronizado com checkboxes por linha.

Anti-patterns

  • Checkbox sem Field/FieldLabel: perde o acoplamento label-input e os estilos de estado disabled/invalid (data-disabled, data-invalid) que dependem do wrapper Field.
  • Misturar controlado e não controlado: não passar checked junto com defaultChecked no mesmo componente.

Key Takeaways

  1. Para checkbox controlado, onCheckedChange já entrega o boolean, não um evento — use direto como setter de estado.
  2. Estado inválido é duplo: aria-invalid no Checkbox + data-invalid no Field pai, para acessibilidade e estilo coexistirem.
  3. Estado desabilitado segue o mesmo padrão: disabled no Checkbox + data-disabled no Field.
  4. FieldSet/FieldLegend/FieldGroup compõem listas de checkboxes (grupos de opções não exclusivas).
  5. RTL é suportado passando dir nos componentes de layout, sem lógica extra no Checkbox.

Connects To

  • Field: wrapper obrigatório para layout, label, descrição e estados (disabled/invalid) do Checkbox.
  • Label: alternativa simples ao FieldLabel quando não há necessidade de FieldDescription/FieldTitle.
  • Radio Group: use quando a seleção deve ser exclusiva (uma entre várias), não múltipla.
  • Switch: alternativa visual para toggle binário fora de contexto de formulário/lista.