ExpoStartup

Toggle

A customizable toggle switch component for binary states with animation.

Toggle

The Toggle component is a switch that allows users to toggle between two states (on/off, true/false). It features a smooth animation and support for both controlled and uncontrolled usage patterns.

Features

  • Animated Transition: Smooth spring animation when toggling states
  • Controlled & Uncontrolled Modes: Can be used with or without external state management
  • Disabled State: Support for disabled/inactive state
  • Customizable Styling: Control for appearance via className
  • Dark Mode Support: Automatic light/dark mode styles

Import

import Toggle from '@/components/Toggle';

Props

PropTypeDefaultDescription
valuebooleanCurrent state of the toggle (controlled mode)
onChange(value: boolean) => voidFunction called when the toggle state changes
disabledbooleanfalseWhether the toggle is disabled
classNamestring''Additional Tailwind classes for the toggle

Usage Examples

Basic Toggle (Uncontrolled)

<Toggle />

Controlled Toggle

const [isEnabled, setIsEnabled] = useState(false);
 
<Toggle
  value={isEnabled}
  onChange={setIsEnabled}
/>

Disabled Toggle

<Toggle 
  value={true} 
  disabled={true} 
/>

Custom Styled Toggle

<Toggle 
  className="shadow-lg" 
/>

Toggle with Label

<View className="flex-row items-center">
  <Text className="mr-2">Dark Mode</Text>
  <Toggle
    value={isDarkMode}
    onChange={setIsDarkMode}
  />
</View>

Form Integration Example

const [formData, setFormData] = useState({
  name: '',
  email: '',
  notifications: false,
  darkMode: false
});
 
const updateFormField = (field, value) => {
  setFormData({
    ...formData,
    [field]: value
  });
};
 
return (
  <View className="p-4">
    <Input
      label="Name"
      value={formData.name}
      onChangeText={(text) => updateFormField('name', text)}
    />
    
    <Input
      label="Email"
      value={formData.email}
      onChangeText={(text) => updateFormField('email', text)}
      keyboardType="email-address"
    />
    
    <View className="flex-row justify-between items-center py-4">
      <Text>Enable Notifications</Text>
      <Toggle
        value={formData.notifications}
        onChange={(value) => updateFormField('notifications', value)}
      />
    </View>
    
    <View className="flex-row justify-between items-center py-4">
      <Text>Dark Mode</Text>
      <Toggle
        value={formData.darkMode}
        onChange={(value) => updateFormField('darkMode', value)}
      />
    </View>
    
    <Button
      title="Save Preferences"
      onPress={() => console.log('Form data:', formData)}
      className="mt-4"
    />
  </View>
);

Settings List Example

const [settings, setSettings] = useState({
  notifications: true,
  darkMode: false,
  locationTracking: false,
  dataSync: true
});
 
const updateSetting = (key, value) => {
  setSettings({
    ...settings,
    [key]: value
  });
};
 
return (
  <View className="divide-y divide-gray-200 dark:divide-gray-700">
    <View className="flex-row justify-between items-center py-4">
      <View>
        <Text className="text-base font-medium">Notifications</Text>
        <Text className="text-sm text-gray-500">Receive app notifications</Text>
      </View>
      <Toggle
        value={settings.notifications}
        onChange={(value) => updateSetting('notifications', value)}
      />
    </View>
    
    <View className="flex-row justify-between items-center py-4">
      <View>
        <Text className="text-base font-medium">Dark Mode</Text>
        <Text className="text-sm text-gray-500">Use dark theme</Text>
      </View>
      <Toggle
        value={settings.darkMode}
        onChange={(value) => updateSetting('darkMode', value)}
      />
    </View>
    
    <View className="flex-row justify-between items-center py-4">
      <View>
        <Text className="text-base font-medium">Location Tracking</Text>
        <Text className="text-sm text-gray-500">Allow location access</Text>
      </View>
      <Toggle
        value={settings.locationTracking}
        onChange={(value) => updateSetting('locationTracking', value)}
      />
    </View>
    
    <View className="flex-row justify-between items-center py-4">
      <View>
        <Text className="text-base font-medium">Data Synchronization</Text>
        <Text className="text-sm text-gray-500">Sync data across devices</Text>
      </View>
      <Toggle
        value={settings.dataSync}
        onChange={(value) => updateSetting('dataSync', value)}
      />
    </View>
  </View>
);

Best Practices

Meaningful Labels

Always provide clear labels for toggles to indicate what they control:

<View className="flex-row justify-between items-center">
  <Text>Enable Notifications</Text>
  <Toggle
    value={notificationsEnabled}
    onChange={setNotificationsEnabled}
  />
</View>

Controlled vs. Uncontrolled Usage

Choose the appropriate usage pattern based on your needs:

// Uncontrolled - when you don't need to track the state elsewhere
<Toggle />
 
// Controlled - when you need to manage the state and use it elsewhere
const [isEnabled, setIsEnabled] = useState(false);
 
<Toggle
  value={isEnabled}
  onChange={setIsEnabled}
/>
 
// Later you can use isEnabled in your logic
{isEnabled && <Text>This appears when enabled</Text>}

Immediate Feedback

Provide immediate visual feedback when a toggle changes state:

const [darkMode, setDarkMode] = useState(false);
 
const handleToggle = (value) => {
  setDarkMode(value);
  // Immediately apply theme change
  applyTheme(value ? 'dark' : 'light');
};
 
<View className="flex-row justify-between items-center">
  <Text>Dark Mode</Text>
  <Toggle
    value={darkMode}
    onChange={handleToggle}
  />
</View>

Implementation Details

The Toggle component uses React Native's Pressable, View, and Animated components to create a smooth toggling experience. It features a spring animation that provides a natural, bouncy feel when toggling between states.

The component works in both controlled and uncontrolled modes:

  • In controlled mode, the value prop determines the toggle state
  • In uncontrolled mode, the component manages its own state internally

The toggle uses Tailwind classes for styling, with different background colors for the on and off states. The component supports both light and dark modes through conditional styling.

Notes

  • The spring animation uses a bounciness of 4 and speed of 12 for a natural feel
  • In controlled mode (value prop provided), the internal state is ignored
  • When disabled, the toggle has reduced opacity and doesn't respond to presses
  • The toggle uses a color from the theme's highlight palette when in the "on" state