Docs
Switch

Switch

A Switch component that allows a user to toggle between checked and not checked.

Installation

Copy and paste the following code into your component.

import * as React from "react";
import styles from "./switch.module.css";

export interface SwitchProps
  extends React.InputHTMLAttributes<HTMLInputElement> {
  onCheckedChange: (checked: boolean) => void;
  checked?: boolean | undefined;
  id?: string;
}

const SWITCH_NAME = "Switch";

const Switch = React.forwardRef<HTMLInputElement, SwitchProps>(
  ({ className, onCheckedChange, checked = false, id, ...props }, ref) => {
    const [isFocused, setIsFocused] = React.useState(false);
    // We only want to handle the enter key when the Switch is focused,
    // this prevents bubbling issues when Switch is a form field
    const handleFocus = () => {
      setIsFocused(true);
    };

    const handleBlur = () => {
      setIsFocused(false);
    };

    const handleButtonClick = () => {
      onCheckedChange(!checked);
    };

    const handleKeyDown = (event: React.KeyboardEvent<HTMLButtonElement>) => {
      if (event.key === "Enter") {
        event.preventDefault();
        handleButtonClick();
      }
    };
    return (
      <span className={styles.switchContainer}>
        <button
          role='switch'
          onFocus={handleFocus}
          onBlur={handleBlur}
          onClick={isFocused ? handleButtonClick : undefined}
          onKeyDown={handleKeyDown}
          aria-checked={checked}
          aria-required={props.required}
          data-state={checked}
          data-disabled={props.disabled ? "" : undefined}
          disabled={props.disabled}
          tabIndex={0}
          className={styles.switchTrack}>
          <div className={styles.switchThumb} />
        </button>
        <input
          type='checkbox'
          className={styles.switchInput}
          checked={checked}
          onChange={(e) => onCheckedChange(e.target.checked)}
          ref={ref}
          aria-hidden
          tabIndex={-1}
          id={id}
          {...props}
        />
      </span>
    );
  }
);

Switch.displayName = SWITCH_NAME;

export { Switch };

Copy and paste the following CSS into a .module.css file.

.switchContainer {
  border: 2px solid transparent;
  cursor: pointer;
  display: inline-block;
  height: 1.5rem;
  position: relative;
  width: 2.75rem;
}

.switchTrack {
  background-color: hsl(var(--input));
  border-radius: 12px;
  bottom: 0;
  left: 0;
  outline-offset: 2px;
  position: absolute;
  right: 0;
  top: 0;
  transition: background-color 0.3s ease;
}

.switchTrack:disabled {
  opacity: 0.5;
}

.switchTrack[aria-checked="true"] {
  background-color: hsl(var(--primary));
}

.switchTrack[aria-checked="true"] .switchThumb {
  transform: translateX(1.125rem);
}

.switchTrack:focus {
  outline: 2px solid hsl(var(--secondary));
}

.switchThumb {
  background: hsl(var(--background));
  border-radius: 50%;
  height: 1.125rem;
  top: 1px;
  left: 2px;
  position: absolute;
  transition: transform 0.3s ease;
  width: 1.125rem;
}

.switchInput {
  cursor: pointer;
  height: 100%;
  opacity: 0;
  position: absolute;
  width: 100%;
}

Update the import paths to match your project setup.

Usage

import { Switch } from "@/components/ui/switch";
<Switch id='optOut' checked={true} onCheckedChange={() => {}} />

Examples

Form Switch

This is the name of your project.

Only People you send a link to can view your project.