> ## Documentation Index
> Fetch the complete documentation index at: https://docs.twenty.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Switch

> A labeled on or off control with controlled and uncontrolled state.

export const StoryEmbed = ({storyId, title, height = 120}) => <>
    <Tabs>
      <Tab title="Light">
        <iframe title={`${title} (light)`} src={`https://storybook.twenty.com/iframe.html?id=${storyId}&viewMode=story&globals=colorScheme:light`} width="100%" height={height} loading="lazy" allow="clipboard-write" style={{
  border: 0
}} />
      </Tab>
      <Tab title="Dark">
        <iframe title={`${title} (dark)`} src={`https://storybook.twenty.com/iframe.html?id=${storyId}&viewMode=story&globals=colorScheme:dark`} width="100%" height={height} loading="lazy" allow="clipboard-write" style={{
  border: 0
}} />
      </Tab>
    </Tabs>
    <a href={`https://storybook.twenty.com/?path=/story/${storyId}`}>
      Open in Storybook
    </a>
  </>;

Use `Switch` for an on or off preference. Give the control a visible label or an accessible name.

<StoryEmbed storyId="ui-input-switch-switch--display" title="Switch example" height={90} />

## Usage

### Uncontrolled state

Use `defaultChecked` to set the initial checked state. The switch owns subsequent changes.

```tsx theme={null}
import { useId } from 'react';
import { Switch } from 'twenty-ui/primitives/input';
import { Text } from 'twenty-ui/primitives/typography';

export const NotificationsPreference = () => {
  const switchId = useId();

  return (
    <label
      htmlFor={switchId}
      style={{ display: 'inline-flex', alignItems: 'center', gap: 8 }}
    >
      <Switch id={switchId} name="notifications" />
      <Text render={<span />}>Email notifications</Text>
    </label>
  );
};
```

## Visual choices

Compare the two sizes in on, off, disabled, read-only, and focus states. Use the enabled examples to try toggling.

<StoryEmbed storyId="ui-input-switch-switch--catalog" title="Visual choices for switch" height={440} />

## Controlled state

Pass `checked` and update it with `onCheckedChange` to own the same preference in React state.

```tsx theme={null}
import { useId, useState } from 'react';
import { Switch } from 'twenty-ui/primitives/input';
import { Text } from 'twenty-ui/primitives/typography';

export const NotificationsPreference = () => {
  const switchId = useId();
  const [checked, setChecked] = useState(false);

  return (
    <label
      htmlFor={switchId}
      style={{ display: 'inline-flex', alignItems: 'center', gap: 8 }}
    >
      <Switch
        id={switchId}
        name="notifications"
        checked={checked}
        onCheckedChange={setChecked}
      />
      <Text render={<span />}>Email notifications</Text>
    </label>
  );
};
```

`onCheckedChange` receives the next boolean and event details. The `size` prop accepts `sm` or `md` and defaults to `md`.

For a consistent full-width row with an icon, description, and switch, use [SettingsRow](/ui/components/settings/settings-row).

## Keyboard and forms

Tab moves focus to the switch; Space toggles it. Clicking its associated label also toggles it. Use `disabled` to prevent interaction or `readOnly` to retain a focusable control whose value cannot be changed.

A named switch submits its value when checked. Use `value` to customize that value, and `uncheckedValue` if the form should also submit a value when it is off.

## Parts and custom content

`Switch` assembles the styled root and its default thumb. Use `Switch.Root` with `Switch.Thumb` to own the thumb content. Root owns state and track appearance; Thumb renders the content you supply.

```tsx theme={null}
import { Switch } from 'twenty-ui/primitives/input';

export const CustomPreference = () => (
  <Switch.Root aria-label="Updates" defaultChecked>
    <Switch.Thumb></Switch.Thumb>
  </Switch.Root>
);
```

`SwitchRootProps` and `SwitchThumbProps` are public types exported from `twenty-ui/primitives/input`. Both parts accept native attributes, handlers, refs, `render`, and state-based `className` and `style` callbacks. Root's `ref` targets the visible control; `inputRef` targets the native input. The part ref targets its rendered element. Pass `nativeButton` with `render={<button />}` when replacing Root with a button. Appearance props belong on Root; explicit classes and styles are merged with the defaults.

Thumb receives the current checked, disabled, readOnly, required, and Field state. Its position follows the reading direction.

<StoryEmbed storyId="ui-input-switch-parts--composition" title="Switch part composition" height={90} />

The callable assembly and its `SwitchProps` type remain supported. Replace the assembly with Root and its part when supplying custom thumb content instead of appending another part to the assembly's children.

For controlled form reset, handle the form's `onReset` and restore `checked` to your initial value. Base UI 1.8 does not restore uncontrolled component state on native form reset. `required`, `form`, `value`, and `uncheckedValue` keep the upstream native input behavior.

## Props

The reference includes component-specific and inherited Base UI props. Native attributes such as `aria-label` and `data-*` are also accepted.

<ParamField body="checked" type="boolean">
  Whether the switch is currently active.

  To render an uncontrolled switch, use the `defaultChecked` prop instead.
</ParamField>

<ParamField body="className" type="string | ((state: SwitchRootState) => string | undefined)">
  CSS class applied to the element, or a function that
  returns a class based on the component's state.
</ParamField>

<ParamField body="defaultChecked" type="boolean" default="false">
  Whether the switch is initially active.

  To render a controlled switch, use the `checked` prop instead.
</ParamField>

<ParamField body="disabled" type="boolean" default="false">
  Whether the component should ignore user interaction.
</ParamField>

<ParamField body="form" type="string">
  Identifies the form that owns the hidden input.
  Useful when the switch is rendered outside the form.
</ParamField>

