> ## 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.

# SettingsRow

> A labeled switch row with flat control props and native label composition.

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>
  </>;

`SettingsRow` combines the appearance of [ListItem](/ui/primitives/navigation/list-item) with [Switch](/ui/primitives/input/switch). It renders a native label associated with its switch. Your application supplies the row content and owns any preference updates.

<StoryEmbed storyId="ui-components-settingsrow--display" title="Settings row example" height={110} />

## Usage

```tsx theme={null}
import { SettingsRow } from 'twenty-ui/components/settings';
import { IconBell } from 'twenty-ui/icon';

export const NotificationSetting = () => (
  <SettingsRow startElement={<IconBell aria-hidden />}>
    Notifications
  </SettingsRow>
);
```

## Visual options

Compare switch sizes and checked, disabled, and read-only states.

<StoryEmbed storyId="ui-components-settingsrow--catalog" title="Settings row sizes and states" height={520} />

## Configure the switch

Pass [Switch props](/ui/primitives/input/switch) directly to `SettingsRow`. Checked state, event details, disabled and read-only behavior, size, native form configuration, handlers, refs, and render composition configure the switch. `children` supplies the visible row label.

Use `checked` and `onCheckedChange` when your application owns the value. The handler receives the next checked state and Base UI event details. Clicking the label or switch invokes it once. Call `eventDetails.cancel()` to reject a change, and keep your controlled value unchanged when the change is canceled.

```tsx theme={null}
import { useState } from 'react';
import { SettingsRow } from 'twenty-ui/components/settings';
import { IconBell } from 'twenty-ui/icon';

export const NotificationSetting = () => {
  const [enabled, setEnabled] = useState(false);

  return (
    <SettingsRow
      startElement={<IconBell aria-hidden />}
      checked={enabled}
      onCheckedChange={setEnabled}
    >
      Notifications
    </SettingsRow>
  );
};
```

Use `defaultChecked` for an uncontrolled setting. Keyboard users focus the switch and press Space. `disabled` disables the control and applies the row's disabled appearance. `readOnly` prevents changes while keeping the switch focusable.

```tsx theme={null}
import { SettingsRow } from 'twenty-ui/components/settings';

export const WorkspaceSettings = () => (
  <>
    <SettingsRow disabled>Notifications</SettingsRow>
    <SettingsRow readOnly defaultChecked>
      Activity history
    </SettingsRow>
  </>
);
```

## Row content and accessible text

`children`, `startElement`, and `description` accept caller-owned nodes. The children supply the switch's accessible name, and the description supplies its accessible description. Keep content inside the label non-interactive. Use [ListItemButton](/ui/components/navigation/list-item-button) for action rows, or compose [ListItem](/ui/primitives/navigation/list-item) with a link for navigation.

<StoryEmbed storyId="ui-components-settingsrow--with-description" title="Settings row with a description" height={110} />

```tsx theme={null}
import { SettingsRow } from 'twenty-ui/components/settings';

export const WeeklyDigestSetting = () => (
  <SettingsRow defaultChecked description="Sent every Monday" name="digest">
    Weekly digest
  </SettingsRow>
);
```

Set `aria-label`, `aria-labelledby`, or `aria-describedby` to supply your own accessible text for the switch. An explicit `aria-label` replaces the generated name association; explicit `aria-labelledby` and `aria-describedby` values replace the corresponding generated associations.

## Native targets and composition

The ordinary native props configure the control. Label customization has two explicit names:

| Props | Target |
| - | - |
| Native attributes, handlers, `className`, `style`, `ref`, and `render` | The visible Switch root |
| `inputRef`, `name`, `value`, `uncheckedValue`, `required`, and `form` | The Switch's underlying native checkbox |
| `labelRef` and attributes, handlers, classes, and styles supplied through `labelRender` | The outer native label |

The label's `htmlFor` is managed internally and follows `id`, or a generated control ID when no ID is supplied. With the default Switch composition, this ID identifies the underlying checkbox. With `nativeButton`, it identifies the visible button. `ref` targets the visible root in both cases.

Use `labelRender` to customize the row's native label. Preserve a label element and forward the render callback props to your element. Its `props.children` contains the complete row, including the switch. Element composition merges its classes and styles with the row's defaults.

```tsx theme={null}
import { useRef } from 'react';
import { SettingsRow } from 'twenty-ui/components/settings';

export const ComposedNotificationSetting = () => {
  const labelRef = useRef<HTMLLabelElement>(null);
  const controlRef = useRef<HTMLElement>(null);
  const inputRef = useRef<HTMLInputElement>(null);

  return (
    <SettingsRow
      id="notification-control"
      ref={controlRef}
      inputRef={inputRef}
      nativeButton
      render={<button />}
      labelRef={labelRef}
      labelRender={<label id="notification-row" data-setting="notifications" />}
    >
      Notifications
    </SettingsRow>
  );
};
```

