# Toggle

> Componentes / Formulário e ação · Estado: **Em andamento** — Implementado e utilizável, mas ainda sem a validação completa de acessibilidade.

Interruptor liga/desliga com efeito imediato, como uma luz: `role="switch"`, trilho verde quando ligado e o polegar deslizando. Tem descrição opcional e estado de erro.

- Função: Formulário e ação
- Também chamado de: interruptor, switch, chave, liga e desliga
- Mora em: `app/components/atoms/Toggle.tsx`
- Página: [https://phorte-design-system.vercel.app/styleguide/peca/Toggle](https://phorte-design-system.vercel.app/styleguide/peca/Toggle)
- Ficha no Storybook: [components-base-toggle](https://main--69b4847d498a9bd8659db9ba.chromatic.com/?path=/docs/components-base-toggle--docs)
- Prévia ao vivo, sozinha: [https://phorte-design-system.vercel.app/previa/Toggle/0](https://phorte-design-system.vercel.app/previa/Toggle/0)
- Todas as peças: [https://phorte-design-system.vercel.app/llms.txt](https://phorte-design-system.vercel.app/llms.txt)

## Como usar no código

```tsx
import { Toggle } from '@/app/components/atoms/Toggle';

<Toggle />
```

## Uso

### Variantes na ficha

1. [Ligado](https://phorte-design-system.vercel.app/previa/Toggle/0)
2. [Desligado](https://phorte-design-system.vercel.app/previa/Toggle/1)
3. [Desabilitado](https://phorte-design-system.vercel.app/previa/Toggle/2)

Para uma preferência que vale na hora em que muda — receber lembretes, mostrar legendas.

### Quando não usar

Para uma escolha que só vale ao enviar o formulário (aceitar termos, opções de inscrição), use o Checkbox.

### Faça

- Escreva o rótulo como o que fica ligado: "Lembretes por e-mail".
- Aplique o efeito na hora da mudança — é o que o interruptor promete.
- Use `description` para explicar o efeito sem alongar o nome.

### Evite

- Pedir confirmação ("Salvar") depois de mudar um interruptor — aí é Checkbox.
- Rótulos "Ligado/Desligado" no lugar do nome: o leitor já anuncia o estado.

### Nota de uso

É **interruptor**, `role="switch"`: o efeito é imediato, como ligar uma luz. Para escolha que só vale ao enviar o formulário, use o `Checkbox`. O trilho desligado tem limite em `--border-interactive`. A `description` é ligada por `aria-describedby` e fica fora do nome. Erro vindo do `FormField` aparece como anel vermelho **e** ícone ao lado do rótulo — estado nunca só por cor.

### Anatomia

1. **Trilho** — 44 × 24px; desligado em `--muted` com borda de controle, ligado em `--secondary`.
2. **Polegar** — 18px, branco, com 2px de folga para todos os lados nos dois estados.
3. **Rótulo** — Texto `text-sm` ao lado; com erro, um ícone de alerta antes dele.
4. **Descrição** — Linha embaixo, fora do nome, ligada por `aria-describedby`.

### Estados

| Estado | O que muda |
| --- | --- |
| Desligado | Trilho claro com borda `--border-interactive`; polegar à esquerda. |
| Ligado | Trilho e borda `--secondary` (verde); polegar desliza 20px para a direita. |
| Foco | Anel `ring-ring` de 2px em volta do trilho, só no teclado. |
| Erro | `aria-invalid`: anel vermelho no trilho e ícone de alerta ao lado do rótulo. |
| Desabilitado | Linha a 50%, cursor proibido e fora do Tab — medido. |

### Comportamento

| Situação | O que acontece |
| --- | --- |
| Clique no trilho ou no texto | Liga ou desliga — a linha é o `<label>` do controle. |

### Relacionados

- [Checkbox](https://phorte-design-system.vercel.app/styleguide/md/Checkbox.md) — Para escolha que só vale ao enviar.

## Especificação

### Propriedades

| Prop | Tipo | Padrão | Obrigatória | Descrição |
| --- | --- | --- | --- | --- |
| `label` | `string` | — | não |  |
| `description` | `string` | — | não | Linha de apoio, ligada ao controle por `aria-describedby` — fora do nome. |

Aceita também: `Omit<React.InputHTMLAttributes<HTMLInputElement>, 'type'>`.

### Medidas

| Parte | Valor | Classe |
| --- | --- | --- |
| Trilho | 44 × 24px | `h-6 w-11` |
| Polegar | 18px | `after:size-4.5` |
| Linha (alvo de toque) | 44px de altura | `min-h-alvo-toque` |

### Tokens de cor

| Token | Valor | Usado como |
| --- | --- | --- |
| `--card` | #FFFFFF | `bg-card`, `border-card` |
| `--destructive` | #BA0517 | `ring-destructive`, `text-destructive` |
| `--secondary` | #0B8434 | `bg-secondary`, `border-secondary` |
| `--border` | #E5E5E5 | `bg-border` |
| `--border-interactive` | #8C8C8C | `border-border-interactive` |
| `--foreground` | #1A1A1A | `text-ink` |
| `--muted` | #F4F6F9 | `bg-muted` |
| `--muted-foreground` | #595959 | `text-muted-foreground` |
| `--primary` | #D42B2B | `ring-primary/20` |
| `--ring` | var(--footer-red)), decisão da revisão 2. Se outra peça precisar
   * dele como superfície, o nome vira de papel (ex.: --surface-brand-strong). */
  --footer-red: #7D1B1B | `ring-ring` |

## Acessibilidade

### Teclado

| Tecla | Faz |
| --- | --- |
| Tab | Leva o foco ao interruptor. Desabilitado é pulado. |
| Espaço | Liga ou desliga — medido. |
| Enter | Não faz nada — medido. Como no Checkbox, só o Espaço alterna. |

### Leitor de tela

- `role="switch"`: o leitor anuncia "interruptor, ligado/desligado", e não "caixa de seleção".
- O controle nativo é visualmente escondido (`sr-only`) e o trilho desenhado é `aria-hidden`.

### O que sustenta o estado

Usa os padrões: formulario. Falta ouvir com leitor de tela: formulario.

## Status e recursos

| Tipo | Recurso | Status |
| --- | --- | --- |
| Código | `app/components/atoms/Toggle.tsx` | Disponível |
| Ficha | https://main--69b4847d498a9bd8659db9ba.chromatic.com/?path=/docs/components-base-toggle--docs | 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

- `0298af8` 2026-09-30 — E147: fechamento da Entrega 11 — REPORT.md, verificação cross-agent e o gate estático estrito
- Histórico completo no GitHub: https://github.com/srbunnie/Pos-Phorte-Design-System/commits/main/app/components/atoms/Toggle.tsx
