Switch
BetaPrende o apaga una preferencia con efecto inmediato, sin botón de guardar.
registry/ds/switch.tsximport { Switch } from "@/registry/ds/switch";
export default function SwitchBasic() {
return <Switch defaultChecked label="Notificaciones por correo" />;
}Cuándo usarlo
La prueba es simple: ¿el cambio se aplica al instante? Si sí, es un Switch. Si hay que apretar "Guardar", es un Checkbox.
| Usá Switch para… | Usá otra cosa para… |
|---|---|
| Preferencias que se aplican ya: notificaciones, modo oscuro. | Opciones de un formulario que se envía → Checkbox. |
| Activar o desactivar una función. | Elegir entre dos cosas distintas (no on/off) → Radio. |
| Filas de configuración. | Aceptar términos → Checkbox. |
Con texto de apoyo
import { Switch } from "@/registry/ds/switch";
export default function SwitchSupporting() {
return (
<div className="flex flex-col gap-4">
<Switch defaultChecked label="Modo enfoque" supporting="Silencia los avisos mientras rendís un examen." />
<Switch label="Perfil público" supporting="Otros estudiantes pueden ver tu nombre y carrera." />
<Switch disabled label="Verificación en dos pasos" supporting="La administra tu institución." />
</div>
);
}Tamaños
import { Switch } from "@/registry/ds/switch";
export default function SwitchSizes() {
return (
<div className="flex flex-wrap items-start gap-8">
<Switch size="sm" defaultChecked label="Small" />
<Switch size="md" defaultChecked label="Medium" />
<Switch size="lg" defaultChecked label="Large" />
</div>
);
}Contenido
- El label nombra la cosa que se prende, no la acción: "Notificaciones por correo", no "Activar notificaciones".
- El label no cambia según el estado. El switch ya dice si está prendido.
- Si el cambio puede fallar (red), volvé el switch a su estado anterior y avisá con un Toast — nunca lo dejes mintiendo.
Medidas
| Size | Pista | Thumb | Recorrido | Padding |
|---|---|---|---|---|
sm | 28 × 16 | 12 | 12 | spacing-xxs 2 |
md | 36 × 20 | 16 | 16 | spacing-xxs 2 |
lg | 44 × 24 | 20 | 20 | spacing-xxs 2 |
Radio radius-full. Transición: duration/fast (200 ms) con easing move;
sin animación con prefers-reduced-motion.
Tokens por estado
| Parte | Propiedad | Default | Hover | Pressed |
|---|---|---|---|---|
| Pista apagada | Fondo | border/strong | icon/subtle | icon/subtle |
| Pista prendida | Fondo | primary/solid | primary/solid-hover | primary/solid-active |
| Thumb | Fondo | primary/on-solid | primary/on-solid | primary/on-solid |
| Parte | Propiedad | Token |
|---|---|---|
| Thumb | Sombra | Elevation/xs |
| Foco | Anillo 2 px, separado 2 px | focus/ring |
| Deshabilitado | Opacidad del control | opacity-disabled |
La pista apagada usa border/strong (no un gris más claro) para llegar a 3:1
contra el fondo: el estado apagado también tiene que verse.
Instalación
npx shadcn@latest add https://polen.cdc.cool/r/switch.jsonPlayground
Configurá el componente y copiá el snippet: se genera del mismo estado que renderiza el preview.
size
<Switch label="Notificaciones por correo" defaultChecked />Ejemplos
import { Switch } from "@/registry/ds/switch";
export default function SwitchSupporting() {
return (
<div className="flex flex-col gap-4">
<Switch defaultChecked label="Modo enfoque" supporting="Silencia los avisos mientras rendís un examen." />
<Switch label="Perfil público" supporting="Otros estudiantes pueden ver tu nombre y carrera." />
<Switch disabled label="Verificación en dos pasos" supporting="La administra tu institución." />
</div>
);
}Props
Sobre Base UI Switch.
| Prop | Tipo | Default | Descripción |
|---|---|---|---|
size | "sm" | "md" | "lg" | "md" | Pista de 28×16 / 36×20 / 44×24. |
label | ReactNode | — | Nombre de la preferencia. Sin label, pasá aria-label. |
supporting | ReactNode | — | Línea de apoyo. |
checked | boolean | — | Valor controlado. |
defaultChecked | boolean | false | Valor inicial. |
onCheckedChange | (checked: boolean) => void | — | Se llama al cambiar — acá va el guardado. |
disabled | boolean | false | Bloquea la interacción. |
Teclado
| Tecla | Qué hace |
|---|---|
| Tab | Mueve el foco al switch. |
| Espacio | Prende o apaga. |
| Enter | Prende o apaga. |
Qué viene resuelto
role="switch"conaria-checked.- Label asociado y clickeable.
- El estado no depende solo del color: el thumb cambia de posición.
Qué tenés que cuidar vos
- Sin
label, pasáaria-label. - Si el guardado es asíncrono y falla, revertí el estado y explicá por qué.