Switch

Atom
On / off switch, isolated or grouped in a settings list.

Playground

Every control sets a real prop of SwitchProps. The JSX below updates as you go.
Glass surfaces
Frost on every pane
Props
checked
boolean
Size
pick one
disabled
boolean
children
string
description
string
JSX · SwitchProps
<Switch checked description="Frost on every pane">Glass surfaces</Switch>

Variants

5 examples from src/atoms/switch/switch.md, each rendered live from its own JSX.
Available to chat
Off
<Switch>Available to chat</Switch>
Available to chat
Show your availability to teammates.
With description
<Switch description="Show your availability to teammates.">Available to chat</Switch>
Available to chat
Disabled
<Switch disabled>Available to chat</Switch>
Notifications
Controlled
<Stateful initial={true}>
{(on, setOn) => <Switch checked={on} onChange={setOn}>Notifications</Switch>}
</Stateful>
Glass surfaces
Frosted material on panels and sheets
Reduced motion
Zero every duration, keep spinners
Haptics
Settings list
<Column tight>
<Switch listed defaultChecked description="Frosted material on panels and sheets">Glass surfaces</Switch>
<Switch listed divided description="Zero every duration, keep spinners">Reduced motion</Switch>
<Switch listed divided defaultChecked>Haptics</Switch>
</Column>

Sizes

Glass surfaces
Frost on every pane
small
Glass surfaces
Frost on every pane
default
Glass surfaces
Frost on every pane
large

States

Hover, focus and press are pinned so they can be compared side by side; the rest are real props.
Glass surfaces
Frost on every pane
default
Glass surfaces
Frost on every pane
hover
Glass surfaces
Frost on every pane
focus
Glass surfaces
Frost on every pane
disabled

Anatomy

Glass surfaces
Frost on every pane
1
Track
2
Thumb
3
Label
4
Description
Dimmed parts appear only in some states or variants.

Props

16 props on SwitchProps, grouped as they are declared in source. Required props are marked *.
Prop
Type
Default
Description
Props
6 props
checked
boolean
false
Controlled on/off state; omit for uncontrolled use.
defaultChecked
boolean
false
Initial state for uncontrolled use (a bare <Switch /> is interactive).
onChange
(next: boolean) => void
–
Fired with the next checked value when the switch is toggled (both modes). Web keyboard activation supports Space on release and Enter.
onValueChange
(next: boolean) => void
–
Alias of onChange, for parity with RN's value-style callbacks.
testID
string
–
E2E hook forwarded to the pressable row.
ref
React.Ref<View>
–
Ref to the interactive switch row, including its label. Typed as a React Native View. On web, React Native Web exposes its DOM host; focus() and blur() move browser focus. Native host behavior depends on the platform and React Native version. Calling focus() does not activate the control or call accessibility focus APIs.
Size
pick one
5 props
small
boolean
false
large
boolean
false
chip
boolean
false
A compact bordered capsule with its label after the switch, for a toolbar setting.
listed
boolean
false
A row of a settings list: 10 px above and below the row, so a stack of switches reads as a list rather than a form (stack them in a Column tight). Pair with divided on every row after the first.
divided
boolean
false
A hairline above the row in the border ink: a settings list's separator from the row before.
State
5 props
disabled
boolean
false
State.
children
ReactNode
–
Optional label, rendered to the left of the track.
description
ReactNode
–
Optional muted description line, rendered under the label.
accessibilityLabel
string
–
Accessible name for the switch when no visible children label is rendered (e.g. a switch embedded in an Action Panel whose label sits in sibling Text). Without it, a label-less switch announces only "switch, on/off".
style
LayoutStyle
–
Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.

Accessibility and keyboard

Keyboard
Space
Toggles
Tab
Moves focus on
Semantics
Roles
switch
States
checked
disabled
ARIA on web
aria-checked
aria-label
Below the platform minimum, the touch area grows to 44 pt on iOS and 48 dp on Android without moving the layout.
From the docs
Pass ref to access the interactive switch row, including its label. Use useRef<ComponentRef<typeof Switch>>(null) from React, or useRef<View>(null) with React Native's View type. Object and callback refs are supported and detach on unmount. Calling ref.current?.focus() or .blur() delegates to the host without activating the control. Browser focus is supported; native focus depends on the platform and React Native version, and is separate from accessibility focus.
On the web, Space activates the focused control on key release, and Enter also activates it. Holding Space does not repeat the change. Moving focus away, disabling the control, or composing text cancels a pending Space press.

Platform skins

The playground's props on each platform: same tree, native shapes, type and touch sizes.
Glass surfaces
Frosted material on panels and sheets
Reduced motion
Zero every duration, keep spinners
Haptics
Web
control 10 · field 10 · card 16 · Instrument Sans
Glass surfaces
Frosted material on panels and sheets
Reduced motion
Zero every duration, keep spinners
Haptics
iOS
capsule controls · field 8 · card 12 · SF Pro · 44 pt
Glass surfaces
Frosted material on panels and sheets
Reduced motion
Zero every duration, keep spinners
Haptics
Android
Material 3 stadium · field 4 · card 12 · Roboto · 48 dp

Usage

<Switch defaultChecked>Available to chat</Switch>
In glass mode a switch keeps its solid look on every platform: it is a small mark inside content, not a surface, so its track and knob draw as in solid mode, with no pane and no rim, a checked track in its solid brand fill. The track, the label, the description and the hit target never move, and the checked state flips at once. A disabled switch is inert.
small and large scale the track on the web. Pass chip for a compact toolbar setting: a 32 px bordered capsule with a 26×16 track, a 10 px knob and the label after the switch. The web thumb follows the reference spring and Reduce Motion; native skins keep their own switch. On iOS and Android the switch is the platform's own control, which comes in one size (51x31 on iOS, 52x32 on Android), so the size props leave it unchanged there.
Pass ref to access the interactive switch row, including its label. Use useRef<ComponentRef<typeof Switch>>(null) from React, or useRef<View>(null) with React Native's View type. Object and callback refs are supported and detach on unmount. Calling ref.current?.focus() or .blur() delegates to the host without activating the control. Browser focus is supported; native focus depends on the platform and React Native version, and is separate from accessibility focus.

Tokens

Read from the playground render. Values follow the scheme and the ion hue.
--fd
--ft
--ion
--tx3

Related components