<ParamField body="id" type="string">
  The id of the hidden input element.

  When `nativeButton` is `true`, the id is applied to the root element.
</ParamField>

<ParamField body="inputRef" type="Ref<HTMLInputElement>">
  A ref to access the hidden `<input>` element.
</ParamField>

<ParamField body="name" type="string">
  Identifies the field when a form is submitted.
</ParamField>

<ParamField body="nativeButton" type="boolean" default="false">
  Whether the component renders a native `<button>` element when replacing it
  via the `render` prop.
  Set to `true` if the rendered element is a native button.
</ParamField>

<ParamField body="onCheckedChange" type="((checked: boolean, eventDetails: { reason: &#x22;none&#x22;; event: Event; cancel: () => void; allowPropagation: () => void; isCanceled: boolean; isPropagationAllowed: boolean; trigger: Element | undefined; }) => void)">
  Event handler called when the switch is activated or deactivated.
</ParamField>

<ParamField body="readOnly" type="boolean" default="false">
  Whether the user should be unable to activate or deactivate the switch.
</ParamField>

<ParamField body="render" type="ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, SwitchRootState>">
  Allows you to replace the component's HTML element
  with a different tag, or compose it with another component.

  Accepts a `ReactElement` or a function that returns the element to render.
</ParamField>

<ParamField body="required" type="boolean" default="false">
  Whether the user must activate the switch before submitting a form.
</ParamField>

<ParamField body="size" type="&#x22;md&#x22; | &#x22;sm&#x22;" default="md">
  Visual size of the switch.
</ParamField>

<ParamField body="style" type="CSSProperties | ((state: SwitchRootState) => CSSProperties | undefined)">
  Style applied to the element, or a function that
  returns a style object based on the component's state.
</ParamField>

<ParamField body="uncheckedValue" type="string">
  The value submitted with the form when the switch is off.
  By default, unchecked switches do not submit any value, matching native checkbox behavior.
</ParamField>

<ParamField body="value" type="string">
  The value submitted with the form when the switch is on.
  By default, switch submits the "on" value, matching native checkbox behavior.
</ParamField>

### Switch.Root

<ParamField body="Root.checked" type="boolean">
  Whether the switch is currently active.

  To render an uncontrolled switch, use the `defaultChecked` prop instead.
</ParamField>

<ParamField body="Root.className" type="string | ((state: SwitchRootState) => string | undefined)">
  CSS class applied to the element, or a function that
  returns a class based on the component's state.
</ParamField>

<ParamField body="Root.defaultChecked" type="boolean" default="false">
  Whether the switch is initially active.

  To render a controlled switch, use the `checked` prop instead.
</ParamField>

<ParamField body="Root.disabled" type="boolean" default="false">
  Whether the component should ignore user interaction.
</ParamField>

<ParamField body="Root.form" type="string">
  Identifies the form that owns the hidden input.
  Useful when the switch is rendered outside the form.
</ParamField>

<ParamField body="Root.id" type="string">
  The id of the hidden input element.

  When `nativeButton` is `true`, the id is applied to the root element.
</ParamField>

<ParamField body="Root.inputRef" type="Ref<HTMLInputElement>">
  A ref to access the hidden `<input>` element.
</ParamField>

<ParamField body="Root.name" type="string">
  Identifies the field when a form is submitted.
</ParamField>

<ParamField body="Root.nativeButton" type="boolean" default="false">
  Whether the component renders a native `<button>` element when replacing it
  via the `render` prop.
  Set to `true` if the rendered element is a native button.
</ParamField>

<ParamField body="Root.onCheckedChange" type="((checked: boolean, eventDetails: { reason: &#x22;none&#x22;; event: Event; cancel: () => void; allowPropagation: () => void; isCanceled: boolean; isPropagationAllowed: boolean; trigger: Element | undefined; }) => void)">
  Event handler called when the switch is activated or deactivated.
</ParamField>

<ParamField body="Root.readOnly" type="boolean" default="false">
  Whether the user should be unable to activate or deactivate the switch.
</ParamField>

<ParamField body="Root.render" type="ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, SwitchRootState>">
  Allows you to replace the component's HTML element
  with a different tag, or compose it with another component.

  Accepts a `ReactElement` or a function that returns the element to render.
</ParamField>

<ParamField body="Root.required" type="boolean" default="false">
  Whether the user must activate the switch before submitting a form.
</ParamField>

<ParamField body="Root.size" type="&#x22;md&#x22; | &#x22;sm&#x22;" default="md">
  Visual size of the switch.
</ParamField>

<ParamField body="Root.style" type="CSSProperties | ((state: SwitchRootState) => CSSProperties | undefined)">
  Style applied to the element, or a function that
  returns a style object based on the component's state.
</ParamField>

<ParamField body="Root.uncheckedValue" type="string">
  The value submitted with the form when the switch is off.
  By default, unchecked switches do not submit any value, matching native checkbox behavior.
</ParamField>

<ParamField body="Root.value" type="string">
  The value submitted with the form when the switch is on.
  By default, switch submits the "on" value, matching native checkbox behavior.
</ParamField>

### Switch.Thumb

<ParamField body="Thumb.className" type="string | ((state: SwitchThumbState) => string | undefined)">
  CSS class applied to the element, or a function that
  returns a class based on the component's state.
</ParamField>

<ParamField body="Thumb.render" type="ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, SwitchThumbState>">
  Allows you to replace the component's HTML element
  with a different tag, or compose it with another component.

  Accepts a `ReactElement` or a function that returns the element to render.
</ParamField>

<ParamField body="Thumb.style" type="CSSProperties | ((state: SwitchThumbState) => CSSProperties | undefined)">
  Style applied to the element, or a function that
  returns a style object based on the component's state.
</ParamField>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.