Menu

Site and documentation links

Search documentation

Type to filter pages and sections. Use the arrow keys to move and Enter to open.

    Switch

    A control that turns a setting on or off.

    View code
    import { Switch, SwitchThumb } from '@syncclouds/ui'
    
    export function SwitchDemo() {
      return (
        <div className="flex items-center gap-3">
          <Switch id="email-alerts" defaultChecked>
            <SwitchThumb />
          </Switch>
          <label htmlFor="email-alerts">Email me when a deploy fails</label>
        </div>
      )
    }

    Installation

    npm install @syncclouds/ui

    Usage

    import { Switch, SwitchThumb } from '@syncclouds/ui'
    <Switch id="alerts" defaultChecked>
      <SwitchThumb />
    </Switch>
    <label htmlFor="alerts">Email alerts</label>

    Anatomy

    Switch
    └── SwitchThumb

    Controlled

    Autosave is off.

    View code
    'use client'
    
    import { useState } from 'react'
    import { Switch, SwitchThumb } from '@syncclouds/ui'
    
    export function SwitchControlled() {
      const [autosave, setAutosave] = useState(false)
    
      return (
        <div className="flex flex-col items-center gap-4">
          <div className="flex items-center gap-3">
            <Switch id="autosave" checked={autosave} onCheckedChange={setAutosave}>
              <SwitchThumb />
            </Switch>
            <label htmlFor="autosave">Autosave</label>
          </div>
          <p className="text-sm">Autosave is {autosave ? 'on' : 'off'}.</p>
        </div>
      )
    }

    Disabled

    View code
    import { Switch, SwitchThumb } from '@syncclouds/ui'
    
    export function SwitchDisabled() {
      return (
        <div className="flex flex-col gap-4">
          <div className="flex items-center gap-3">
            <Switch id="sso" disabled defaultChecked>
              <SwitchThumb />
            </Switch>
            <label htmlFor="sso">Single sign-on (set by your admin)</label>
          </div>
          <div className="flex items-center gap-3">
            <Switch id="beta" disabled>
              <SwitchThumb />
            </Switch>
            <label htmlFor="beta">Beta features (on paid plans)</label>
          </div>
        </div>
      )
    }

    With a description

    Point aria-describedby at the hint so screen readers read it after the name.

    A summary of deploys and errors, every Monday morning.

    View code
    import { Switch, SwitchThumb } from '@syncclouds/ui'
    
    /* aria-describedby lets screen readers read the hint after the name. */
    export function SwitchDescription() {
      return (
        <div className="flex max-w-sm items-start justify-between gap-6">
          <div className="flex flex-col gap-1">
            <label htmlFor="weekly-digest" className="font-semibold">
              Weekly digest
            </label>
            <p id="weekly-digest-hint" className="text-sm opacity-80">
              A summary of deploys and errors, every Monday morning.
            </p>
          </div>
          <Switch id="weekly-digest" aria-describedby="weekly-digest-hint" defaultChecked>
            <SwitchThumb />
          </Switch>
        </div>
      )
    }

    Without the theme

    View code
    import { Switch, SwitchThumb } from '@syncclouds/ui'
    
    export function SwitchUnstyled() {
      return (
        <div className="flex items-center gap-3">
          <Switch
            id="dark-mode-unstyled"
            className="flex h-6 w-11 cursor-pointer items-center rounded-full bg-zinc-400 p-0.5 transition-colors focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600 data-[state=checked]:bg-indigo-600 dark:bg-zinc-600 dark:data-[state=checked]:bg-indigo-400"
          >
            <SwitchThumb className="block size-5 rounded-full bg-white shadow transition-transform data-[state=checked]:translate-x-5" />
          </Switch>
          <label htmlFor="dark-mode-unstyled" className="text-sm text-zinc-900 dark:text-zinc-100">
            Dark mode
          </label>
        </div>
      )
    }

    Accessibility

    Follows the WAI-ARIA Switch pattern.

    KeysWhat they do
    Space, EnterTurns the switch on or off.
    • Screen readers announce it as a switch that is on or off, not as a checkbox.

    API reference

    Every part also accepts the props of the element it renders, including className and ref.

    Switchrenders <button>

    A button with role="switch". Name it with a <label htmlFor> or aria-label.

    PropTypeDefaultDescription
    checkedbooleannoneWhether it is on, when you control it.
    defaultCheckedbooleanfalseWhether it starts on.
    onCheckedChange(checked: boolean) => voidnoneCalled when it is turned on or off.
    disabledbooleanfalseStops it from changing.
    asChildbooleanfalseUse your own element.
    Data attributeValues
    data-state"checked" | "unchecked"
    data-disabledpresent when disabled

    SwitchThumbrenders <span>

    The moving knob. Purely visual.

    Data attributeValues
    data-state"checked" | "unchecked"
    Built by Syncclouds. Syncclouds UI is in development.