nili/ui
All components

Switch

Overview
5 exports2 variant axes23 props4 files
import { Switch } from '@nili/ui';

This is the library’s own overview page, rendered live. Switch the language or the theme in the header and it follows.

States

A switch takes effect immediately — if the change needs a Save button, you want a Checkbox. onCheckedChange fires with the new state; the raw event is still there as onInputChange when you genuinely need it.

import { Switch } from "@nili/ui"

export function Example() {
  const [enabled, setEnabled] = useState(true)

  return (
    <>
      <Switch label={t('states.off')} />
      <Switch label={t('states.on')} defaultChecked />
      <Switch
        label="Controlled"
        checked={enabled}
        onCheckedChange={setEnabled}
      />
      <Switch label={t('states.disabled')} disabled />
      <Switch label={t('states.disabledOn')} disabled defaultChecked />
    </>
  )
}

The label row

The same four slots as Checkbox and Radio — sublabel, badge, description, linkButton — so a settings list built from all three lines up.

(optional)
(recommended)SecureWe will ask for a code from your authenticator app at every sign-in.Set up a new device
import { Switch, Badge, LinkButton } from "@nili/ui"

export function Example() {
  return (
    <Switch
      defaultChecked
      label="Two-factor authentication"
      sublabel="(recommended)"
      badge={<Badge size="small" color="green" appearance="lighter">Secure</Badge>}
      description="We will ask for a code from your authenticator app at every sign-in."
      linkButton={<LinkButton href="#" size="sm">Set up a new device</LinkButton>}
    />
  )
}

Label position

In a settings list the switch usually sits at the end of the row, away from the text. Logical, so it follows reading direction.

labelPosition is start
labelPosition is end — the default
import { Switch } from "@nili/ui"

export function Example() {
  return (
    <>
      <Switch label="Switch after the label" labelPosition="start" />
      <Switch label="Switch before the label" labelPosition="end" />
    </>
  )
}

Without a label

Give a bare switch an aria-label — a toggle with no name is announced as “switch” and nothing else.

import { Switch } from "@nili/ui"

export function Example() {
  return <Switch aria-label="Dark mode" />
}

In a settings list

The usual shape: a row of switches with descriptions, label first and control at the end.

Product updates and security alerts.
On this device only.
A summary every Monday morning.
import { Switch } from "@nili/ui"

export function Example() {
  return (
    <div className="divide-y divide-soft-200 rounded-xl border border-soft-200">
      <div className="p-4">
        <Switch
          labelPosition="start"
          label="Email notifications"
          description="Product updates and security alerts."
          defaultChecked
        />
      </div>
      …
    </div>
  )
}