Switch

Formulario

Alternador on/off sobre o primitivo Radix, com uma prop visual para reproduzir o estado misto do Switch legado.

Carregando

Instalação

Recebe correções por update de versão. O caminho recomendado.

npm i @trdr/ui

import { Switch } from "@trdr/ui/switch"

Uso

import { Switch } from "@trdr/ui/switch"

export function Exemplo() {
  return <Switch />
}

Props

SwitchPropsestende React.ComponentPropsWithoutRef<typeof SwitchPrimitive.Root>
PropTipoDescrição
mixed?booleanEstado misto (indeterminado), herdado do Switch legado (`SwitchType = "on" | "off" | "mixed"`). Decisao de migracao: o Radix Switch so modela `checked` como booleano, sem terceiro estado nativo (ao contrario do Checkbox, cujo `CheckedState` ja inclui "indeterminate"). Reproduzir o misto exigiria bifurcar o primitivo ou reimplementar o Switch do zero, o que contradiz o proposito de usar o Radix como base. Em vez disso, o misto vira uma prop puramente visual por cima do primitivo: com `mixed`, incluimos `aria-checked="mixed"` no objeto de props passado ao `Root` (o Radix monta o seu proprio `aria-checked` antes de espalhar o restante das props recebidas, entao a chave so pode existir quando queremos vencer a sobrescrita; passar `undefined` no lugar de omitir a chave apagaria o valor correto do Radix quando `mixed` for falso) e trocamos o thumb pelo traco central do legado. O `checked` on/off interno do Radix continua existindo por baixo: a primeira interacao do usuario resolve o misto para um dos dois lados, o mesmo comportamento do Checkbox indeterminado.

Quando usar

Use o switch para ligar ou desligar uma preferencia com efeito imediato: notificacoes, modo escuro, um recurso experimental. Ele e a metafora de uma chave liga/desliga, diferente do checkbox dentro de um formulario que so aplica a mudanca ao confirmar.

Quando nao usar

Nao use switch dentro de um formulario que so aplica a mudanca ao confirmar: use Checkbox. Nao use switch para selecao unica entre tres ou mais opcoes: isso e toggle-group (quando existir) ou radio-group.

Anatomia

  • Switch (data-slot="switch"): a raiz interativa, com role="switch" herdado do Radix.
  • switch-thumb (data-slot="switch-thumb"): o circulo que desliza entre os dois lados da trilha.
  • switch-mixed-indicator (data-slot="switch-mixed-indicator"): so existe quando mixed esta ativo, um traco central que substitui o thumb, replicando o icone do Switch legado.

Rotulo nao faz parte do componente, assim como no Checkbox. Componha com um <label> ou use aria-label quando nao houver texto visivel.

Decisao sobre o estado misto

O Switch legado do Hub tinha tres estados (on, off, mixed), com um icone de traco no misto. O Switch do Radix, ao contrario do Checkbox, so modela checked como booleano: nao existe um terceiro estado nativo equivalente ao indeterminate do checkbox.

Duas saidas eram possiveis: reportar que o misto nao sobrevive a migracao, ou reconstruir o misto por cima do primitivo sem abrir mao do Radix como base. Escolhemos a segunda. A prop mixed e puramente visual: quando verdadeira, o componente inclui aria-checked="mixed" no conjunto de props passado ao Root (o Radix monta o proprio aria-checked antes de espalhar o restante das props recebidas, entao a chave so existe quando mixed for verdadeiro, nunca como undefined, senao apagaria o valor correto do Radix quando o switch nao esta misto) e troca o thumb pelo traco central. O estado interno on/off do Radix continua existindo por baixo do misto: assim que o usuario interage, o Switch resolve para um dos dois lados, o mesmo comportamento que o Checkbox ja tem quando sai do indeterminado.

Acessibilidade

role="switch" e aria-checked (incluindo "mixed") chegam corretos ao leitor de tela sem configuracao adicional. O componente funciona por teclado: Tab foca, Espaco alterna. Estado desabilitado usa o atributo disabled nativo, nunca so opacidade. Todo Switch sem texto visivel ao lado precisa de aria-label.

Slots e tokens

Todo elemento renderizado carrega um data-slot para estilizar partes internas sem depender de classe da biblioteca. Os tokens listados são extraídos do código fonte.

[data-slot="switch"][data-slot="switch-mixed-indicator"][data-slot="switch-thumb"]
8 tokens usados
bg-backgroundbg-primaryborder-transparentoutline-nonering-offset-2ring-offset-backgroundring-ringshadow-none