Switch

A toggle control that allows users to switch between on and off states.

Import

import { Switch } from 'heroui-native';

Anatomy

<Switch>
  <Switch.Thumb>...</Switch.Thumb>
  <Switch.StartContent>...</Switch.StartContent>
  <Switch.EndContent>...</Switch.EndContent>
</Switch>
  • Switch: Main container that handles toggle state and user interaction. Renders default thumb if no children provided. Animates scale (on press) and background color based on selection state. Acts as a pressable area for toggling.
  • Switch.Thumb: Optional sliding thumb element that moves between positions. Uses spring animation for smooth transitions. Can contain custom content like icons or be customized with different styles and animations.
  • Switch.StartContent: Optional content displayed on the left side of the switch. Typically used for icons or text that appear when switch is off. Positioned absolutely within the switch container.
  • Switch.EndContent: Optional content displayed on the right side of the switch. Typically used for icons or text that appear when switch is on. Positioned absolutely within the switch container.

Usage

Basic Usage

The Switch component renders with default thumb if no children provided.

<Switch isSelected={isSelected} onSelectedChange={setIsSelected} />

With Custom Thumb

Replace the default thumb with custom content using the Thumb component.

<Switch isSelected={isSelected} onSelectedChange={setIsSelected}>
  <Switch.Thumb>...</Switch.Thumb>
</Switch>

With Start and End Content

Add icons or text that appear on each side of the switch.

<Switch isSelected={isSelected} onSelectedChange={setIsSelected}>
  <Switch.Thumb />
  <Switch.StartContent>...</Switch.StartContent>
  <Switch.EndContent>...</Switch.EndContent>
</Switch>

With Render Function

Use render functions for dynamic content based on switch state.

<Switch isSelected={isSelected} onSelectedChange={setIsSelected}>
  {({ isSelected, isDisabled }) => (
    <>
      <Switch.Thumb>
        {({ isSelected }) => (isSelected ? <CheckIcon /> : <XIcon />)}
      </Switch.Thumb>
    </>
  )}
</Switch>

With Custom Animations

Customize animations for the switch root and thumb components.

<Switch
  animation={{
    scale: {
      value: [1, 0.9],
      timingConfig: { duration: 200 },
    },
    backgroundColor: {
      value: ['#172554', '#eab308'],
    },
  }}
>
  <Switch.Thumb
    animation={{
      left: {
        value: 4,
        springConfig: {
          damping: 30,
          stiffness: 300,
          mass: 1,
        },
      },
      backgroundColor: {
        value: ['#dbeafe', '#854d0e'],
      },
    }}
  />
</Switch>

Disable Animations

Disable animations entirely or only for specific components.

{
  /* Disable all animations including children */
}
<Switch animation="disable-all">
  <Switch.Thumb />
</Switch>;

{
  /* Disable only root animations, thumb can still animate */
}
<Switch>
  <Switch.Thumb animation={false} />
</Switch>;

Example

import { Switch } from 'heroui-native';
import { Ionicons } from '@expo/vector-icons';
import React from 'react';
import { View } from 'react-native';
import Animated, { ZoomIn } from 'react-native-reanimated';

export default function SwitchExample() {
  const [darkMode, setDarkMode] = React.useState(false);

  return (
    <View className="flex-row gap-4">
      <Switch
        isSelected={darkMode}
        onSelectedChange={setDarkMode}
        className="w-[56px] h-[32px]"
        animation={{
          backgroundColor: {
            value: ['#172554', '#eab308'],
          },
        }}
      >
        <Switch.Thumb
          className="size-[22px]"
          animation={{
            left: {
              value: 4,
              springConfig: {
                damping: 30,
                stiffness: 300,
                mass: 1,
              },
            },
          }}
        />
        <Switch.StartContent className="left-2">
          {darkMode && (
            <Animated.View key="sun" entering={ZoomIn.springify()}>
              <Ionicons name="sunny" size={16} color="#854d0e" />
            </Animated.View>
          )}
        </Switch.StartContent>
        <Switch.EndContent className="right-2">
          {!darkMode && (
            <Animated.View key="moon" entering={ZoomIn.springify()}>
              <Ionicons name="moon" size={16} color="#dbeafe" />
            </Animated.View>
          )}
        </Switch.EndContent>
      </Switch>
    </View>
  );
}

API Reference

Switch

