Switcher

free

Switcher toggles a single setting on or off directly in place.

Preview
Dark
Email notifications

Send a summary whenever a report finishes.

import { useState } from 'react';
import Switcher from '@/components/ui/Switcher';

export default function UsageDemo() {
  const [enabled, setEnabled] = useState(true);

  return (
    <div className="flex items-center gap-4">
      <Switcher checked={enabled} onChange={setEnabled} />
      <div>
        <div className="font-medium text-foreground">
          Email notifications
        </div>
        <p className="text-muted-foreground">
          Send a summary whenever a report finishes.
        </p>
      </div>
    </div>
  );
}

Installation

Add this component with the NateUI CLI.

npx nateui@latest add Switcher

Examples

Basic

Preview
Dark
import Switcher from '@/components/ui/Switcher';

export default function BasicDemo() {
  return (
    <div className="flex items-center gap-4">
      <Switcher />
      <Switcher defaultChecked />
    </div>
  );
}

Content

Preview
Dark
import Switcher from '@/components/ui/Switcher';
import { PiMoon, PiSun } from 'react-icons/pi'

export default function ContentDemo() {
  return (
    <div className="flex items-center gap-4">
      <Switcher
        defaultChecked
        checkedContent="On"
        unCheckedContent="Off"
      />
      <Switcher
        defaultChecked
        checkedContent={<PiSun />}
        unCheckedContent={<PiMoon />}
      />
    </div>
  );
}

Custom Color

Preview
Dark
Service is live
Maintenance mode
Delete after export
import Switcher from '@/components/ui/Switcher';

export default function CustomColorDemo() {
  return (
    <div className="flex flex-col gap-4">
      <div className="flex items-center gap-4">
        <Switcher defaultChecked toggledClass="bg-success" />
        <span className="text-foreground">Service is live</span>
      </div>
      <div className="flex items-center gap-4">
        <Switcher defaultChecked toggledClass="bg-warning" />
        <span className="text-foreground">Maintenance mode</span>
      </div>
      <div className="flex items-center gap-4">
        <Switcher defaultChecked toggledClass="bg-destructive" />
        <span className="text-foreground">Delete after export</span>
      </div>
    </div>
  );
}

Loading

Preview
Dark
import { useState } from 'react';
import Switcher from '@/components/ui/Switcher';

export default function LoadingDemo() {
  const [checked, setChecked] = useState(false);
  const [isLoading, setIsLoading] = useState(false);

  const handleChange = (next: boolean) => {
    setIsLoading(true);
    setTimeout(() => {
      setChecked(next);
      setIsLoading(false);
    }, 1200);
  };

  return (
    <Switcher
      checked={checked}
      isLoading={isLoading}
      onChange={handleChange}
    />
  );
}

Disabled

Preview
Dark
import Switcher from '@/components/ui/Switcher';

export default function DisabledDemo() {
  return (
    <div className="flex items-center gap-4">
      <Switcher disabled />
      <Switcher disabled defaultChecked />
    </div>
  );
}

Controlled

Preview
Dark

State: off

import { useState } from 'react';
import Switcher from '@/components/ui/Switcher';

export default function ControlledDemo() {
  const [checked, setChecked] = useState(false);

  return (
    <div className="flex flex-col items-center gap-4">
      <div>
        <Switcher checked={checked} onChange={setChecked} />
      </div>
      <p>
        State: <span className="font-medium">{checked ? 'on' : 'off'}</span>
      </p>
    </div>
  );
}

API

Switcher renders a labelled checkbox styled as an on/off toggle. Use it uncontrolled with defaultChecked, or controlled with checked plus onChange. It also accepts native input props.

PropDescriptionTypeDefault
checkedControlled on/off state.boolean-
defaultCheckedInitial state for uncontrolled usage.boolean-
checkedContentContent shown inside the track when on.string | ReactNode-
unCheckedContentContent shown inside the track when off.string | ReactNode-
toggledClassClass applied to the track while on, used to override the on color.string'bg-primary'
isLoadingReplace the thumb with a spinner and block toggling.booleanfalse
disabledPrevent interaction and apply disabled styling.booleanfalse
readOnlyPrevent the state from changing on interaction.booleanfalse
nameName passed to the underlying input.string-
onChangeCalled with the next state and the input change event.SwitcherChangeHandler-
labelRefRef forwarded to the root label element.Ref<HTMLLabelElement>-
refRef forwarded to the underlying checkbox input.Ref<HTMLInputElement>-
...nativeInputPropsNative props for the underlying checkbox input.NativeSwitcherInputProps-

Types

type SwitcherChangeHandler = (
  checked: boolean,
  event: ChangeEvent<HTMLInputElement>,
) => void;
type NativeSwitcherInputProps = Omit<
  ComponentPropsWithRef<'input'>,
  'onChange'
>;