Skip to main content
React Native Switchery is built with accessibility in mind, providing proper ARIA roles, states, and customizable labels to ensure your switches work well with screen readers and assistive technologies.

Built-in Accessibility

Every Switch component automatically includes:
  • accessibilityRole="switch" - Properly identifies the element as a switch
  • accessibilityState - Communicates the checked state and disabled status
  • Touch target optimization - Ensures the switch is easy to interact with

Accessibility Label

Provide a descriptive label that screen readers will announce:
import { Switch } from 'react-native-switchery';

export default function App() {
  const [enabled, setEnabled] = useState(false);
  
  return (
    <Switch
      value={enabled}
      onValueChange={setEnabled}
      accessibilityLabel="Enable notifications"
    />
  );
}
Always provide an accessibilityLabel for switches that aren’t accompanied by visible text labels.

Accessibility Hint

Add helpful context about what the switch does:
<Switch
  value={enabled}
  onValueChange={setEnabled}
  accessibilityLabel="Dark mode"
  accessibilityHint="Toggles dark mode theme for the entire app"
/>
Screen readers will announce both the label and hint, giving users complete context about the switch’s purpose and effect.

Disabled State

Disable switches when they shouldn’t be interactive:
<Switch
  value={enabled}
  onValueChange={setEnabled}
  disabled={true}
  accessibilityLabel="Premium feature"
  accessibilityHint="Upgrade to premium to enable this feature"
/>
When disabled:
  • The switch becomes non-interactive
  • A visual overlay indicates the disabled state
  • Screen readers announce the switch as disabled
  • The accessibilityState.disabled is set to true

Complete Example

Here’s a settings screen with fully accessible switches:
import { View, Text, StyleSheet } from 'react-native';
import { Switch } from 'react-native-switchery';

export default function SettingsScreen() {
  const [settings, setSettings] = useState({
    notifications: true,
    location: false,
    analytics: false,
  });
  const [isPremium, setIsPremium] = useState(false);
  
  return (
    <View style={styles.container}>
      <View style={styles.row}>
        <Text style={styles.label}>Notifications</Text>
        <Switch
          value={settings.notifications}
          onValueChange={(val) => setSettings({ ...settings, notifications: val })}
          accessibilityLabel="Enable notifications"
          accessibilityHint="Receive push notifications for updates and messages"
          variant="primary"
        />
      </View>
      
      <View style={styles.row}>
        <Text style={styles.label}>Location Services</Text>
        <Switch
          value={settings.location}
          onValueChange={(val) => setSettings({ ...settings, location: val })}
          accessibilityLabel="Enable location services"
          accessibilityHint="Allow app to access your location for personalized content"
          variant="info"
        />
      </View>
      
      <View style={styles.row}>
        <Text style={styles.label}>Usage Analytics</Text>
        <Switch
          value={settings.analytics}
          onValueChange={(val) => setSettings({ ...settings, analytics: val })}
          disabled={!isPremium}
          accessibilityLabel="Enable usage analytics"
          accessibilityHint={isPremium 
            ? "Share anonymous usage data to help improve the app" 
            : "Premium feature - upgrade to enable"
          }
          variant="success"
        />
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
  },
  row: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    paddingVertical: 16,
    borderBottomWidth: 1,
    borderBottomColor: '#E5E7EB',
  },
  label: {
    fontSize: 16,
    color: '#1F2937',
  },
});

Best Practices

Clear Labels: Use concise, descriptive labels that clearly indicate what the switch controls.
Informative Hints: Add hints that explain the consequence of toggling the switch, especially for critical or non-obvious actions.
Size for Touch: For better accessibility, consider using size="large" for important controls or when designing for users with motor impairments.
Don’t rely solely on color to convey information. Always provide text labels or accessibility labels for switches.

Testing Accessibility

iOS VoiceOver

  1. Enable VoiceOver: Settings > Accessibility > VoiceOver
  2. Navigate to your switch
  3. VoiceOver should announce: “[Label], switch, [on/off], [hint]“

Android TalkBack

  1. Enable TalkBack: Settings > Accessibility > TalkBack
  2. Navigate to your switch
  3. TalkBack should announce: “[Label], switch, [checked/not checked], [hint]“

Prop Reference

PropTypeDefaultDescription
accessibilityLabelstringundefinedLabel announced by screen readers
accessibilityHintstringundefinedAdditional context about the switch’s purpose
disabledbooleanfalseWhether the switch is disabled
testIDstring'switch'Identifier for automated testing

Accessibility State

The switch automatically manages its accessibilityState with:
accessibilityState={{
  disabled: disabled,  // From the disabled prop
  checked: value,      // From the value prop
}}
This ensures assistive technologies always have accurate information about the switch’s current state.

Additional Resources

Accessibility is not just a feature—it’s a fundamental requirement for inclusive app design. Always test your switches with screen readers during development.

Build docs developers (and LLMs) love