proptypedefaultdescription
childrenReact.ReactNode | ((props: SwitchRenderProps) => React.ReactNode)undefinedContent to render inside the switch, or a render function
isSelectedbooleanundefinedWhether the switch is currently selected
isDisabledbooleanfalseWhether the switch is disabled and cannot be interacted with
classNamestringundefinedCustom class name for the switch
animationSwitchRootAnimation-Animation configuration
onSelectedChange(isSelected: boolean) => void-Callback fired when the switch selection state changes
...AnimatedPressablePropsAnimatedProps<PressableProps>-All React Native Reanimated Pressable props are supported

SwitchRenderProps

proptypedescription
isSelectedbooleanWhether the switch is selected
isDisabledbooleanWhether the switch is disabled

SwitchRootAnimation

Animation configuration for Switch component. Can be:

  • false or "disabled": Disable only root animations
  • "disable-all": Disable all animations including children
  • true or undefined: Use default animations
  • object: Custom animation configuration
proptypedefaultdescription
scale.value[number, number][1, 0.96]Scale values [unpressed, pressed]
scale.timingConfigWithTimingConfig{ duration: 150 }Animation timing configuration
backgroundColor.value[string, string]Uses theme colorsBackground color values [unselected, selected]
backgroundColor.timingConfigWithTimingConfig{ duration: 175, easing: Easing.bezier(0.25, 0.1, 0.25, 1) }Animation timing configuration

Switch.Thumb

proptypedefaultdescription
childrenReact.ReactNode | ((props: SwitchRenderProps) => React.ReactNode)undefinedContent to render inside the thumb, or a render function
classNamestringundefinedCustom class name for the thumb element
animationSwitchThumbAnimation-Animation configuration
...ViewPropsViewProps-All standard React Native View props are supported

SwitchThumbAnimation

Animation configuration for Switch.Thumb component. Can be:

  • false or "disabled": Disable all animations
  • true or undefined: Use default animations
  • object: Custom animation configuration
proptypedefaultdescription
left.valuenumber2Offset value from the edges (left when unselected, right when selected)
left.springConfigWithSpringConfig{ damping: 120, stiffness: 1600, mass: 2 }Spring animation configuration for thumb position
backgroundColor.value[string, string]['white', theme accent-foreground color]Background color values [unselected, selected]
backgroundColor.timingConfigWithTimingConfig{ duration: 175, easing: Easing.bezier(0.25, 0.1, 0.25, 1) }Animation timing configuration

Switch.StartContent

proptypedefaultdescription
childrenReact.ReactNodeundefinedContent to render inside the switch content
classNamestringundefinedCustom class name for the content element
...ViewPropsViewProps-All standard React Native View props are supported

Switch.EndContent

proptypedefaultdescription
childrenReact.ReactNodeundefinedContent to render inside the switch content
classNamestringundefinedCustom class name for the content element
...ViewPropsViewProps-All standard React Native View props are supported

Hooks

useSwitch

A hook that provides access to the Switch context. This is useful when building custom switch components or when you need to access switch state in child components.

Returns:

PropertyTypeDescription
isSelectedbooleanWhether the switch is selected
isDisabledbooleanWhether the switch is disabled

Example:

import { useSwitch } from 'heroui-native';

function CustomSwitchContent() {
  const { isSelected, isDisabled } = useSwitch();

  return (
    <View>
      <Text>Status: {isSelected ? 'On' : 'Off'}</Text>
      {isDisabled && <Text>Disabled</Text>}
    </View>
  );
}

// Usage
<Switch>
  <CustomSwitchContent />
  <Switch.Thumb />
</Switch>;

Special Notes

Border Styling

If you need to apply a border to the switch root, use the outline style properties instead of border. This ensures the border doesn't affect the internal layout calculations for the thumb position:

<Switch className="outline outline-accent">
  <Switch.Thumb />
</Switch>

Using outline keeps the border visual without impacting the switch's internal width calculations, ensuring the thumb animates correctly.

Integration with FormField

The Switch component integrates seamlessly with FormField for press state sharing:

<FormField isSelected={isSelected} onSelectedChange={setIsSelected}>
  <View className="flex-1">
    <FormField.Label>Enable notifications</FormField.Label>
    <FormField.Description>Receive push notifications</FormField.Description>
  </View>
  <FormField.Indicator />
</FormField>

When wrapped in FormField, the Switch will automatically respond to press events on the entire FormField container, creating a larger touch target and better user experience.

On this page