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 / Area | Status |
|---|---|
| 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), witharia-checked/accessibilityState.checkedreflecting state.- Fully keyboard operable on web: Tab to focus, Space/Enter to toggle (native
<button>semantics). showStateIconprovides 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
labelis set, the whole row is a hit target on both platforms: on web the wrapper is a real<label>(matchingCheckbox), 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 ownaria-labelledby, which wins over the implicit name a wrapping<label>would otherwise provide; on native it keepsaccessibilityLabel. - 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.