# Checkbox Field (/components/forms/checkbox-field)

Use `CheckboxField` when someone can choose an option independently of nearby controls. Pass `label`
to name the option, and `description` to clarify what it means.

Use [`CheckboxGroup`](/components/forms/checkbox-group) when related options need a shared label and
validation message.

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

```tsx
import { CheckboxField } from '@luke-ui/react/checkbox-field';

export default () => {
	return <CheckboxField description="Receive updates by email." label="Email notifications" />;
};
```

## Labels [#labels]

Every `CheckboxField` has a visible `label`. The label sits inside a native `<label>`, so pass
textual content only. Place links and buttons next to the checkbox. 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 table row or a settings row,
compose the [Checkbox primitive](/components/primitives/checkbox) 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 selection. `isIndeterminate` communicates a mixed state, such as a parent
option whose child options are only partly selected.

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

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

export default () => {
	return (
		<Comparison>
			<ComparisonItem label="Unchecked">
				<CheckboxField label="Example checkbox" />
			</ComparisonItem>
			<ComparisonItem label="Checked">
				<CheckboxField defaultSelected label="Example checkbox" />
			</ComparisonItem>
			<ComparisonItem label="Indeterminate">
				<CheckboxField isIndeterminate label="Example checkbox" />
			</ComparisonItem>
			<ComparisonItem label="Disabled">
				<CheckboxField isDisabled label="Example checkbox" />
			</ComparisonItem>
			<ComparisonItem label="Disabled and checked">
				<CheckboxField defaultSelected isDisabled label="Example checkbox" />
			</ComparisonItem>
			<ComparisonItem label="Invalid">
				<CheckboxField
					errorMessage="Select this example checkbox to continue."
					label="Example checkbox"
				/>
			</ComparisonItem>
		</Comparison>
	);
};
```

apps/docs/src/examples/checkbox-field/controlled.tsx

```tsx
import { CheckboxField } from '@luke-ui/react/checkbox-field';
import { useState } from 'react';

export default () => {
	const [isSelected, setIsSelected] = useState(false);

	return (
		<CheckboxField
			isSelected={isSelected}
			label={isSelected ? 'Checked' : 'Unchecked'}
			onChange={setIsSelected}
		/>
	);
};
```

## Size [#size]

Use `size` to change the checkbox control. It does not change the label typography. `medium` is the
default. Use `small` in compact layouts.

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

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

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

## Validation [#validation]

Set `isRequired` to require the choice. `CheckboxField` shows its validation message after
validation fails. Pass `errorMessage` only for an error you already have, such as one from a form
library or your server. A non-empty message marks the checkbox invalid. Read
[Validation](/docs/validation) for where messages come from and how to write them.

Inside a [`CheckboxGroup`](/components/forms/checkbox-group#validation), set `isRequired` or pass
`validate` on the child for native validation. Pass controlled or server errors to the group's
`errorMessage`.

apps/docs/src/examples/checkbox-field/validation.tsx

```tsx
import { Button } from '@luke-ui/react/button';
import { CheckboxField } from '@luke-ui/react/checkbox-field';
import { Cluster } from '@luke-ui/react/cluster';
import { Stack } from '@luke-ui/react/stack';
import type { SubmitEvent } from 'react';

function handleSubmit(event: SubmitEvent<HTMLFormElement>) {
	event.preventDefault();
}

export default () => {
	return (
		<form onSubmit={handleSubmit}>
			<Stack gap="space.16">
				<CheckboxField isRequired label="Example checkbox" />
				<Cluster>
					<Button type="submit">Submit</Button>
				</Cluster>
			</Stack>
		</form>
	);
};
```

## Required marker [#required-marker]

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

## Labels with Text [#labels-with-text]

Wrap a checkbox in block `Text` when its label needs a specific text size. The control follows the
inherited line height. It keeps its fixed visual square centred on the first line when the label
wraps. Outside `Text`, it uses the normal compact control size.

apps/docs/src/examples/checkbox-field/first-line-alignment.tsx

```tsx
import { CheckboxField } from '@luke-ui/react/checkbox-field';
import { Stack } from '@luke-ui/react/stack';
import { Text } from '@luke-ui/react/text';

export default () => {
	return (
		<Stack gap="space.16" style={{ maxInlineSize: '18rem' }}>
			<Text elementType="div" typography="caption">
				<CheckboxField label="A longer label keeps its control aligned when it wraps." />
			</Text>
			<Text elementType="div" typography="heading4">
				<CheckboxField label="Larger text keeps the same first-line alignment when it wraps." />
			</Text>
		</Stack>
	);
};
```

## 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 checkbox joins `FormData` when selected. Pass `value` to set the submitted value,
and `form` to associate a checkbox with a `<form>` it does not sit inside.

## Accessibility [#accessibility]

Disabled checkboxes cannot receive focus, and their value cannot change. Read-only checkboxes remain
focusable, so someone who uses a keyboard or assistive technology can still perceive their state.
Keyboard navigation shows a focus ring. Pointer focus does not.

## API [#api]

### CheckboxFieldProps

Props for `CheckboxField`.

`CheckboxFieldProps` 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<CheckboxFieldRenderProps> \| undefined`                      | Class name for the root element.                                                                                               |
| `defaultSelected?`    | `boolean \| undefined`                                                            | Initial selection state for an uncontrolled checkbox.                                                                          |
| `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">` element.                                                                 |
| `isDisabled?`         | `boolean \| undefined`                                                            | Whether the checkbox is disabled.                                                                                              |
| `isIndeterminate?`    | `boolean \| undefined`                                                            | Whether the checkbox displays a mixed selection state.                                                                         |
| `isReadOnly?`         | `boolean \| undefined`                                                            | Whether the checkbox can be read but not changed.                                                                              |
| `isRequired?`         | `boolean \| undefined`                                                            | Whether the checkbox is required before the form can submit.                                                                   |
| `isSelected?`         | `boolean \| undefined`                                                            | Whether the checkbox is selected.                                                                                              |
| `name?`               | `string \| undefined`                                                             | The name of the input, used when submitting an HTML form.                                                                      |
| `onChange?`           | `((isSelected: boolean) => void) \| undefined`                                    | Called when the selection changes.                                                                                             |
| `ref?`                | `Ref<HTMLDivElement>`                                                             | Forwarded to the root element.                                                                                                 |
| `size?`               | `"medium" \| "small" \| undefined`                                                | Visual size of the checkbox 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 checkbox is selected.                                                           |
| `description?`        | `ReactNode`                                                                       | Supporting text shown beneath the checkbox 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 checkbox.                 |
| `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);
```

##### `CheckboxFieldRenderProps`

Declared in [`react-aria-components`](https://www.npmjs.com/package/react-aria-components) (`dist/types/src/Checkbox.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`).
