Forms
Switch
Toggle de efeito imediato — on / off, sem botão Salvar.
Overview
Switch é um toggle visual que sinaliza estado ligado / desligado.
A diferença crítica em relação ao Checkbox é
comportamental: Switch tem efeito imediato — o usuário move o
controle e a mudança é persistida agora, sem botão Salvar. Checkbox
faz parte de uma form que será submetida.
Use Switch em painéis de configurações (notificações, dark mode, permissões), feature flags, controles de produto. Não use Switch em forms multi-campo que terminam num Submit — ali, Checkbox é o componente correto.
Preview
Switch com Label ao lado.
Anatomy
<Switch>
├─ [data-slot="switch"]
├─ [data-state="checked" | "unchecked"]
├─ [data-size="sm" | "default"]
└─ <Thumb /> (translate-x baseado no state)
</Switch>Usage
import { Switch } from "@kalvner/kds/forms/switch";
import { Label } from "@kalvner/kds/forms/label";
export function NotificationsToggle() {
return (
<div className="flex items-center gap-3">
<Switch
id="notify"
onCheckedChange={(v) => persist({ notify: v })}
/>
<Label htmlFor="notify">Notificações</Label>
</div>
);
}Props
| Prop | Tipo | Default | Descrição |
|---|---|---|---|
checked | boolean | — | Controlado. |
defaultChecked | boolean | false | Não controlado. |
onCheckedChange | (v: boolean) => void | — | Callback. |
size | 'sm' | 'default' | 'default' | Altura do switch + thumb. |
disabled | boolean | false | Bloqueia interação. |
id | string | — | Vincula ao Label. |
Variants
Sizes
sm para listas densas, default para painéis.
States
Off
Background input, thumb à esquerda.
On
Background primary, thumb à direita.
Disabled
Sem pointer events, opacidade reduzida.
With label on the side
Padrão de painel de configurações.
Composition
Settings panel
Linhas com label + descrição + switch à direita.
Resumo diário e alertas importantes.
Recomendado — adiciona uma camada extra de segurança.
When to use
- Configurações persistidas imediatamente (dark mode, notificações, feature flags do produto).
- Permissões granulares em painéis de admin.
- Qualquer "ligar/desligar" que tem efeito agora, sem submit.
When not to use
- Em formulários multi-campo que terminam num submit — use
Checkbox. Switch num form com Submit gera ambiguidade (a configuração foi aplicada agora ou só após submit?). - Para escolher entre múltiplas opções — use
RadioGroup. - Para acionar uma ação destrutiva — use
Buttoncom Dialog de confirmação.
Best practices
- Estado on é a configuração ativa. "Notificações" = ON significa notificações ativas. Evite labels invertidas como "Desativar notificações" — confunde o usuário do estado.
- Persiste em onChange. Se a operação pode falhar (rede), mostre estado optimista + rollback em erro com Toast.
- Não desabilite sem explicação. Switch desabilitado merece um Tooltip ou helper text dizendo o porquê.
- Sem label "On / Off" próprio. O Label descreve o que é controlado; o estado é inferido do Switch.
Accessibility
| Concern | Comportamento |
|---|---|
| Roles | Radix expõe role="switch" + aria-checked. |
| Keyboard | Tab foca; Space ou Enter alterna. |
| Label | Vincule via htmlFor + id ou aria-label. |
| Disabled | disabled bloqueia foco e interação. |
| Touch target | Default size (32×18px) é pequeno para mobile — combine com Label clicável (a linha inteira em painéis), ampliando a área hit. |
| Anúncio | Leitores de tela falam "ligado" / "desligado" + texto do label. |