# Switch Field (/components/forms/switch-field)

Use `SwitchField` for a setting someone turns on or off. Pass `label` to name the setting, and
`description` to clarify what it changes.

apps/docs/src/examples/switch-field/basic.tsx

```tsx
import { SwitchField } from '@luke-ui/react/switch-field';

export default () => {
	return <SwitchField description="Example description" label="Example switch" />;
};
```

## Best practices [#best-practices]

Use a switch for an immediate change, such as a preference that saves straight away. Use a
[`CheckboxField`](/components/forms/checkbox-field) for a choice that someone submits with a form,
such as accepting terms.

## Labels [#labels]

Every `SwitchField` has a visible `label`. The label sits inside a native `<label>`, so pass textual
content only. Place links and buttons next to the switch. Inline typography such as `Strong` works
inside the label. Set `slot={null}` on a `Text` you place there, as the
[Checkbox primitive](/components/primitives/checkbox#text-in-the-label) describes.

When another part of the layout draws the visible label, such as a settings row, compose the
[Switch primitive](/components/primitives/switch) and name the control with `aria-labelledby`.

## States [#states]

Use `defaultSelected` for an uncontrolled initial value, or pair `isSelected` with `onChange` when
application state owns the setting. Set `isReadOnly` to keep the current value while a change is
saving.

apps/docs/src/examples/switch-field/states.tsx

```tsx
import { SwitchField } from '@luke-ui/react/switch-field';
import { Comparison, ComparisonItem } from '#docs';

export default () => {
	return (
		<Comparison>
			<ComparisonItem label="Off">
				<SwitchField label="Example switch" />
			</ComparisonItem>
			<ComparisonItem label="On">
				<SwitchField defaultSelected label="Example switch" />
			</ComparisonItem>
			<ComparisonItem label="Disabled">
				<SwitchField isDisabled label="Example switch" />
			</ComparisonItem>
			<ComparisonItem label="Disabled and on">
				<SwitchField defaultSelected isDisabled label="Example switch" />
			</ComparisonItem>
			<ComparisonItem label="Invalid">
				<SwitchField
					errorMessage="Turn on this example switch to continue."
					label="Example switch"
				/>
			</ComparisonItem>
		</Comparison>
	);
};
```

## Size [#size]

Use `size` to change the switch control. It does not change the label typography. `medium` is the
default.

apps/docs/src/examples/switch-field/sizes.tsx

```tsx
import { SwitchField } from '@luke-ui/react/switch-field';
import { Comparison, ComparisonItem } from '#docs';

export default () => {
	return (
		<Comparison>
			<ComparisonItem label="small">
				<SwitchField defaultSelected label="Example switch" size="small" />
			</ComparisonItem>
			<ComparisonItem label="medium">
				<SwitchField defaultSelected label="Example switch" size="medium" />
			</ComparisonItem>
		</Comparison>
	);
};
```

## Validation [#validation]

Pass `errorMessage` for an error you already have, such as one from your server. A non-empty message
marks the switch invalid. Set `isRequired` only when the switch must be on before a form submits,
and pass `validate` for a custom rule. Read [Validation](/docs/validation) for where messages come
from and how to write them.

By default, a required switch shows a marker after its `label`. Read
[Required fields](/docs/forms#required-fields) for the `necessityIndicator` values.

## IDs and refs [#ids-and-refs]

`id`, `className`, and `ref` target the root element. `inputId` and `inputRef` target the input.

## Form values [#form-values]

Pass `name` so the switch joins `FormData` while it is on. Pass `value` to set the submitted value,
and `form` to associate a switch with a `<form>` it does not sit inside.

## Accessibility [#accessibility]

A switch has the `switch` role, so assistive technology announces it as on or off. Space toggles it
from the keyboard. Disabled switches cannot receive focus. Read-only switches remain focusable, so
someone who uses a keyboard or assistive technology can still perceive their state.

## API [#api]

### SwitchFieldProps

Props for `SwitchField`.

`SwitchFieldProps` also accepts compatible DOM and ARIA attributes and event handlers for its rendered element.

| Prop                  | Type                                                                              | Description                                                                                                                    |
| --------------------- | --------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `aria-describedby?`   | `string`                                                                          | Identifies the element (or elements) that describes the object.                                                                |
| `aria-details?`       | `string`                                                                          | Identifies the element (or elements) that provide a detailed, extended description for the object.                             |
| `aria-errormessage?`  | `string`                                                                          | Identifies the element that provides an error message for the object.                                                          |
| `onKeyDown?`          | `(e: KeyboardEvent) => void`                                                      | Handler that is called when a key is pressed.                                                                                  |
| `onKeyUp?`            | `(e: KeyboardEvent) => void`                                                      | Handler that is called when a key is released.                                                                                 |
| `onFocus?`            | `(e: React.FocusEvent<Element, Element>) => void`                                 | Handler that is called when the element receives focus.                                                                        |
| `onBlur?`             | `(e: React.FocusEvent<Element, Element>) => void`                                 | Handler that is called when the element loses focus.                                                                           |
| `onFocusChange?`      | `(isFocused: boolean) => void`                                                    | Handler that is called when the element's focus status changes.                                                                |
| `onPress?`            | `(e: PressEvent) => void`                                                         | Handler that is called when the press is released over the target.                                                             |
| `onPressStart?`       | `(e: PressEvent) => void`                                                         | Handler that is called when a press interaction starts.                                                                        |
| `onPressEnd?`         | `(e: PressEvent) => void`                                                         | Handler that is called when a press interaction ends, either over the target or when the pointer leaves the target.            |
| `onPressChange?`      | `(isPressed: boolean) => void`                                                    | Handler that is called when the press state changes.                                                                           |
| `onPressUp?`          | `(e: PressEvent) => void`                                                         | Handler that is called when a press is released over the target, regardless of whether it started on the target or not.        |
| `autoFocus?`          | `boolean`                                                                         | Whether the element should receive focus on render.                                                                            |
| `className?`          | `ClassNameOrFunction<SwitchFieldRenderProps> \| undefined`                        | Class name for the root element.                                                                                               |
| `defaultSelected?`    | `boolean \| undefined`                                                            | Initial selection state for an uncontrolled switch.                                                                            |
| `form?`               | `string \| undefined`                                                             | The `<form>` element to associate the input with, by id.                                                                       |
| `id?`                 | `string`                                                                          | Element id for the root element. Use `inputId` for the input.                                                                  |
| `inputId?`            | `string \| undefined`                                                             | Element id for the input and the `for` of a `FieldLabel` in the root. Defaults to a generated id.                              |
| `inputRef?`           | `React.Ref<HTMLInputElement \| null> \| undefined`                                | Forwarded to the underlying `<input type="checkbox" role="switch">` element.                                                   |
| `isDisabled?`         | `boolean \| undefined`                                                            | Whether the switch is disabled.                                                                                                |
| `isReadOnly?`         | `boolean \| undefined`                                                            | Whether the switch can be read but not changed.                                                                                |
| `isRequired?`         | `boolean \| undefined`                                                            | Whether the switch must be on before the form can submit.                                                                      |
| `isSelected?`         | `boolean \| undefined`                                                            | Whether the switch is on.                                                                                                      |
| `name?`               | `string \| undefined`                                                             | The name of the input, used when submitting an HTML form.                                                                      |
| `onChange?`           | `((isSelected: boolean) => void) \| undefined`                                    | Called when the switch turns on or off.                                                                                        |
| `ref?`                | `Ref<HTMLDivElement>`                                                             | Forwarded to the root element.                                                                                                 |
| `size?`               | `"medium" \| "small" \| undefined`                                                | Visual size of the switch control. Default: `'medium'`                                                                         |
| `validate?`           | `((value: boolean) => true \| ValidationError \| null \| undefined) \| undefined` | Custom validation function run against the selection. Return a message, or `true`/`null` when valid.                           |
| `validationBehavior?` | `"aria" \| "native" \| undefined`                                                 | When native HTML form validation runs. Default: `'native'`                                                                     |
| `value?`              | `string \| undefined`                                                             | The value submitted with an HTML form when the switch is on.                                                                   |
| `description?`        | `ReactNode`                                                                       | Supporting text shown beneath the switch label.                                                                                |
| `errorMessage?`       | `ReactNode`                                                                       | Validation message for a controlled error. A non-empty message marks the field invalid.                                        |
| `label`               | `Exclude<ReactNode, boolean \| null \| undefined>`                                | Visible label. Pass non-empty, textual, non-interactive content. Place links and buttons outside the switch.                   |
| `necessityIndicator?` | `NecessityIndicator`                                                              | Controls how the label identifies required or optional values. Inherits from `Form`, or uses `'required-asterisk'` when unset. |

#### Type definitions

These are the types that this table's signatures and the definitions below name. TypeScript's built-in types, such as `Omit` and `ReadonlyArray`, are not listed.

##### `NecessityIndicator`

```ts
type NecessityIndicator = 'required-asterisk'
  | 'required-label'
  | 'optional-label';
```

##### `KeyboardEvent`

Declared in [`@react-types/shared`](https://www.npmjs.com/package/@react-types/shared) (`src/events.d.ts`).

```ts
type KeyboardEvent = BaseEvent<ReactKeyboardEvent<any>>;
```

Refers to `BaseEvent` and `KeyboardEvent` from `@types/react`.

##### `BaseEvent`

Declared in [`@react-types/shared`](https://www.npmjs.com/package/@react-types/shared) (`src/events.d.ts`).

##### `KeyboardEvent` from `@types/react` (written as `ReactKeyboardEvent`)

Declared in [`@types/react`](https://www.npmjs.com/package/@types/react) (`index.d.ts`).

##### `FocusEvent`

Declared in [`@types/react`](https://www.npmjs.com/package/@types/react) (`index.d.ts`).

##### `PressEvent`

Declared in [`@react-types/shared`](https://www.npmjs.com/package/@react-types/shared) (`src/events.d.ts`).

##### `ClassNameOrFunction`

Declared in [`react-aria-components`](https://www.npmjs.com/package/react-aria-components) (`dist/types/src/utils.d.ts`).

```ts
type ClassNameOrFunction<T> = string | ((values: T & {
  defaultClassName: string | undefined;
}) => string);
```

##### `SwitchFieldRenderProps`

Declared in [`react-aria-components`](https://www.npmjs.com/package/react-aria-components) (`dist/types/src/Switch.d.ts`).

##### `Ref`

Declared in [`@types/react`](https://www.npmjs.com/package/@types/react) (`index.d.ts`).

```ts
type Ref<T> = RefCallback<T>
  | RefObject<T | null>
  | null;
```

Refers to `RefCallback` and `RefObject`.

##### `RefCallback`

Declared in [`@types/react`](https://www.npmjs.com/package/@types/react) (`index.d.ts`).

##### `RefObject`

Declared in [`@types/react`](https://www.npmjs.com/package/@types/react) (`index.d.ts`).

##### `ValidationError`

Declared in [`@react-types/shared`](https://www.npmjs.com/package/@react-types/shared) (`src/inputs.d.ts`).

```ts
type ValidationError = string | string[];
```

##### `ReactNode`

Declared in [`@types/react`](https://www.npmjs.com/package/@types/react) (`index.d.ts`).

```ts
type ReactNode = ReactElement
  | string
  | number
  | bigint
  | Iterable<ReactNode>
  | ReactPortal
  | boolean
  | null
  | undefined
  | DO_NOT_USE_OR_YOU_WILL_BE_FIRED_EXPERIMENTAL_REACT_NODES[keyof DO_NOT_USE_OR_YOU_WILL_BE_FIRED_EXPERIMENTAL_REACT_NODES]
  | Promise<AwaitedReactNode>;
```

Refers to `ReactElement`, `ReactPortal`, `DO_NOT_USE_OR_YOU_WILL_BE_FIRED_EXPERIMENTAL_REACT_NODES`, and `AwaitedReactNode`.

##### `ReactElement`

Declared in [`@types/react`](https://www.npmjs.com/package/@types/react) (`index.d.ts`).

##### `ReactPortal`

Declared in [`@types/react`](https://www.npmjs.com/package/@types/react) (`index.d.ts`).

##### `DO_NOT_USE_OR_YOU_WILL_BE_FIRED_EXPERIMENTAL_REACT_NODES`

Declared in [`@types/react`](https://www.npmjs.com/package/@types/react) (`index.d.ts`).

##### `AwaitedReactNode`

Declared in [`@types/react`](https://www.npmjs.com/package/@types/react) (`index.d.ts`).
