Knit UI
GitHub

Usage

import { Switch } from "@knitui/components";

<Switch label="Push notifications" onChange={setEnabled} />;

Uncontrolled by default; pass checked + onChange to control it. As with the other inputs, description and error are wired to the control for you.

onLabel / offLabel render inside the track, and thumbIcon puts a glyph on the thumb itself — useful when colour alone shouldn't carry the state:

<Switch label="Dark mode" onLabel="ON" offLabel="OFF" />

A switch implies its change takes effect immediately. If the value needs a Save button to matter, a checkbox is the more honest control.

When to use something else

Examples

Sizes

All seven sizes side by side for a quick visual comparison.

Loading example…

SizesSourceStorybook

Shadows

Elevation shadow ladder applied to the track via the inherited shadow prop.

Loading example…

ShadowsSourceStorybook

Disabled

Disabled state — the switch is non-interactive and visually dimmed.

Loading example…

DisabledSourceStorybook

Track Labels

On/off labels rendered inside the track, behind the thumb.

Loading example…

Track LabelsSourceStorybook

Thumb Icon

An icon rendered inside the thumb replaces the default dot indicator.

Loading example…

Thumb IconSourceStorybook

Themes

Accent colour comes from the Tamagui theme prop.

Loading example…

ThemesSourceStorybook

Label Left

Label placed to the left of the track.

Loading example…

Label LeftSourceStorybook

With Description And Error

Description and error slot — rendered below the label when provided.

Loading example…

With Description And ErrorSourceStorybook

Controlled

Fully controlled switch — the parent manages checked state via React.useState.

Loading example…

ControlledSourceStorybook

Group

Switch.Group manages a set of switches as a multi-select; maxSelectedValues caps the selection.

Loading example…

GroupSourceStorybook

Group Read Only

A read-only Switch.Group keeps the current values visible but prevents toggling them.

Loading example…

Group Read OnlySourceStorybook

Controlled Group

Controlled Switch.Group — parent tracks the selected values array.

Loading example…

Controlled GroupSourceStorybook

Styles

Per-slot styles targets individual parts — here the track, thumb and label.

Loading example…

StylesSourceStorybook

Props

PropTypeDefaultDescription
aria-describedbystring | undefined—Ids of external description elements; merged with description/error ids.
aria-labelstring | undefined—Accessible label when no visible label is provided.
aria-labelledbystring | undefined—Id of an external label element. Defaults to the visible label id.
checkedboolean | undefined—Controlled checked state.
defaultCheckedboolean | undefinedfalseInitial checked state for the uncontrolled case.
descriptionReactNode—Description rendered below the label.
disabled systemboolean | undefinedfalseDisables the switch.
errorReactNode—Error rendered below the description (string nodes get the error theme).
idstring | undefined—Id used to bind the control and label; auto-generated when omitted.
labelReactNodeSwitchLabel content rendered next to the control.
labelPosition"left" | "right" | undefined
left · right
'right'Position of the label relative to the track.
offLabelReactNode—Inner label shown in the track when unchecked.
onChange((checked: boolean) => void) | undefined—Called with the next checked state. Mirrors Mantine's `onChange` name; the payload is a boolean (not a DOM event) because the kit is cross-platform.
onCheckedChange((checked: boolean) => void) | undefined——
onLabelReactNode—Inner label shown in the track when checked.
radius systemstring | number | undefined——
rootRefRef<TamaguiElement> | undefined—Ref of the root wrapper element.
shadow system"xs" | "sm" | "md" | "lg" | "xl" | "xxs" | "xxl" | undefined——
size system"xs" | "sm" | "md" | "lg" | "xl" | "xxs" | "xxl" | undefined
xxs · xs · sm · md · lg · xl · xxl
'sm'Controls the height, width and thumb dimensions of the track.
styles systemSlotStyles<SwitchStyles> | undefined—Uniform per-slot style passthrough — sugar over the composable parts. Own slots: `track` / `thumb` / `thumbIndicator` / `trackLabel`; plus the inherited chrome slots `label` / `description` / `error` / `root` forwarded to the `InlineControl`.
theme systemThemeName | null | undefined—Applies a theme to this element
thumbIconReactNode—Icon rendered inside the thumb.
valuestring | undefined—Value reported to a surrounding `Switch.Group`.
withThumbIndicatorboolean | undefinedtrueShow a coloured dot inside the thumb.

Style slots

Every part of Switch can be styled through the styles prop. Explicit props on the component always win over slot styles.

SlotTargets
descriptionThe description Text rendered below the label.
errorThe error Text rendered below the description.
labelThe label Text.
rootThe outer InlineControlRoot row.
thumbProps for the sliding SwitchThumb.
thumbIndicatorProps for the dot inside the thumb (SwitchThumbIndicator).
trackProps for the pill SwitchTrack.
trackLabelProps for the on/off label rendered in the track (SwitchTrackLabel).
Accessibility & DOM props (2)
PropType
keyKey | null | undefined
refRef<TamaguiElement> | undefined

Plus 495 inherited style props from Box — the full Tamagui/React Native style surface, including token shorthands like p, mx, bg and c. See Tokens for the scales they accept, or the full list.

Accessibility

On the web the control carries role="switch" with aria-checked — announced as "switch, on/off" rather than "checkbox, checked", which is the distinction users of screen readers rely on to know the change is immediate.

Focus and key handling come from the shared useKeyboardActions hook, as the track is a styled Box rather than a native input.

KeyAction
TabMove focus to the switch
Space / EnterToggle
  • Name it. Use label, or aria-label / aria-labelledby when the label is rendered elsewhere.
  • description and error are referenced via aria-describedby.
  • disabled sets aria-disabled and removes the switch from the tab order.
  • onLabel / offLabel are decoration inside the track — they are not a substitute for a name, since they describe the states, not the setting.

Edit this page on GitHub