Toggle

A switch with a spring in it. Press it and the thumb stretches toward where it's going. Let go and it lands with a bounce. Drag it and it holds back until halfway, then snaps over the middle the way a real toggle does, and gives a little past either end.

  • Wi-FiHome network
  • Bluetooth2 devices
  • AirDropContacts only

Installation

Terminalbash
npx @neelshha/ui@latest add toggle

Usage

page.tsxtsx
import { Toggle } from "@/components/ui/toggle";

<Toggle aria-label="Wi-Fi" checked={wifi} onCheckedChange={setWifi} />

It's a button with the switch role, so it needs a name: aria-label, or aria-labelledby pointing at the text beside it. A tap flips it, and so does a drag that ends past the middle. A drag that ends short of halfway springs back.

Drag it

A big one, so the detent is easy to feel. Drag the thumb slowly: it lags your finger until halfway, then jumps ahead of it.

page.tsxtsx
<Toggle
  aria-label="Airplane mode"
  style={{ "--ns-toggle-w": "4.75rem", "--ns-toggle-h": "2.75rem" }}
/>

Sizes and tones

The key tone lights the blue LED. Ink fills with the text colour.

page.tsxtsx
<Toggle aria-label="Sync" defaultChecked />
<Toggle aria-label="Sync" tone="ink" defaultChecked />
<Toggle aria-label="Sync" size="sm" defaultChecked />
<Toggle aria-label="Sync" size="sm" tone="ink" />

Keyboard

Tab to it, then Space or Enter flips it. Screen readers hear a switch that's on or off. In right-to-left text, on is to the left.

API

Other props go to the button. Its size comes from --ns-toggle-w and --ns-toggle-h. With reduced motion the thumb moves at once, with no stretch or bounce.

PropTypeDefaultDescription
checked / defaultCheckedbooleanfalseControlled or uncontrolled. onCheckedChange fires with the next state.
size"sm" | "md""md"The small one fits a dense list.
tone"key" | "ink""key"What it lights when on: the blue LED or solid ink.