# Checkbox

Caixa de marcar.

`indeterminate` e o estado misto: alguns itens marcados, nem todos. E o que a
caixa de "selecionar todas" mostra quando parte da lista esta selecionada.

Sem rótulo visível ao lado, passe `aria-label`.

## O rótulo

Passe o texto como filho e a caixa sai dentro de um `<label>`, então clicar no
texto também marca:

```tsx
<Checkbox defaultChecked>ISS retido na fonte</Checkbox>
```

Sem filho, sai só a caixa, e o arranjo fica com quem monta a tela. Use assim
quando o rótulo tiver estrutura própria: um título com descrição embaixo, um
link no meio da frase. Nesse caso, o `<label>` em volta é seu, e é ele que faz
o clique no texto valer.

## A caixa marcada

A caixa marcada pinta `accent-text`, e não `accent`, com o tique em
`surface-raised`. É a mesma troca do trilho do `Switch`, e pelo mesmo motivo:
com a lima cheia o preenchimento media 1,21:1 sobre a página no tema claro e
1,26:1 sobre o cartão, abaixo dos 3:1 que a WCAG 1.4.11 pede para controle sem
texto.

Aqui o estado ainda se lia, e é o que fazia o defeito passar: o tique era
grafite e se via de qualquer jeito. O que desaparecia era a **fronteira da
caixa** - sobrava um tique flutuando no lugar de uma caixa marcada. Com
`accent-text` a fronteira mede 5,55:1 sobre a página e 5,75:1 sobre o cartão, e
o tique mede 5,75:1 dentro do preenchimento.

O estado misto entra na mesma troca, pelo mesmo par de tokens: ele pintava a
lima cheia também, e a caixa de selecionar-todas sumia igual.

Não havia lima clara que resolvesse: o passo mais escuro antes do `accent-text`
é o `accent-active`, e ele para em 1,49:1 sobre a página. No tema escuro os dois
papéis apontam para o mesmo valor, então lá a caixa não mudou de cor, e o tique
foi de 15,06:1 para 13,91:1.

Quem escreve tema de cliente herda a garantia sem fazer nada: `accent-text` já
precisa de 4,5:1 sobre `bg`, `surface` e `surface-raised`, e contraste é
simétrico - é a mesma medida que a fronteira e o tique usam.

## Desabilitado

Desabilitado se pinta com token, e não com opacidade: o fundo passa a
`surface-raised` e o visto vai para `fg-disabled`. Vale marcada, desmarcada e no
estado misto. Antes o `indeterminate` vencia o desabilitado, e a caixa de
selecionar-todas saía pintada de acento cheio.

A borda desce um degrau, para `border-disabled`. Os dois vizinhos não serviam:
`border` dá 1,3:1 contra o próprio preenchimento e a caixa travada sumiria, e
`border-strong` (a fronteira de controle nos 3:1 da WCAG 1.4.11) deixaria
travada igual a viva. O token do meio existe para esta faixa, e é o único par da
casa com teto além de piso: pelo menos 1,6:1 contra o fundo, e a fronteira viva
pesando 1,4 vez mais. A 1.4.11 dispensa controle inativo dos 3:1, e é essa folga
que ele ocupa.

Isso importa mais onde não há rótulo. Numa coluna de seleção do `DataTable`, uma
caixa desmarcada e travada não tem texto apagado ao lado para dizer o estado. E
`surface` e `surface-raised` são a mesma branca no tema claro, então o
preenchimento também não diz nada. Sobrava a borda, e ela não dizia.

## Quando não usar

Para o ajuste que vale na hora (notificação que liga, modo escuro, recurso que
a conta passa a ter), use `Switch`. A caixa promete um Salvar depois; a chave
promete que já valeu. Uma caixa de marcar numa tela de preferências sem botão
de salvar deixa a pessoa esperando por um botão que não existe.

Para escolher uma opção entre várias que se excluem, é `RadioGroup`: caixa que
desmarca a irmã ao ser marcada é um rádio malfeito.

## No React Native

Traduz, com um porém que morde na primeira linha: no nativo o `Checkbox` é **sempre controlado**. `checked` e `onCheckedChange` são obrigatórios, não há `defaultChecked` e não há `indeterminate`: a caixa de selecionar-todas do web não tem terceiro estado lá. Copiar `<Checkbox defaultChecked>ISS retido</Checkbox>` do web não compila.

## Importação

```tsx
import { Checkbox } from '@rivocode/ui'
```

## Exemplos

### Estados

```tsx
import { Checkbox, Field, FieldLabel } from '@rivocode/ui'

export function States() {
  return (
    <div className="flex flex-wrap items-center gap-6">
      <label className="flex items-center gap-2 text-base text-fg">
        <Checkbox aria-label="Não marcada" />
        Não marcada
      </label>
      <label className="flex items-center gap-2 text-base text-fg">
        <Checkbox checked aria-label="Marcada" />
        Marcada
      </label>
      <label className="flex items-center gap-2 text-base text-fg">
        <Checkbox indeterminate aria-label="Algumas" />
        Algumas
      </label>
      <label className="flex items-center gap-2 text-base text-fg-disabled">
        <Checkbox disabled aria-label="Desabilitada" />
        Desabilitada
      </label>
    </div>
  )
}
```

