Skip to content
React NativeBeta

Switch

On/off settings with an async save state that rolls back on failure.

Beta. React Native support is in beta. APIs may change or break between prereleases (npm tag native).

On this page
Web preview — real device may differ
tsx
import { useState } from "react";
import { View } from "react-native";
import { useKitTheme } from "@/component-lib/shared/native";
import { Switch } from "@/component-lib/switch";
import { Section } from "./layout"; // Section and Row: page layout for the demo
 
const wait = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
 
export function SwitchDemo() {
  const { tokens } = useKitTheme();
  const [wifi, setWifi] = useState(true);
  const [failNext, setFailNext] = useState(true);
 
  return (
    <>
      <Section title="Switch · sizes">
        <Switch size="sm" label="Small" defaultChecked />
        <Switch size="md" label="Medium" />
        <Switch size="lg" label="Large" defaultChecked />
      </Section>
 
      <Section title="Switch · states">
        <Switch label="Controlled Wi-Fi" checked={wifi} onCheckedChange={setWifi} description={wifi ? "Connected" : "Off"} />
        <Switch label="Disabled" disabled defaultChecked />
        <Switch label="Read only" readOnly defaultChecked />
        <Switch label="Accept terms" required error="You need to accept the terms to continue." />
        <Switch label="Loading from outside" loading defaultChecked />
      </Section>
 
      <Section title="Switch · async save">
        <Switch
          label="Email me receipts"
          description="Saves for 1.2 s, then succeeds."
          onCheckedChange={() => wait(1200)}
        />
        <Switch
          label="Flaky setting"
          description={failNext ? "Next save fails and the switch goes back." : "Next save succeeds."}
          onCheckedChange={async () => {
            await wait(1200);
            const fail = failNext;
            setFailNext((f) => !f);
            if (fail) throw new Error("Network error");
          }}
        />
      </Section>
 
      <Section title="Switch · settings row (label at start)">
        <View style={{ borderWidth: 1, borderColor: tokens.border, borderRadius: tokens.radius, paddingHorizontal: 12 }}>
          <Switch labelPosition="start" label="Notifications" description="Push alerts for new payments" defaultChecked />
          <Switch labelPosition="start" label="Dark statements" />
        </View>
      </Section>
    </>
  );
}

Install

npx @grampro/kit@native add Switch

Usage

tsx
import { Switch } from "@/component-lib/switch";
 
<Switch label="Email me receipts" onCheckedChange={(on) => saveSetting(on)} />

Props

SwitchProps

PropTypeDescription
checkedbooleanOn or off (controlled).
defaultCheckedbooleanThe starting state when you are not controlling checked.
onCheckedChange(checked: boolean) => void | Promise<unknown>Fires with the new state. Return a promise and the switch stays on the new setting with a busy indicator until it resolves, then puts itself back if it rejects.
labelReactNodeThe text beside the track. Tapping it flips the switch.
descriptionReactNodeA hint under the label, read as the switch's hint.
errorReactNodeThe validation message. Setting it is enough: it is shown and announced.
sizeSwitchSizeDefault md.
labelPositionSwitchLabelPositionDefault end: the label after the track. start puts the track on the right, for settings rows.
loadingbooleanShow the busy state and block presses from outside, e.g. while a form saves.
disabledboolean
readOnlyboolean
requiredboolean
styleStyleProp<ViewStyle> | ((state: SwitchStyleState) => StyleProp<ViewStyle>)
stylesPartial<{ root: StyleProp<ViewStyle>; control: StyleProp<ViewStyle>; track: StyleProp<V…
localeTextPartial<SwitchLocaleText>

Also accepts the props of Omit<PressableProps, "children" | "style" | "onPress" | "disabled" | "role">.

Native and web

  • Sizes are larger for touch than on the web. labelPosition="start" makes a settings row.
  • Web version: Switch on the web.