# Switch (React Native)

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

GramproKit for React Native · Forms · Beta · Source: https://kit.gramproindia.com/native/docs/switch

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

_Interactive demo:_ [open the live example](https://kit.gramproindia.com/native/docs/switch). The example's source:

```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

```bash
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

| Prop | Type | Description |
|---|---|---|
| `checked` | `boolean` | On or off (controlled). |
| `defaultChecked` | `boolean` | The 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. |
| `label` | `ReactNode` | The text beside the track. Tapping it flips the switch. |
| `description` | `ReactNode` | A hint under the label, read as the switch's hint. |
| `error` | `ReactNode` | The validation message. Setting it is enough: it is shown and announced. |
| `size` | `SwitchSize` | Default `md`. |
| `labelPosition` | `SwitchLabelPosition` | Default `end`: the label after the track. `start` puts the track on the right, for settings rows. |
| `loading` | `boolean` | Show the busy state and block presses from outside, e.g. while a form saves. |
| `disabled` | `boolean` |   |
| `readOnly` | `boolean` |   |
| `required` | `boolean` |   |
| `style` | `StyleProp<ViewStyle> \| ((state: SwitchStyleState) => StyleProp<ViewStyle>)` |   |
| `styles` | `Partial<{ root: StyleProp<ViewStyle>; control: StyleProp<ViewStyle>; track: StyleProp<V…` |   |
| `localeText` | `Partial<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](https://kit.gramproindia.com/switch).
