# Switch

A switch lets someone choose between two mutually exclusive options, like on or off. Activating a switch triggers an immediate change.

## Best practices

### Do

- Use a switch for two mutually exclusive states whose change applies immediately.
- Use a visible label in most contexts.
- Use a noun or short noun phrase to describe the setting.

### Don't

- Use a switch when changes require submission; use a checkbox.
- Use it for an indeterminate state; use a checkbox.
- Label switches with “Turn on” or “Turn off.”

## Behavior and states

- Activating a switch triggers an immediate change.
- Use switches with labels in most cases.
- A switch without a visible label must appear in an obvious context.
- Use hidden label text to identify an icon-only switch to screen readers.
- If you need a component that requires a submission step before applying a change, or if you need to specify an indeterminate state, try a checkbox.

## Default

Source: CoreAI.

[Download source](/coreai-design-system/source/examples/components-switch--default.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { SwitchProps } from "@coreai-ds/react-components";
import type { JSXElement } from "@coreai-ds/react-components";
import { Switch } from "@coreai-ds/react-components";
import * as React from 'react';

export const Default = (props: SwitchProps): JSXElement => (<Switch label="This is a switch" {...props}/>);

export default Default;
```

## API

Generated CoreAI prop summaries, not replacement type declarations. Most native DOM/event and ARIA props are omitted. `?` means optional; JSDoc shows defaults, deprecations, and conditional requirements. Defaults assume the standard CoreAI provider.

### Switch API

Switches enable users to trigger an option on or off through pressing the component.

```ts
interface SwitchProps {
  as?: "input";

  /**
   * Defines the controlled checked state of the Switch.
   * If passed, Switch ignores the `defaultChecked` property.
   * This should only be used if the checked state is to be controlled at a higher level and there is a plan to pass the
   * correct value based on handling `onChange` events and re-rendering.
   * @default false
   */
  checked?: boolean;

  children?: undefined;

  className?: string;

  /**
   * Defines whether the Switch is initially in a checked state or not when rendered.
   * @default false
   */
  defaultChecked?: boolean;

  /**
   * When set, allows the Switch to be focusable even when it has been disabled. This is used in scenarios where it is
   * important to keep a consistent tab order for screen reader and keyboard users.
   * @default false
   */
  disabledFocusable?: boolean;

  /**
   * The track and the thumb sliding over it indicating the on and off status of the Switch.
   */
  indicator?: NonNullable<WithSlotShorthandValue<{ as?: "div"; } & Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & { ref?: ((instance: HTMLDivElement | null) => void) | RefObject<HTMLDivElement> | null; }, "children"> & { children?: any; }> | null> | undefined;

  /**
   * Hidden input that handles the Switch's functionality.
   *
   * This is the PRIMARY slot: all native properties specified directly on the `<Switch>` tag will be applied to this
   * slot, except `className` and `style`, which remain on the root slot.
   */
  input?: ({ as?: "input"; } & Omit<Omit<DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "ref"> & { ref?: ((instance: HTMLInputElement | null) => void) | RefObject<HTMLInputElement> | null; }, "children"> & { children?: undefined; }) | undefined;

  /**
   * The Switch's label.
   */
  label?: WithSlotShorthandValue<Omit<ComponentProps<LabelSlots>, "required"> & { disabled?: boolean; required?: boolean | WithSlotShorthandValue<{ as?: "span"; } & Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "ref"> & { ref?: ((instance: HTMLSpanElement | null) => void) | RefObject<HTMLSpanElement> | null | undefined; }, "children"> & { children?: any; }> | null | undefined; size?: "small" | "medium" | "large" | undefined; weight?: "regular" | "semibold" | undefined; } & RefAttributes<HTMLLabelElement>> | null | undefined;

  /**
   * The position of the label relative to the Switch.
   * @default after
   */
  labelPosition?: "above" | "before" | "after";

  /**
   * Callback to be called when the checked state value changes.
   */
  onChange?: ((ev: ChangeEvent<HTMLInputElement>, data: SwitchOnChangeData) => void);

  ref?: Ref<HTMLInputElement>;

  /**
   * The root element of the Switch.
   *
   * The root slot receives the `className` and `style` specified directly on the `<Switch>` tag.
   * All other native props will be applied to the primary slot: `input`.
   */
  root?: NonNullable<WithSlotShorthandValue<{ as?: "div"; } & Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & { ref?: ((instance: HTMLDivElement | null) => void) | RefObject<HTMLDivElement> | null; }, "children"> & { children?: any; }> | null> | undefined;

  /**
   * The size of the Switch.
   * @default 'medium'
   */
  size?: "small" | "medium";

  style?: CSSProperties;
}
```

## Implementation

CoreAI 0.12.0; Fluent 9.74.9.

[Setup and dependencies](/coreai-design-system/guides/Package.md).

Import components from `@coreai-ds/react-components`. CoreAI guidance above takes precedence over API demonstration examples.

## Checked

Source: Fluent, adapted for CoreAI.

A Switch can be initially checked by passing a value to the `defaultChecked` property, or have its checked value controlled via the `checked` property.

[Download source](/coreai-design-system/source/examples/components-switch--checked.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import * as React from 'react';
import { Switch } from "@coreai-ds/react-components";

export const Checked = (): JSXElement => {
    const [checked, setChecked] = React.useState(true);
    const onChange = React.useCallback((ev: React.ChangeEvent<HTMLInputElement>) => {
        setChecked(ev.currentTarget.checked);
    }, [setChecked]);
    return <Switch checked={checked} onChange={onChange} label={checked ? 'Checked' : 'Unchecked'}/>;
};

export default Checked;
```

## Disabled

Source: Fluent, adapted for CoreAI.

A Switch can be disabled.

[Download source](/coreai-design-system/source/examples/components-switch--disabled.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import * as React from 'react';
import { Switch } from "@coreai-ds/react-components";

const wrapperStyle: React.CSSProperties = {
    display: 'flex',
    flexDirection: 'column',
};

export const Disabled = (): JSXElement => (<div style={wrapperStyle}>
    <Switch disabled label="Unchecked and disabled"/>
    <Switch checked disabled label="Checked and disabled"/>
    <Switch disabledFocusable label="Unchecked and disabled focusable"/>
    <Switch checked disabledFocusable label="Checked and disabled focusable"/>
  </div>);

export default Disabled;
```

## Label

Source: Fluent, adapted for CoreAI.

A label can be provided to the Switch and is positioned above, before or after the component.

[Download source](/coreai-design-system/source/examples/components-switch--label.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import * as React from 'react';
import { Switch } from "@coreai-ds/react-components";

const wrapperStyle: React.CSSProperties = {
    display: 'flex',
    justifyContent: 'space-around',
    width: '100%',
};

export const Label = (): JSXElement => {
    const [checked, setChecked] = React.useState(false);
    const onChange = React.useCallback((ev: React.ChangeEvent<HTMLInputElement>) => {
        setChecked(ev.currentTarget.checked);
    }, [setChecked]);
    const [checked2, setChecked2] = React.useState(false);
    const onChange2 = React.useCallback((ev: React.ChangeEvent<HTMLInputElement>) => {
        setChecked2(ev.currentTarget.checked);
    }, [setChecked2]);
    const [checked3, setChecked3] = React.useState(false);
    const onChange3 = React.useCallback((ev: React.ChangeEvent<HTMLInputElement>) => {
        setChecked3(ev.currentTarget.checked);
    }, [setChecked3]);
    const checkedString = checked ? 'checked' : 'unchecked';
    const checkedString2 = checked2 ? 'checked' : 'unchecked';
    const checkedString3 = checked3 ? 'checked' : 'unchecked';
    return (<div style={wrapperStyle}>
      <Switch checked={checked} label={`With label before and ${checkedString}`} labelPosition="before" onChange={onChange}/>
      <Switch checked={checked2} label={`With label above and ${checkedString2}`} labelPosition="above" onChange={onChange2}/>
      <Switch checked={checked3} label={`With label after and ${checkedString3}`} labelPosition="after" onChange={onChange3}/>
    </div>);
};

export default Label;
```

## Label Wrapping

Source: Fluent, adapted for CoreAI.

The label will wrap if it is wider than the available space. The Switch track will stay aligned to the first line of text.

[Download source](/coreai-design-system/source/examples/components-switch--label-wrapping.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { Switch } from "@coreai-ds/react-components";
import * as React from 'react';

export const LabelWrapping = (): JSXElement => (<Switch style={{ maxWidth: '400px' }} label="Here is an example of a Switch with a long label and it starts to wrap to a second line."/>);

export default LabelWrapping;
```

## Required

Source: Fluent, adapted for CoreAI.

When a Switch is marked as `required`, its label also gets the required styling.

[Download source](/coreai-design-system/source/examples/components-switch--required.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { Switch } from "@coreai-ds/react-components";
import * as React from 'react';

export const Required = (): JSXElement => <Switch required label="Required"/>;

export default Required;
```

## Size

Source: Fluent, adapted for CoreAI.

A Switch can have different sizes.

[Download source](/coreai-design-system/source/examples/components-switch--size.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { SwitchProps } from "@coreai-ds/react-components";
import type { JSXElement } from "@coreai-ds/react-components";
import * as React from 'react';
import { Switch } from "@coreai-ds/react-components";

const wrapperStyle: React.CSSProperties = {
    display: 'flex',
    flexDirection: 'column',
};

export const Size = (props: SwitchProps): JSXElement => {
    return (<div style={wrapperStyle}>
      <Switch label="Small" size="small" {...props}/>
      <Switch label="Medium" size="medium" {...props}/>
    </div>);
};

export default Size;
```

## Resources

- [Figma component](https://www.figma.com/design/eXfSQrRg3poHRgmr0ivN5V/CoreAI-Figma-Library?node-id=6022-126541)
- [Fluent guidance](https://fluent2.microsoft.design/components/web/react/core/switch/usage)