Skip to content

Selection

Switch

Stable

A toggle control for a single boolean setting, available on web (React) and native (React Native). 3 sizes, optional in-track state icon for non-colour affordance, optional label in 4 positions.

Sizes

Small

Dense UI, compact forms.

<Switch size="sm" defaultChecked />

Medium

The default size for most layouts.

<Switch size="md" defaultChecked />

Large

Prominent settings screens.

<Switch size="lg" defaultChecked />

Disabled

Disabled, off

<Switch disabled />

Disabled, on

<Switch disabled defaultChecked />

State icon

With state icon

A check/cross icon inside the track, for a non-colour signal of state.

<Switch showStateIcon defaultChecked />

With label

Label right (default)

Clicking the label toggles the switch: the whole row is a hit target.

<Switch label="Email notifications" />

Label left

<Switch label="Email notifications" labelPosition="left" />

When to use

Use a switch for a single, immediately-applied boolean setting, for example “Email notifications: on/off”. Unlike a checkbox, a switch implies the change takes effect right away, without a separate save/submit step.

When not to use

  • A list of options where only one is correct at a time: use radio buttons.
  • A setting that requires an explicit “Save” action: use a checkbox instead. A switch’s on/off framing implies immediacy.
  • Multiple independent selections from a list: use checkboxes.

Props

Prop Type Default Description
checked boolean - Controlled checked state. Omit and use defaultChecked for uncontrolled usage.
defaultChecked boolean false Initial checked state for uncontrolled usage. Ignored if checked is provided.
onChange (checked: boolean) => void - Fires with the new checked value on toggle.
size 'sm' | 'md' | 'lg' 'md' Controls track and thumb size.
disabled boolean false Disables interaction and dims the control.
showStateIcon boolean false Renders a check/cross icon inside the track for a non-colour state signal.
label string - Optional label text rendered alongside the control.
labelPosition 'left' | 'right' | 'top' | 'below' 'right' Position of the label relative to the control. Only used when label is set.

Import

Web

import { Switch } from '@checkatrade/components-web';

Native

import { Switch } from '@checkatrade/components-native';

Basic usage

const [checked, setChecked] = useState(false);
<Switch checked={checked} onChange={setChecked} label="Email notifications" />;

Platform status

Platform / AreaStatus
Design (Figma) Stable
Web (React) Stable
Native (React Native) Stable
iOS (Swift) Planned
Android (Kotlin) Planned
Accessibility audit Planned

Accessibility

  • role="switch" (web) / accessibilityRole="switch" (native), with aria-checked/accessibilityState.checked reflecting state.
  • Fully keyboard operable on web: Tab to focus, Space/Enter to toggle (native <button> semantics).
  • showStateIcon provides a non-colour signal of on/off state for colour-blind users. The icon itself is decorative (aria-hidden/accessibilityElementsHidden) since the accessible state lives on the control.
  • When label is set, the whole row is a hit target on both platforms: on web the wrapper is a real <label> (matching Checkbox), and on native the label text is its own press target routing through the same handler as the control, so clicking or tapping the label toggles the switch. The accessible name is unchanged: on web the control keeps its own aria-labelledby, which wins over the implicit name a wrapping <label> would otherwise provide; on native it keeps accessibilityLabel.
  • On web the label wrapper is select-none, so repeated clicks don’t select the label text as prose. On native the label text carries both the iOS/Android hiding props (accessibilityElementsHidden, importantForAccessibility) and their react-native-web counterparts (aria-hidden, tabIndex={-1}), so it is neither announced twice nor a second tab stop on RN-web.

No releases yet.