Skip to content

Toggle ​

A sleek toggle switch component for binary on/off states. Supports labels, descriptions, icons, validation states, and full reactivity. Perfect for settings, preferences, and feature toggles. Built for Pulse Framework with complete accessibility support.

Import ​

tsx
import { Toggle, Pulse } from '@odyssee-software/components';

Basic Usage ​

Code Éditable
Résultat

With Description ​

Add helpful descriptions below the toggle label.

Code Éditable
Résultat

Sizes ​

Four size options control the toggle size: xs, sm, md, and lg.

Code Éditable
Résultat

Variants ​

The Toggle component supports two variants: default and soft.

Code Éditable
Résultat

With Icons ​

Show check/cross icons inside the toggle.

Code Éditable
Résultat

Required Field ​

Mark toggles as required with visual indicators.

Code Éditable
Résultat

With Error State ​

Display validation errors.

Code Éditable
Résultat

With Success State ​

Show success feedback.

Code Éditable
Résultat

Disabled State ​

Disable toggles when they cannot be interacted with.

Code Éditable
Résultat

Label Position ​

Control label placement with the labelPosition prop.

Code Éditable
Résultat

Reactive Value ​

Control toggle state with Pulse signals.

tsx
const isDarkMode = Pulse.signal(false);

const reactiveToggle = (
  <div>
    <Toggle
      label="Dark Mode"
      description="Switch between light and dark theme"
      checked={isDarkMode}
      onChange={(checked) => isDarkMode(checked)}
    />
    
    <div class="mt-4">
      <p class="text-sm text-gray-600">
        Theme: {isDarkMode() ? 'Dark 🌙' : 'Light ☀️'}
      </p>
    </div>
  </div>
);

Settings Panel ​

Create organized settings with multiple toggles.

tsx
const SettingsPanel = () => {
  const settings = Pulse.signal({
    notifications: true,
    autoSave: true,
    twoFactor: false,
    newsletter: false
  });

  return (
    <div class="space-y-4">
      <h3 class="text-lg font-semibold mb-3">Account Settings</h3>
      
      <Toggle
        label="Push Notifications"
        description="Receive push notifications on your devices"
        checked={settings().notifications}
        onChange={(checked) => 
          settings({ ...settings(), notifications: checked })
        }
      />
      
      <Toggle
        label="Auto-save"
        description="Automatically save your work"
        checked={settings().autoSave}
        onChange={(checked) => 
          settings({ ...settings(), autoSave: checked })
        }
      />
      
      <Toggle
        label="Two-factor Authentication"
        description="Add an extra layer of security"
        checked={settings().twoFactor}
        onChange={(checked) => 
          settings({ ...settings(), twoFactor: checked })
        }
      />
      
      <Toggle
        label="Newsletter Subscription"
        description="Receive our weekly newsletter"
        checked={settings().newsletter}
        onChange={(checked) => 
          settings({ ...settings(), newsletter: checked })
        }
      />
    </div>
  );
};

Dependent Toggles ​

Create toggles that enable/disable other options.

tsx
const DependentToggles = () => {
  const emailNotifications = Pulse.signal(true);
  const emailTypes = Pulse.signal({
    marketing: false,
    updates: true,
    security: true
  });

  return (
    <div class="space-y-4">
      <Toggle
        label="Email Notifications"
        description="Master toggle for all email notifications"
        checked={emailNotifications}
        onChange={(checked) => emailNotifications(checked)}
        size="lg"
      />
      
      <div class="ml-6 space-y-3">
        <Toggle
          label="Marketing Emails"
          description="Promotional content and offers"
          checked={emailTypes().marketing}
          disabled={!emailNotifications()}
          onChange={(checked) => 
            emailTypes({ ...emailTypes(), marketing: checked })
          }
        />
        
        <Toggle
          label="Product Updates"
          description="News about new features"
          checked={emailTypes().updates}
          disabled={!emailNotifications()}
          onChange={(checked) => 
            emailTypes({ ...emailTypes(), updates: checked })
          }
        />
        
        <Toggle
          label="Security Alerts"
          description="Important security notifications"
          checked={emailTypes().security}
          disabled={!emailNotifications()}
          onChange={(checked) => 
            emailTypes({ ...emailTypes(), security: checked })
          }
        />
      </div>
    </div>
  );
};

Form Validation ​

Integrate with form validation.

