Hanzo GUI

Switch

A toggle between two states

StyledUnstyledHeadless

`

`

`

  • Accessible, easy to compose and customize.
  • Style and animate both frame and thumb.
  • Sizable & works controlled or uncontrolled.
  • Native prop that renders native Switch on mobile

Installation

Switch is already installed in @hanzo/gui, or you can install it independently:

npm install @hanzogui/switch

Switch is already installed in @hanzo/gui, or you can install it independently:

npm install @hanzogui/switch

To use the headless switch, you want to import it from the @hanzogui/switch-headless package. This package has no dependency on @hanzogui/core, but still works off the react-native APIs. This means you can bring your own style library.

npm install @hanzogui/switch-headless

Usage

import { Switch } from '@hanzo/gui' // or '@hanzogui/switch'

export default () => (
  <Switch size="$4">
    <Switch.Thumb transition="bouncy" />
  </Switch>
)

Using the createSwitch export, you can create an unstyled switch without using any of the default styles. This is similar to the unstyled prop, but it doesn't assume the props size or unstyled exist, and it won't automatically apply the active theme.

You must pass SwitchContext as the context option to your Frame and Thumb styled components.

If you define a checked variant, it will apply those styles.

The useSwitch hook provides all the state and accessibility props needed to build a custom switch with any styling solution.

Basic Usage

import { useSwitch } from '@hanzogui/switch-headless'
import { useState } from 'react'
import { Pressable, View } from 'react-native'

function MySwitch({ defaultChecked, onCheckedChange, ...props }) {
  const [checked, setChecked] = useState(defaultChecked || false)

  const { switchProps, switchRef, bubbleInput } = useSwitch(
    props,
    [checked, setChecked],
    null
  )

  return (
    <>
      <Pressable
        ref={switchRef}
        {...switchProps}
        style={{
          width: 50,
          height: 28,
          borderRadius: 14,
          backgroundColor: checked ? '#22c55e' : '#d1d5db',
          padding: 2,
        }}
      >
        <View
          style={{
            width: 24,
            height: 24,
            borderRadius: 12,
            backgroundColor: 'white',
            transform: [{ translateX: checked ? 22 : 0 }],
          }}
        />
      </Pressable>
      {bubbleInput}
    </>
  )
}

API Reference

Switch

Switch extends Stack views inheriting all the Gui standard props, plus:

PropTypeDefaultRequired
labeledBystring--
namestring--
valuestring--
checkedboolean--
defaultCheckedboolean--
requiredboolean--
onCheckedChange(checked: boolean) => void--
unstyledbooleanfalse-
nativeNativeValue<"mobile" | "ios" | "android">--
nativePropsSwitchProps (from `react-native`)--
activeStyleViewStyle--
activeThemestring | null--

Switch.Thumb

Switch.Thumb extends Stack views inheriting all the Gui standard props, plus:

PropTypeDefaultRequired
unstyledbooleanfalse-
activeStyleViewStyle--

useSwitch

The useSwitch hook accepts three arguments:

const { switchProps, switchRef, bubbleInput } = useSwitch(
  props, // SwitchProps
  state, // [checked: boolean, setChecked: (checked: boolean) => void]
  ref // React.Ref
)

Props (first argument)

PropTypeDefaultRequired
labeledBystring--
disabledboolean--
namestring--
valuestring--
requiredboolean--
onPress(event) => void--

State (second argument)

A tuple of [checked, setChecked] where:

  • checked: Current boolean state
  • setChecked: React state setter function

Return Value

PropertyTypeDescription
switchPropsobjectProps to spread on your switch element (role, aria-checked, onPress, etc.)
switchRefRefComposed ref to attach to your switch element
bubbleInputReactNode | nullHidden input for form compatibility (render as sibling, web only)

Last updated on

On this page