KDS
Forms

Toggle

Botão único com estado on/off — formatação, modos de visualização, filtros.

Overview

Toggle é um botão de duas posições — aria-pressed=true|false. Use para estado de ação fora de form: bold/italic em editor de texto, modo grade vs. lista, chips de filtro ativável.

A diferença em relação a Switch é semântica: Switch é configuração persistida (notificações, dark mode). Toggle é estado de comando ou filtro — visualmente um botão, com efeito agora. Para form-bound boolean, use Checkbox.

Preview
Toggle de formatação (Bold).

Anatomy

<Toggle variant="default" | "outline" size="sm" | "default" | "lg">
  ├─ [data-state="on" | "off"]
  └─ <icon /> | <text />
</Toggle>

Usage

import { Toggle } from "@kalvner/kds/forms/toggle";
import { Bold } from "lucide-react";

export function BoldToggle({ pressed, onPressedChange }) {
  return (
    <Toggle
      pressed={pressed}
      onPressedChange={onPressedChange}
      aria-label="Negrito"
    >
      <Bold />
    </Toggle>
  );
}

Props

PropTipoDefaultDescrição
pressedbooleanControlado.
defaultPressedbooleanfalseNão controlado.
onPressedChange(v: boolean) => voidCallback.
variant'default' | 'outline''default'Aparência.
size'sm' | 'default' | 'lg''default'h-8 / h-9 / h-10.
disabledbooleanfalseBloqueia interação.
aria-labelstringObrigatório quando só ícone.

Subcomponents

Toggle é monolítico. Para grupos coordenados, use ToggleGroup, que aplica variant e size a todos os filhos via context.

Variants

Default vs. Outline
Outline aparece com borda, útil em barras de formatação.
Sizes
sm para toolbar densa, default padrão, lg para destaque.

States

EstadoComportamento
data-state=offBackground transparente (variants default + outline).
data-state=onBackground accent, texto accent-foreground.
disabledPointer-events none, opacity 50%.

Composition

Toggles individuais raramente aparecem sozinhos. Padrões:

  • Em editor de texto, agrupe via ToggleGroup type="multiple" para combinar formatações.
  • Como chip de filtro, use Toggles soltos (cada filtro é independente).
  • Em alternância exclusiva (ex.: alinhamento), use ToggleGroup type="single".
<ToggleGroup type="multiple" aria-label="Formatação">
  <ToggleGroupItem value="bold"><Bold /></ToggleGroupItem>
  <ToggleGroupItem value="italic"><Italic /></ToggleGroupItem>
  <ToggleGroupItem value="underline"><Underline /></ToggleGroupItem>
</ToggleGroup>

When to use

  • Editores rich-text (B, I, U).
  • Alternar modos de visualização (grade ↔ lista).
  • Chips de filtro ativável (independentes).
  • Botões de menu de visualização (mostrar grade, ocultar barra).

When not to use

  • Configuração persistida — use Switch.
  • Valor de form bound — use Checkbox.
  • Navegação — use Link ou Tabs.
  • Múltiplos toggles relacionados que devem coordenar — use ToggleGroup.

Best practices

  • aria-label é obrigatório quando o botão só tem ícone. Sem isso, leitor de tela diz "botão" e nada mais.
  • Pareie ícone + texto quando o significado não é universalmente claro (não confie só em "B" sem contexto).
  • Para action commands não-stateful (Save, Delete), use Button, não Toggle.
  • Tamanho sm em toolbars densas; default em painéis amplos.

Accessibility

ConcernComportamento
Rolebutton com aria-pressed (não checkbox).
KeyboardSpace/Enter alterna.
Focusfocus-visible:ring-[3px] (3px ring no token).
Labelaria-label obrigatório quando só ícone.
Disableddisabled remove do tab order; pointer-events none.
EstadoLeitor de tela anuncia "pressionado" / "não pressionado".
  • ToggleGroup — múltiplos coordenados.
  • Switch — configuração persistida (efeito imediato).
  • Checkbox — valor bound a form.
  • Button — ação sem estado.

On this page