### Selecionar todas

```tsx
import { Checkbox, Field, FieldLabel } from '@rivocode/ui'

export function SelectAll() {
  return (
    <div className="flex max-w-xs flex-col gap-3">
      <label className="flex items-center gap-2 border-b border-border pb-3 text-base font-medium text-fg">
        <Checkbox indeterminate aria-label="Selecionar todas" />
        Selecionar todas
      </label>
      <label className="flex items-center gap-2 text-base text-fg">
        <Checkbox checked aria-label="Nota 4813" />
        Nota 4813
      </label>
      <label className="flex items-center gap-2 text-base text-fg">
        <Checkbox aria-label="Nota 4814" />
        Nota 4814
      </label>
    </div>
  )
}
```

### Dentro de campo

```tsx
import { Checkbox, Field, FieldLabel } from '@rivocode/ui'

export function InsideAField() {
  return (
    <Field name="termos" className="max-w-sm">
      <div className="flex items-center gap-2">
        <Checkbox aria-label="Aceito os termos" />
        <FieldLabel>Aceito os termos e condições</FieldLabel>
      </div>
    </Field>
  )
}
```

### Com rótulo

```tsx
import { Checkbox, Field, FieldLabel } from '@rivocode/ui'

export function WithText() {
  return (
    <div className="space-y-3">
      <Checkbox defaultChecked>ISS retido na fonte</Checkbox>
      <Checkbox>INSS</Checkbox>
      <Checkbox disabled>IRRF, indisponível neste regime</Checkbox>
    </div>
  )
}
```

## Props

| Prop | Tipo | Obrigatória | Desde | O que faz |
| --- | --- | --- | --- | --- |
| `checked` | `boolean` |  | 0.4.0 | Whether the checkbox is currently ticked. |
| `classNames` | `Partial<Record<"box" \| "indicator" \| "label", string>>` |  | 0.5.0 | Classe por parte: `box`, `indicator`, `label`. |
| `defaultChecked` | `boolean` |  | 0.4.0 | Whether the checkbox is initially ticked. |
| `disabled` | `boolean` |  | 0.4.0 | Whether the component should ignore user interaction. |
| `form` | `string` |  | 0.4.0 | Identifies the form that owns the hidden input. |
| `indeterminate` | `boolean` |  | 0.4.0 | Whether the checkbox is in a mixed state: neither ticked, nor unticked. |
| `inputRef` | `Ref<HTMLInputElement>` |  | 0.4.0 | A ref to access the hidden `<input>` element. |
| `labelClassName` | `string` |  | 0.4.0 | Classe do `<label>` de fora, quando ha texto. |
| `name` | `string` |  | 0.4.0 | Identifies the field when a form is submitted. |
| `nativeButton` | `boolean` |  | 0.4.0 | Whether the component renders a native `<button>` element when replacing it via the `render` prop. |
| `onCheckedChange` | `((checked: boolean, eventDetails: { reason: "none"; event: Event; cancel: () => void; allowPropagation: () => void; isCanceled: boolean; isPropagationAllowed: boolean; trigger: Element \| undefined; }) => void)` |  | 0.4.0 | Event handler called when the checkbox is ticked or unticked. |
| `parent` | `boolean` |  | 0.4.0 | Whether the checkbox controls a group of child checkboxes. |
| `readOnly` | `boolean` |  | 0.4.0 | Whether the user should be unable to tick or untick the checkbox. |
| `render` | `ComponentRenderFn<HTMLProps, CheckboxRootState> \| ReactElement<unknown, string \| JSXElementConstructor<any>>` |  | 0.4.0 | Allows you to replace the component's HTML element with a different tag, or compose it with another component. |
| `required` | `boolean` |  | 0.4.0 | Whether the user must tick the checkbox before submitting a form. |
| `uncheckedValue` | `string` |  | 0.4.0 | The value submitted with the form when the checkbox is unchecked. |
| `value` | `string` |  | 0.4.0 | The checkbox's value. |

Além dessas: repassa `className`, `style`, `id` e os demais atributos do elemento raiz.

## Ver também

- [Autocomplete](/componentes/autocomplete.md)
- [Calendar](/componentes/calendar.md)
- [CheckboxGroup](/componentes/checkbox-group.md)
- [ColorPicker](/componentes/color-picker.md)
- [Combobox](/componentes/combobox.md)
- [DatePicker](/componentes/date-picker.md)
- [Convenções da biblioteca](/convencoes.md): Provider, tokens e as regras que valem para toda peça
- [Índice completo](/llms.txt)
