Files
skills/docs/ui/react/react-ui/src/components/switch/switch.md
2026-05-29 08:20:56 +01:00

5.9 KiB
Raw Blame History

Switch

(no submodules)

- switch.variants — `switchVariants` and `switchThumb…
  • switch.variants — switchVariants and switchThumbVariants are the two cva (class-variance-authority) configurations that together powe…

  • switch.variants — switchVariants and `switchThumb…

  • switch.variants — switchVariants and switchThumbVariants are the two cva (class-variance-authority) configurations that together powe…

  • switch.variants — switchVariants and `switchThumb…

  • switch.variants — switchVariants and switchThumbVariants are the two cva (class-variance-authority) configurations that together powe…

  • switch.variants — switchVariants and `switchThumb…

  • switch.variants — switchVariants and switchThumbVariants are the two cva (class-variance-authority) configurations that together powe…

  • switch.variants — switchVariants and switchThumbVariants are the two cva (class-variance-authority) configurations that together powe…

Purpose

<Switch> is the chassis on/off toggle primitive built on @radix-ui/react-switch. Radix supplies the a11y semantics (role="switch", aria-checked reflecting boolean state, native Space activation, disabled propagation); the chassis layers theme-driven variant resolution, the sliding-thumb render, and the cva size axis that scales both the track and the thumb proportionally.

The thumb cva is exported alongside the track cva so consumers can theme each independently. Refs are forwarded to the Radix Root which renders a styled <button>.

Icon-only switches (no visible label sibling) MUST supply an aria-label so screen readers can announce what is being toggled. The chassis does NOT inject a fallback because the label is domain-specific — only the consumer knows what is being switched on or off.

Features

  • Three sizes (sm, default, lg) scaling track + thumb proportionally.
  • Sliding thumb with data-[state=checked]:translate-x-* driving the on/off motion via Tailwind transforms.
  • Controlled and uncontrolled use via Radix checked / defaultChecked / onCheckedChange.
  • disabled blocks pointer + keyboard input and decays opacity.
  • data-state="checked|unchecked" mirrored on the rendered button.
  • Refs forwarded to the Radix Root.
  • motion-reduce:transition-none collapses both colour + transform transitions for prefers-reduced-motion: reduce.
  • Theme-driven variant overrides via useThemedVariants("Switch", switchVariants).

Usage: Basic Example

import { Switch } from "@suaveplan/react-ui";

export function AirplaneToggle() {
    return (
        <div className="flex items-center gap-2">
            <Switch id="airplane" />
            <label htmlFor="airplane">Airplane mode</label>
        </div>
    );
}

Usage: Advanced Example

import { Switch } from "@suaveplan/react-ui";
import { useState } from "react";

export function NotificationSettings() {
    const [enabled, setEnabled] = useState(true);
    const [marketing, setMarketing] = useState(false);

    return (
        <div className="flex flex-col gap-3 p-4 border rounded">
            <div className="flex items-center justify-between">
                <label htmlFor="notif">Notifications</label>
                <Switch
                    id="notif"
                    checked={enabled}
                    onCheckedChange={setEnabled}
                />
            </div>
            <div className="flex items-center justify-between">
                <label htmlFor="marketing">Marketing emails</label>
                <Switch
                    id="marketing"
                    checked={marketing}
                    disabled={!enabled}
                    onCheckedChange={setMarketing}
                />
            </div>
        </div>
    );
}

API Reference

<Switch>

forwardRef<ComponentRef<typeof SwitchPrimitive.Root>, SwitchProps> — wraps Radix Root, renders a <button role="switch"> containing the sliding thumb.

SwitchProps

Inherits every prop from Radix SwitchPrimitive.Root except asChild. Adds:

Prop Type Default Description
size "sm" | "default" | "lg" "default" Visual variant scaling track + thumb.

Common Radix props consumers will use:

Prop Type Default Description
checked boolean uncontrolled Controlled state.
defaultChecked boolean false Initial state for uncontrolled use.
onCheckedChange (checked: boolean) => void none Fires on state change.
disabled boolean false Blocks input + decays opacity.
required boolean false Native form-field required.
name string none Native form-field name.
value string "on" Native form-field value when checked.

switchVariants / switchThumbVariants

Both bare cva resolvers are exported so external consumers can re-use the variants directly.

Implementation Notes

  • The track and thumb cva configs are kept separate so consumer themes can override either independently — for example a theme that makes the thumb glossy without changing the track shape.
  • The thumb's translate-x-* per-size value is hard-coded into switchThumbVariants rather than computed because cva is a string-templating library, not a runtime calculator. The math is track-width − thumb-width − padding-x*2.
  • motion-reduce:transition-none applies to both the track (colour transition) and the thumb (transform transition) so reduced-motion users see instant state changes.
  • Refs target the Radix Root (the <button> element) — consumers can .focus() the switch programmatically through the forwarded ref.
  • The chassis does NOT auto-inject an aria-label for icon-only use — see Purpose.