`onClick` receives control clicks. Native handlers supplied through `labelRender` receive label events and bubbled control events. Calling `preventDefault()` on a label click prevents its native control activation. Use `onCheckedChange` for preference updates, rather than inferring state from a label click.

The switch defaults to `size="sm"`; use `"md"` for a larger switch. The row height stays the same. `focused` applies the row's highlighted appearance without moving keyboard focus. `className`, `style`, and `render` accept Switch state callbacks and customize the control. Supply label classes and styles through `labelRender` to customize the row.

## Front component renderer

Inside a front component, use the native button composition for a switch nested in the row's label:

```tsx theme={null}
import { SettingsRow } from 'twenty-ui/components/settings';

export const FrontComponentNotificationSetting = () => (
  <SettingsRow nativeButton render={<button />}>
    Notifications
  </SettingsRow>
);
```

This composition activates once when clicking the label or control. The renderer's asynchronous event bridge cannot cancel the host label's default activation in time for a span-based control, which can produce duplicate change callbacks on a direct control click. Native form validation attributes such as `required` are also filtered by the current renderer. Standalone `SettingsRow` retains the full Switch form contract.

## Forms and reset

`name`, `value`, and `required` configure the underlying checkbox for form submission and validation. A checked switch submits its value. An unchecked switch omits the value unless `uncheckedValue` is supplied. Use `form` to associate the input with a form outside the row's parent tree.

For controlled form reset, restore the application-owned checked value in the form's `onReset` handler. Base UI 1.8 does not restore uncontrolled switch state on native form reset. `SettingsRow` preserves this upstream behavior.

```tsx theme={null}
import { useState } from 'react';
import { SettingsRow } from 'twenty-ui/components/settings';
import { Button } from 'twenty-ui/primitives/input';

export const NotificationPreferences = () => {
  const [enabled, setEnabled] = useState(true);

  return (
    <form onReset={() => setEnabled(true)}>
      <SettingsRow
        checked={enabled}
        onCheckedChange={setEnabled}
        name="notifications"
        value="enabled"
        uncheckedValue="disabled"
      >
        Notifications
      </SettingsRow>
      <Button type="reset">Reset</Button>
    </form>
  );
};
```

## Props

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

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

<ParamField body="children" type="ReactNode" required>
  Visible label and default accessible name of the switch. Use non-interactive node content.
</ParamField>

<ParamField body="className" type="string | ((state: SwitchRootState) => string | undefined)">
  Customizes the visible Switch root and accepts a Switch state callback.
</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="description" type="ReactNode">
  Non-interactive supporting node content, used as the default accessible description of the switch.
</ParamField>

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

<ParamField body="focused" type="boolean" default="false">
  Applies the highlighted row style without moving keyboard focus.
</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">
  Identifies the associated checkbox, or the visible root with nativeButton. The label association follows this ID.
</ParamField>

<ParamField body="inputRef" type="Ref<HTMLInputElement>">
  Targets the underlying native checkbox.
</ParamField>

<ParamField body="labelRef" type="Ref<HTMLLabelElement>">
  Targets the outer native label.
</ParamField>

<ParamField body="labelRender" type="ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, {}>">
  Customizes the outer native label with its complete composed row children. Preserve a label element and forward its props to retain control association.
</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)">
  Receives the next checked value and Base UI event details. Controlled callers own accepted state updates; cancellation prevents a change.
</ParamField>

<ParamField body="onClick" type="((event: BaseUIEvent<MouseEvent<HTMLSpanElement, MouseEvent>>) => void)">
  Native click handler for the visible Switch root.
</ParamField>

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

<ParamField body="ref" type="Ref<HTMLSpanElement>">
  Targets the visible Switch root, which defaults to a span.
</ParamField>

<ParamField body="render" type="ReactElement<unknown, string | JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, SwitchRootState>">
  Customizes the visible Switch root with control props and Switch state. Use nativeButton when composing a button.
</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="sm">
  Visual size of the switch. Defaults to sm.
</ParamField>

<ParamField body="startElement" type="ReactNode">
  Non-interactive node content before the label.
</ParamField>

<ParamField body="style" type="CSSProperties | ((state: SwitchRootState) => CSSProperties | undefined)">
  Customizes the visible Switch root and accepts a Switch state callback.
</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>


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