Switch

A native switch control for toggling a boolean value.

Switch is the React Native implementation shipped by the native-switch registry item. The component adapts the registry's web-facing composition to native primitives and touch-based interaction.

The native Switch is a compact boolean control built from React Native primitives. It animates the thumb when the checked state changes and supports both controlled and uncontrolled usage.

It exposes switch semantics through React Native accessibility state and can be disabled without losing the current value.

See the shadcn/ui Switch documentation for the web component API, concepts, and additional examples.

Installation

CLI

npx shadcn add https://ui.tiesen.id.vn/r/native-switch.json

Manual

Copy and paste the following code into your project.

import * as React from 'react'import { Animated, TouchableOpacity } from 'react-native'import { cn } from '@/lib/utils'const SWITCH_WIDTH = 32const THUMB_SIZE = 14const PADDING = 2const TRANSLATE_X = SWITCH_WIDTH - THUMB_SIZE - PADDING * 2function Switch({  className,  checked: _checked = false,  onCheckedChange,  disabled = false,  activeOpacity = 0.8,  onPress,  ...props}: Omit<React.ComponentProps<typeof TouchableOpacity>, 'children'> & {  checked?: boolean  onCheckedChange?: (checked: boolean) => void}) {  const [localChecked, setLocalChecked] = React.useState(_checked)  // oxlint-disable-next-line react/refs  const translateX = React.useRef(    new Animated.Value(_checked ? TRANSLATE_X : PADDING)  ).current  const isControlled = _checked !== undefined && onCheckedChange !== undefined  const checked = isControlled ? _checked : localChecked  const handlePress = React.useCallback(    (event: Parameters<NonNullable<typeof onPress>>[0]) => {      if (disabled) return      Animated.timing(translateX, {        toValue: checked ? PADDING : TRANSLATE_X,        duration: 200,        useNativeDriver: true,      }).start()      if (!isControlled) setLocalChecked(!checked)      onCheckedChange?.(!checked)      onPress?.(event)    },    [checked, disabled, isControlled, onCheckedChange, onPress, translateX]  )  return (    <TouchableOpacity      data-slot='switch'      accessibilityRole='switch'      accessibilityState={{ checked, disabled }}      aria-checked={checked}      aria-disabled={disabled}      disabled={disabled}      onPress={handlePress}      activeOpacity={activeOpacity}      style={{ width: SWITCH_WIDTH }}      className={cn(        'group/switch relative inline-flex h-5 shrink-0 flex-row items-center rounded-full border border-transparent bg-input transition-all outline-none dark:bg-input/80',        checked && 'bg-primary dark:bg-primary',        disabled && 'opacity-50',        className      )}      {...props}    >      <Animated.View        data-slot='switch-thumb'        style={{          width: THUMB_SIZE,          height: THUMB_SIZE,          transform: [{ translateX }],        }}        className={cn(          'shrink-0 rounded-full bg-foreground',          checked && 'bg-primary-foreground'        )}      />    </TouchableOpacity>  )}export { Switch }

Features

  • Controlled and uncontrolled checked state.
  • Animated thumb transition.
  • Disabled state.
  • Configurable active opacity.
  • Native switch accessibility semantics.
  • Standard touch event forwarding.

Usage

import { Switch } from '@/components/native/switch'

export function SwitchExample() {
  const [enabled, setEnabled] = React.useState(true)

  return (
    <Switch
      checked={enabled}
      onCheckedChange={setEnabled}
    />
  )
}

Controlled

<Switch
  checked={enabled}
  onCheckedChange={setEnabled}
/>

The switch is controlled when both checked and onCheckedChange are provided.

Uncontrolled

<Switch />

Without the controlled callback pair, the component keeps the checked state internally.

Disabled

<Switch
  checked={true}
  disabled
/>

Disabled switches do not respond to presses and receive reduced opacity.

API Reference

Switch

PropTypeDefault
checkedbooleanfalse
onCheckedChange(checked: boolean) => void—
disabledbooleanfalse
activeOpacitynumber0.8
onPressTouchableOpacityProps['onPress']—
classNamestring—
...propsOmit<React.ComponentProps<typeof TouchableOpacity>, 'children'>—

The switch does not render children; the visual track and thumb are rendered internally.

On this page