AppyKit UI

Switch

A toggle control for switching between two states, like on/off.

import { Switch } from '@/components/ui/switch';
import React from 'react';
import { Text, View } from 'react-native';

export default function SwitchDemo() {
const [checked, setChecked] = React.useState(false);
return (
<View className="flex-1 justify-center items-center p-6 gap-12">
<View className="flex-row items-center gap-2">
<Switch
  checked={checked}
  onCheckedChange={setChecked}
  nativeID="airplane-mode"
/>
<Text
  nativeID="airplane-mode"
  onPress={() => {
    setChecked((prev) => !prev);
  }}
>
  Airplane Mode
</Text>
</View>
</View>
);
}

Installation

npx shadcn@latest add switch

Install the following dependencies:

npx expo install @rn-primitives/switch

Create a folder named ui under component folder in your project and add the following code in a file named switch.tsx:

import * as SwitchPrimitives from '@rn-primitives/switch';
import * as React from 'react';
import { Platform } from 'react-native';
import Animated, {
  interpolateColor,
  useAnimatedStyle,
  useDerivedValue,
  withTiming,
} from 'react-native-reanimated';
import { useColorScheme } from '@/lib/useColorScheme';
import { cn } from '@/lib/utils';

function SwitchWeb({
  className,
  ...props
}: SwitchPrimitives.RootProps & {
  ref?: React.RefObject<SwitchPrimitives.RootRef>;
}) {
  return (
    <SwitchPrimitives.Root
      className={cn(
        'peer flex-row h-5 w-10 shrink-0 cursor-pointer items-center native:rounded-full rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed',
        props.checked ? 'bg-primary' : 'bg-input',
        props.disabled && 'opacity-50',
        className
      )}
      {...props}
    >
      <SwitchPrimitives.Thumb
        className={cn(
          'pointer-events-none block h-4 w-4 rounded-full bg-background native:rounded-full shadow-md shadow-foreground/5 ring-0 transition-transform',
          props.checked ? 'translate-x-5' : 'translate-x-0'
        )}
      />
    </SwitchPrimitives.Root>
  );
}

const RGB_COLORS = {
  light: {
    primary: 'rgb(24, 24, 27)',
    input: 'rgb(228, 228, 231)',
  },
  dark: {
    primary: 'rgb(250, 250, 250)',
    input: 'rgb(39, 39, 42)',
  },
} as const;

function SwitchNative({
  className,
  ...props
}: SwitchPrimitives.RootProps & {
  ref?: React.RefObject<SwitchPrimitives.RootRef>;
}) {
  const { colorScheme } = useColorScheme();
  const translateX = useDerivedValue(() => (props.checked ? 18 : 0));
  const animatedRootStyle = useAnimatedStyle(() => {
    return {
      backgroundColor: interpolateColor(
        translateX.value,
        [0, 18],
        [RGB_COLORS[colorScheme].input, RGB_COLORS[colorScheme].primary]
      ),
    };
  });
  const animatedThumbStyle = useAnimatedStyle(() => ({
    transform: [{ translateX: withTiming(translateX.value, { duration: 200 }) }],
  }));
  return (
    <Animated.View
      style={animatedRootStyle}
      className={cn('h-6 w-[40px] rounded-full', props.disabled && 'opacity-50')}
    >
      <SwitchPrimitives.Root
        className={cn(
          'flex-row h-6 w-[40px] shrink-0 items-center rounded-full border-2 border-transparent',
          props.checked ? 'bg-primary' : 'bg-input',
          className
        )}
        {...props}
      >
        <Animated.View style={animatedThumbStyle}>
          <SwitchPrimitives.Thumb
            className={'h-[21px] w-[21px] rounded-full bg-background shadow-md shadow-foreground/25 ring-0'}
          />
        </Animated.View>
      </SwitchPrimitives.Root>
    </Animated.View>
  );
}

const Switch = Platform.select({
  web: SwitchWeb,
  default: SwitchNative,
});

export { Switch };

This component depends on the Text component. Please follow the installation guide here before using the Switch.

Update the import paths to match your project setup.

Usage

import { Switch } from "@/components/ui/switch";
<Switch
  checked={checked}
  onCheckedChange={setChecked}
  nativeID="airplane-mode"
/>

On this page