tsx
const ConsentForm = () => {
  const consent = Pulse.signal(false);
  const error = Pulse.signal('');

  const handleSubmit = (e: Event) => {
    e.preventDefault();
    
    if (!consent()) {
      error('You must accept the terms to continue');
      return;
    }
    
    error('');
    console.log('Form submitted!');
  };

  return (
    <form onsubmit={handleSubmit} class="space-y-4">
      <Toggle
        label="I agree to the terms and conditions"
        description="By enabling this, you accept our terms of service"
        checked={consent}
        onChange={(checked) => {
          consent(checked);
          if (checked) error('');
        }}
        error={error()}
        required
      />
      
      <Button type="submit">
        Continue
      </Button>
    </form>
  );
};

Props ​

PropTypeDefaultDescription
checkedboolean | Signal<boolean>falseChecked state
labelstring-Toggle label
descriptionstring-Helper text below label
errorstring-Error message
successstring-Success message
size"xs" | "sm" | "md" | "lg""md"Toggle size
variant"default" | "soft""default"Visual style
showIconsbooleanfalseShow check/cross icons
labelPosition"left" | "right""right"Label position
disabledbooleanfalseDisable toggle
requiredbooleanfalseMark as required
namestring-Form field name
onChange(checked: boolean) => void-Change event handler
classNamestring-Additional CSS classes
idstringAuto-generatedHTML id attribute

Accessibility ​

The Toggle component follows accessibility best practices:

  • ✅ Uses checkbox input with proper role
  • ✅ Keyboard navigation support (Space to toggle)
  • ✅ Focus management with visible focus ring
  • ✅ Screen reader friendly labels
  • ✅ ARIA attributes for states
  • ✅ Required field indicators
  • ✅ Clear visual state feedback

Keyboard Navigation ​

  • Space: Toggle on/off
  • Tab: Move to next element
  • Shift + Tab: Move to previous element

ARIA Attributes ​

tsx
const accessibleToggle = (
  <Toggle
    label="Dark Mode"
    aria-label="Enable dark mode"
    aria-describedby="dark-mode-hint"
  />
);

Best Practices ​

✅ Do ​

  • Use toggles for binary on/off states
  • Provide clear, concise labels
  • Add descriptions for complex options
  • Show immediate feedback on toggle
  • Use appropriate sizes for context
  • Group related toggles together
tsx
// Good: Clear label with helpful description
const goodToggle = (
  <Toggle
    label="Enable two-factor authentication"
    description="Adds an extra layer of security to your account"
    onChange={handleToggle}
  />
);

❌ Don't ​

  • Don't use for choices between options (use radio buttons)
  • Don't use for multiple selections (use checkboxes)
  • Don't require confirmation for toggle changes
  • Don't hide important state changes
  • Don't use vague labels
tsx
// Bad: Vague label, unclear what happens
const badToggle = (
  <Toggle label="Enable" />
);

// Better: Clear label explaining the action
const betterToggle = (
  <Toggle
    label="Enable email notifications"
    description="Receive updates via email"
  />
);

Use Cases ​

Dark Mode Toggle ​

tsx
const DarkModeToggle = () => {
  const isDark = Pulse.signal(false);

  return (
    <Toggle
      label="Dark Mode"
      description="Switch between light and dark theme"
      showIcons={true}
      checked={isDark}
      onChange={(checked) => {
        isDark(checked);
        document.body.classList.toggle('dark', checked);
      }}
    />
  );
};

Feature Flags ​

tsx
const FeatureFlags = () => (
  <div class="space-y-3">
    <Toggle
      label="Beta Features"
      description="Enable experimental features"
    />
    <Toggle
      label="Analytics"
      description="Help us improve by sharing usage data"
    />
  </div>
);

Privacy Settings ​

tsx
const PrivacySettings = () => (
  <div class="space-y-3">
    <Toggle
      label="Profile Visibility"
      description="Make your profile visible to others"
    />
    <Toggle
      label="Show Email"
      description="Display your email on your profile"
    />
  </div>
);

Styling & Theming ​

All toggle styles use Tailwind CSS classes and support dark mode automatically.

Custom Styling ​

tsx
const customToggle = (
  <Toggle
    className="custom-toggle"
    label="Custom styled toggle"
  />
);

TypeScript ​

Full TypeScript support with complete type definitions:

tsx
import type { ToggleProps } from '@odyssee-software/components';

const props: ToggleProps = {
  label: 'Enable feature',
  checked: false,
  showIcons: true,
  onChange: (checked: boolean) => {
    console.log('Toggled:', checked);
  }
};

const toggle = <Toggle {...props} />;

Version: 1.0.0
Last Updated: January 2025

Released under the MIT License.