Gecko UIGecko UI

Switch

Toggle switch component with multiple sizes built on HeadlessUI

Switch

A toggle component built on HeadlessUI that provides an accessible on/off control. Supports multiple sizes, controlled and uncontrolled modes, and integrates seamlessly with forms.

Installation

import { Switch } from '@geckoui/geckoui';

Basic Usage

Enable notifications
import { useState } from 'react';

function Example() {
  const [enabled, setEnabled] = useState(false);

  return (
    <Switch checked={enabled} onChange={setEnabled} />
  );
}

Props API

PropTypeDefaultDescription
checkedboolean-Controlled checked state
onChange(checked: boolean) => void-Callback when state changes
size'sm' | 'md''md'Size of the switch
classNamestring-CSS class for the switch container
thumbClassNamestring-CSS class for the switch thumb
disabledbooleanfalseDisable the switch
defaultCheckedboolean-Initial checked state (uncontrolled)

Examples

Sizes

Small
Medium (default)
<div className="flex flex-col gap-4">
  <Switch size="sm" checked={enabled} onChange={setEnabled} />
  <Switch size="md" checked={enabled} onChange={setEnabled} />
</div>

Settings Panel

Email Notifications
Receive email updates
Dark Mode
Use dark theme
Analytics
Share anonymous usage data
function SettingsPanel() {
  const [settings, setSettings] = useState({
    notifications: true,
    darkMode: false,
    analytics: true,
  });

  return (
    <div className="space-y-4">
      <div className="flex items-center justify-between">
        <div>
          <div className="font-medium">Email Notifications</div>
          <div className="text-sm text-gray-500">Receive email updates</div>
        </div>
        <Switch
          checked={settings.notifications}
          onChange={(checked) =>
            setSettings({ ...settings, notifications: checked })
          }
        />
      </div>
      {/* More settings... */}
    </div>
  );
}

Disabled State

<div className="flex gap-4">
  <Switch checked disabled />
  <Switch disabled />
</div>

Uncontrolled with Default Value

Enable notifications
<Switch defaultChecked={true} />

Keyboard Navigation

The switch supports keyboard interaction:

  • Space or Enter: Toggle the switch
  • Tab: Move focus to next element
  • Shift + Tab: Move focus to previous element

Note: The Enter key is prevented from default form submission behavior.

Module Augmentation

The Switch component supports TypeScript module augmentation, allowing you to add custom sizes with full type safety.

Live Example

This documentation site demonstrates module augmentation with a custom lg size:

Small
Medium (default)
Large (custom)

Step 1: TypeScript Declaration

Create a declaration file (e.g., gecko.d.ts) in your project:

import "@geckoui/geckoui";

declare module "@geckoui/geckoui" {
  interface SwitchSizeMap {
    lg: unknown;
  }
}

Step 2: Add CSS Styles

Add the corresponding styles to your global CSS/SCSS file. You need to define both the container size and the thumb element:

.GeckoUISwitch {
  &--size-lg {
    @apply h-8 w-14;
  }

  &__thumb {
    &--size-lg {
      @apply w-6 translate-x-0.5 group-data-[checked]:translate-x-3.5;
    }
  }
}

Step 3: Use Your Custom Size

<Switch size="lg" checked={enabled} onChange={setEnabled} />

Accessibility

  • Built on HeadlessUI for WCAG compliance
  • Proper ARIA attributes automatically applied
  • Fully keyboard navigable
  • Focus visible for keyboard users
  • Works with screen readers
  • Disabled state properly communicated

Styling

The component uses BEM-style class names:

  • GeckoUISwitch - Main container
  • GeckoUISwitch--size-{sm|md} - Size modifiers
  • GeckoUISwitch__thumb - Toggle thumb element
  • GeckoUISwitch__thumb--size-{sm|md} - Thumb size modifiers

The switch also supports HeadlessUI data attributes:

  • data-[checked] - Applied when checked
  • data-[disabled] - Applied when disabled

Dependencies

This component uses @headlessui/react for accessibility and behavior.

  • Checkbox - For multi-select options
  • Radio - For mutually exclusive selections
  • RHFSwitch - React Hook Form integration