# Checkbox
> Checkbox is an input control that lets users select one or more options from a list of options.

## Import

```js
import { Checkbox, CheckboxGroup } from '@gemini-suite/vera-react';
```

## Examples

### Basic

<Callout variant="tip">

Use `Checkbox` when selection doesn’t take immediate effect (typically within a form that requires submission).
To turn a state on and off with immediate effect such as enabling or disabling a system feature, consider using [Switch](/components/switch) instead.

One exception to this guideline is using checkboxes as page-level filters that take effect immediately.

</Callout>

```jsx
<Flex flow="column" gap="spacingS">
  <Checkbox.Root defaultChecked={false}>
    <Checkbox.Indicator />
    <Checkbox.Label>{'Unchecked'}</Checkbox.Label>
  </Checkbox.Root>
  <Checkbox.Root defaultChecked={true}>
    <Checkbox.Indicator />
    <Checkbox.Label>{'Checked'}</Checkbox.Label>
  </Checkbox.Root>
  <Checkbox.Root isIndeterminate>
    <Checkbox.Indicator />
    <Checkbox.Label>{'Indeterminate'}</Checkbox.Label>
  </Checkbox.Root>
  <Checkbox.Root isDisabled>
    <Checkbox.Indicator />
    <Checkbox.Label>{'Disabled'}</Checkbox.Label>
  </Checkbox.Root>
  <Checkbox.Root defaultChecked={true} isDisabled>
    <Checkbox.Indicator />
    <Checkbox.Label>{'Checked + disabled'}</Checkbox.Label>
  </Checkbox.Root>
</Flex>
```

### Controlled

It is most common to set up `Checkbox` as a [controlled component](https://reactjs.org/docs/forms.html#controlled-components), meaning that React state drives its value. To achieve this you must provide `isChecked` and `onChange` properties.

<Callout variant="tip">

The `defaultChecked` prop will have no effect in a controlled checkbox.

</Callout>

```jsx
() => {
  const [isChecked, setIsChecked] = React.useState(false);
  const handleChange = event => setIsChecked(event.target.checked);

  return (
    <Checkbox.Root isChecked={isChecked} onChange={handleChange}>
      <Checkbox.Indicator />
      <Checkbox.Label>{'Controlled'}</Checkbox.Label>
    </Checkbox.Root>
  );
};
```

### Indeterminate state

Use `isIndeterminate` prop to convey that a checkbox is partially checked and controls a set of sub-checkboxes.
In the following example, the checkbox is indeterminate when not every descendant is checked.

```jsx
() => {
  const [checkedItems, setCheckedItems] = React.useState([false, false]);

  const everyChecked = checkedItems.every(Boolean);
  const isIndeterminate = checkedItems.some(Boolean) && !everyChecked;

  return (
    <React.Fragment>
      <Checkbox.Root
        isChecked={everyChecked}
        isIndeterminate={isIndeterminate}
        onChange={e => setCheckedItems([e.target.checked, e.target.checked])}
      >
        <Checkbox.Indicator />
        <Checkbox.Label>{'All ingredients'}</Checkbox.Label>
      </Checkbox.Root>
      <Flex
        flow="column"
        gap="spacingXs"
        marginLeft="spacingM"
        marginTop="spacingS"
      >
        <Checkbox.Root
          isChecked={checkedItems[0]}
          onChange={e => setCheckedItems([e.target.checked, checkedItems[1]])}
        >
          <Checkbox.Indicator />
          <Checkbox.Label>{'Ingredient 1'}</Checkbox.Label>
        </Checkbox.Root>
        <Checkbox.Root
          isChecked={checkedItems[1]}
          onChange={e => setCheckedItems([checkedItems[0], e.target.checked])}
        >
          <Checkbox.Indicator />
          <Checkbox.Label>{'Ingredient 2'}</Checkbox.Label>
        </Checkbox.Root>
      </Flex>
    </React.Fragment>
  );
};
```

### Checkbox with help text

In cases where the checkbox requires additional context, you can display this information as help text. This helps keep checkbox labels concise.

<Callout variant="tip">

Avoid lengthy text labels. Be clear and brief with checkbox labels so they are easily scanned.
Label things positively. For example, prefer "Enable notifications" over "Don't send me notifications".

</Callout>

```jsx
<Checkbox.Root defaultChecked>
  <Checkbox.Indicator />
  <Flex flow="column" gap="none">
    <Checkbox.Label>Enable notifications</Checkbox.Label>
    <Checkbox.HelperText>
      We will not send any notifications to your account when turned off.
    </Checkbox.HelperText>
  </Flex>
</Checkbox.Root>
```

### CheckboxGroup

Multiple checkboxes and their labels should be grouped together with a common `CheckboxGroup` component.

`CheckboxGroup` helps managing the checked state of its children `Checkbox` components and conveniently passes some shared props to each.

<Callout variant="tip">

Make sure to pass `value` prop to each checkbox within a group.

</Callout>

```jsx
<CheckboxGroup
  defaultValue={['bulbasaur', 'charmander']}
  onChange={val => console.log(val)}
>
  <Flex flow="column" gap="spacingXs">
    <Checkbox.Root value="bulbasaur">
      <Checkbox.Indicator />
      <Checkbox.Label>{'Bulbasaur'}</Checkbox.Label>
    </Checkbox.Root>
    <Checkbox.Root value="charmander">
      <Checkbox.Indicator />
      <Checkbox.Label>{'Charmander'}</Checkbox.Label>
    </Checkbox.Root>
    <Checkbox.Root value="squirtle">
      <Checkbox.Indicator />
      <Checkbox.Label>{'Squirtle'}</Checkbox.Label>
    </Checkbox.Root>
  </Flex>
</CheckboxGroup>
```

Mark the checkbox group as disabled by passing `true` to the `isDisabled` prop. All descendant inputs will be disabled.

```jsx
<CheckboxGroup isDisabled defaultValue={['bulbasaur', 'charmander']}>
  <Flex flow="column" gap="spacingXs">
    <Checkbox.Root value="bulbasaur">
      <Checkbox.Indicator />
      <Checkbox.Label>{'Bulbasaur'}</Checkbox.Label>
    </Checkbox.Root>
    <Checkbox.Root value="charmander">
      <Checkbox.Indicator />
      <Checkbox.Label>{'Charmander'}</Checkbox.Label>
    </Checkbox.Root>
    <Checkbox.Root value="squirtle">
      <Checkbox.Indicator />
      <Checkbox.Label>{'Squirtle'}</Checkbox.Label>
    </Checkbox.Root>
  </Flex>
</CheckboxGroup>
```

### With Form Field

[Form Field component](/components/forms/form-field) should be used to label groups of related checkboxes. The same goes for connecting helper text and/or validation feedback message.

<Callout variant="tip">

When providing a top-level label for a group of checkbox inputs that are already labelled, it doesn't make sense for the `FormField.Label` to render an HTML `<label>` element. The `as` prop should be provided with another element type, such as `span`.

</Callout>

```jsx
<FormField.Root as={Flex} flow="column">
  <FormField.Label as="span">How do you like your eggs?</FormField.Label>
  <FormField.HelperText>Select all the options that apply</FormField.HelperText>
  <CheckboxGroup>
    <Flex flow="column" gap="spacingXs">
      <Checkbox.Root value="overeasy">
        <Checkbox.Indicator />
        <Checkbox.Label>Overeasy</Checkbox.Label>
      </Checkbox.Root>
      <Checkbox.Root value="hard-boiled">
        <Checkbox.Indicator />
        <Checkbox.Label>Hard-boiled</Checkbox.Label>
      </Checkbox.Root>
      <Checkbox.Root value="scram-boiled">
        <Checkbox.Indicator />
        <Flex flow="column" gap="none">
          <Checkbox.Label>Scram-boiled</Checkbox.Label>
          <Checkbox.HelperText>
            A hardboiled egg that is then scrambled
          </Checkbox.HelperText>
        </Flex>
      </Checkbox.Root>
    </Flex>
  </CheckboxGroup>
</FormField.Root>
```

<Callout variant="important">

Don't validate each checkbox in a group, always treat validation on the group as a whole.

</Callout>

```jsx
() => {
  const [groupValue, setGroupValue] = React.useState([]);

  return (
    <FormField.Root
      as={Flex}
      flow="column"
      isRequired
      validationStatus={groupValue.length === 0 ? 'error' : undefined}
    >
      <FormField.Label as="span">Choose ingredients</FormField.Label>
      <CheckboxGroup value={groupValue} onChange={setGroupValue}>
        <Flex flow="column" gap="spacingXs">
          <Checkbox.Root value="tomato">
            <Checkbox.Indicator />
            <Checkbox.Label>{'Tomato'}</Checkbox.Label>
          </Checkbox.Root>
          <Checkbox.Root value="lettuce">
            <Checkbox.Indicator />
            <Checkbox.Label>{'Lettuce'}</Checkbox.Label>
          </Checkbox.Root>
          <Checkbox.Root value="cucumber">
            <Checkbox.Indicator />
            <Checkbox.Label>{'Cucumber'}</Checkbox.Label>
          </Checkbox.Root>
        </Flex>
      </CheckboxGroup>
      <FormField.FeedbackMessage>
        <FormField.FeedbackIcon />
        {'You must choose at least one ingredient.'}
      </FormField.FeedbackMessage>
    </FormField.Root>
  );
};
```

Checkboxes in a field group should be listed in a logical order (alphabetical, numerical, time-based, etc).

```jsx
<FormField.Root as={Flex} flow="column">
  <FormField.Label as="span">Choose preferred days</FormField.Label>
  <CheckboxGroup>
    <Flex flow="column" gap="spacingXs">
      <Checkbox.Root value="monday">
        <Checkbox.Indicator />
        <Checkbox.Label>Monday</Checkbox.Label>
      </Checkbox.Root>
      <Checkbox.Root value="tuesday">
        <Checkbox.Indicator />
        <Checkbox.Label>Tuesday</Checkbox.Label>
      </Checkbox.Root>
      <Checkbox.Root value="wednesday">
        <Checkbox.Indicator />
        <Checkbox.Label>Wednesday</Checkbox.Label>
      </Checkbox.Root>
      <Checkbox.Root value="thursday">
        <Checkbox.Indicator />
        <Checkbox.Label>Thursday</Checkbox.Label>
      </Checkbox.Root>
      <Checkbox.Root value="friday">
        <Checkbox.Indicator />
        <Checkbox.Label>Friday</Checkbox.Label>
      </Checkbox.Root>
    </Flex>
  </CheckboxGroup>
</FormField.Root>
```

### Standalone checkbox

In some rare cases, you may need to render a standalone checkbox. Make sure to always associate the checkbox with a label and make the label visually hidden.
A standalone checkbox without an accessible label does not describe its purpose.

```jsx
<Checkbox.Root as="label" display="inline" defaultChecked>
  <Checkbox.Indicator />
  <Checkbox.Label as={VisuallyHidden}>Label</Checkbox.Label>
</Checkbox.Root>
```

Alternatively, you may provide `aria-label` property to maintain accessibility:

```jsx
<Checkbox.Root as="label" display="inline" defaultChecked aria-label="Label">
  <Checkbox.Indicator />
</Checkbox.Root>
```

### Sizes

`Checkbox` component comes in two different sizes: `medium` and `small`. By default, it uses `medium` size.

```jsx
<Flex>
  <Checkbox.Root>
    <Checkbox.Indicator />
    <Flex flow="column" gap="none">
      <Checkbox.Label>{'Default'}</Checkbox.Label>
      <Checkbox.HelperText>Extra information.</Checkbox.HelperText>
    </Flex>
  </Checkbox.Root>
  <Checkbox.Root size="small">
    <Checkbox.Indicator />
    <Flex flow="column" gap="none">
      <Checkbox.Label>{'Small'}</Checkbox.Label>
      <Checkbox.HelperText>Extra information.</Checkbox.HelperText>
    </Flex>
  </Checkbox.Root>
</Flex>
```

#### Size inheritance

`Checkbox` automatically inherits size, when placed inside a [FormField component](/components/forms/form-field).

```jsx
<Flex cross="start" gap="spacingXl" wrap="wrap">
  <FormField.Root as={Flex} flow="column" size="medium">
    <FormField.Label as="span">Choose preferred days</FormField.Label>
    <FormField.HelperText>
      Select all the options that apply
    </FormField.HelperText>
    <CheckboxGroup defaultValue={['overeasy']}>
      <Flex flow="column" gap="spacingXs">
        <Checkbox.Root value="overeasy">
          <Checkbox.Indicator />
          <Checkbox.Label>Overeasy</Checkbox.Label>
        </Checkbox.Root>
        <Checkbox.Root value="hard-boiled">
          <Checkbox.Indicator />
          <Checkbox.Label>Hard-boiled</Checkbox.Label>
        </Checkbox.Root>
        <Checkbox.Root value="scram-boiled">
          <Checkbox.Indicator />
          <Flex flow="column" gap="none">
            <Checkbox.Label>Scram-boiled</Checkbox.Label>
            <Checkbox.HelperText>
              A hardboiled egg that is then scrambled
            </Checkbox.HelperText>
          </Flex>
        </Checkbox.Root>
      </Flex>
    </CheckboxGroup>
  </FormField.Root>
  <FormField.Root as={Flex} flow="column" size="small">
    <FormField.Label as="span">Choose preferred days</FormField.Label>
    <FormField.HelperText>
      Select all the options that apply
    </FormField.HelperText>
    <CheckboxGroup defaultValue={['overeasy']}>
      <Flex flow="column" gap="spacingXs">
        <Checkbox.Root value="overeasy">
          <Checkbox.Indicator />
          <Checkbox.Label>Overeasy</Checkbox.Label>
        </Checkbox.Root>
        <Checkbox.Root value="hard-boiled">
          <Checkbox.Indicator />
          <Checkbox.Label>Hard-boiled</Checkbox.Label>
        </Checkbox.Root>
        <Checkbox.Root value="scram-boiled">
          <Checkbox.Indicator />
          <Flex flow="column" gap="none">
            <Checkbox.Label>Scram-boiled</Checkbox.Label>
            <Checkbox.HelperText>
              A hardboiled egg that is then scrambled
            </Checkbox.HelperText>
          </Flex>
        </Checkbox.Root>
      </Flex>
    </CheckboxGroup>
  </FormField.Root>
</Flex>
```

### Customizing appearance

`Checkbox` API allows you to easily implement custom behaviours and appearances.

```jsx
() => {
  const [groupValue, setGroupValue] = React.useState([]);
  const customStyles = {
    borderRadius: '$m',
    padding: '$spacingM',
    border: '1px solid $borderNeutralSubtle'
  };

  return (
    <CheckboxGroup value={groupValue} onChange={setGroupValue}>
      <AutoGrid min="20ch">
        <Checkbox.Root
          as="label"
          value="item1"
          gap="spacingM"
          css={{
            ...customStyles,
            backgroundColor: groupValue.includes('item1')
              ? '$backgroundAccent'
              : '$backgroundNeutralMinimal'
          }}
        >
          <Checkbox.Indicator />
          <Flex flow="column" gap="spacingXs">
            <Checkbox.Label as={Flex} gap="spacingS">
              <Box>Choice A</Box>
              <Label size="small" color="success" variant="subtle">
                Label
              </Label>
            </Checkbox.Label>
            <Checkbox.HelperText>
              Extra information about the choice A
            </Checkbox.HelperText>
          </Flex>
        </Checkbox.Root>
        <Checkbox.Root
          as="label"
          value="item2"
          gap="spacingM"
          css={{
            ...customStyles,
            backgroundColor: groupValue.includes('item2')
              ? '$backgroundAccent'
              : '$backgroundNeutralMinimal'
          }}
        >
          <Checkbox.Indicator />
          <Flex flow="column" gap="spacingXs">
            <Checkbox.Label as={Flex} gap="spacingS">
              <Box>Choice B</Box>
              <Label size="small" color="success" variant="subtle">
                Label
              </Label>
            </Checkbox.Label>
            <Checkbox.HelperText>
              Extra information about the choice B
            </Checkbox.HelperText>
          </Flex>
        </Checkbox.Root>
      </AutoGrid>
    </CheckboxGroup>
  );
};
```

---

## API Reference

### Checkbox.Root

<Callout variant="tip">

In addition to the props below, you can pass [Flex props](/components/layout/flex#api-reference) to control the layout.

</Callout>

| Name               | Type                                                      | Default | Description                                                                                                                                                                                                                                                                                  | Required |
| ------------------ | --------------------------------------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| `as`               | `keyof JSX.IntrinsicElements \| React.ComponentType<any>` | `div`   | Change the component to a different HTML tag or custom component. This will merge the original component props with the props of the supplied element/component and change the underlying DOM node.   For more details, read our [Composition](/get-started/composition#polymorphism) guide. |          |
| `css`              | `StitchesCss`                                             |         | Apply styles directly to a component in a similar way how you would define inline styles. Vera uses [Stitches](https://stitches.dev/) under the hood with a fully-typed API and support for features like tokens, media queries, or variants.                                                |          |
| `value`            | `string \| number`                                        |         | The value to be used in the checkbox input. It will be returned on form submission.                                                                                                                                                                                                          |          |
| `name`             | `string`                                                  |         | Name attribute of the input field in a checkbox. Useful for form submission.                                                                                                                                                                                                                 |          |
| `id`               | `string`                                                  |         | ID assigned to input. Used for `htmlFor` of `Checkbox.Label`. Defaults to a generated ID.                                                                                                                                                                                                    |          |
| `defaultChecked`   | `boolean`                                                 | `false` | When `true` the checkbox will be initially checked.                                                                                                                                                                                                                                          |          |
| `isChecked`        | `boolean`                                                 |         | When `true`, the checkbox will be checked. This makes the checkbox controlled, so passing `onChange` is required to update its value.                                                                                                                                                        |          |
| `onChange`         | `(event: React.ChangeEvent<HTMLInputElement>) => void`    |         | Event handler called when the input checked state changes.                                                                                                                                                                                                                                   |          |
| `onFocus`          | `(event: React.FocusEvent<HTMLInputElement>) => void`     |         | Event handler called when the input receives a focus.                                                                                                                                                                                                                                        |          |
| `onBlur`           | `(event: React.FocusEvent<HTMLInputElement>) => void`     |         | Event handler called when focus has left the input.                                                                                                                                                                                                                                          |          |
| `isIndeterminate`  | `boolean`                                                 |         | When `true`, the checkbox will be indeterminate. This only affects the style of the checkbox and does not modify the `isChecked` property.                                                                                                                                                   |          |
| `isDisabled`       | `boolean`                                                 |         | When `true`, the checkbox will be disabled, preventing the user from interacting with it.                                                                                                                                                                                                    |          |
| `isReadOnly`       | `boolean`                                                 |         | When `true`, the checkbox will be readonly.                                                                                                                                                                                                                                                  |          |
| `isRequired`       | `boolean`                                                 |         | When `true`, the checkbox input is marked as required.                                                                                                                                                                                                                                       |          |
| `validationStatus` | `"error" \| "success" \| "warning"`                       |         | Styles the checkbox to match the status.                                                                                                                                                                                                                                                     |          |
| `size`             | `"medium" \| "small"`                                     |         | Size of the checkbox.                                                                                                                                                                                                                                                                        |          |

### Checkbox.Indicator

| Name  | Type          | Default | Description                                                                                                                                                                                                                                   | Required |
| ----- | ------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| `css` | `StitchesCss` |         | Apply styles directly to a component in a similar way how you would define inline styles. Vera uses [Stitches](https://stitches.dev/) under the hood with a fully-typed API and support for features like tokens, media queries, or variants. |          |

### Checkbox.Label

| Name  | Type                                                      | Default | Description                                                                                                                                                                                                                                                                                  | Required |
| ----- | --------------------------------------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| `as`  | `keyof JSX.IntrinsicElements \| React.ComponentType<any>` | `label` | Change the component to a different HTML tag or custom component. This will merge the original component props with the props of the supplied element/component and change the underlying DOM node.   For more details, read our [Composition](/get-started/composition#polymorphism) guide. |          |
| `css` | `StitchesCss`                                             |         | Apply styles directly to a component in a similar way how you would define inline styles. Vera uses [Stitches](https://stitches.dev/) under the hood with a fully-typed API and support for features like tokens, media queries, or variants.                                                |          |

### Checkbox.HelperText

<Callout variant="tip">

In addition to the props below, you can pass [Text props](/components/typography/text#api-reference).

</Callout>

| Name  | Type          | Default | Description                                                                                                                                                                                                                                   | Required |
| ----- | ------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
| `css` | `StitchesCss` |         | Apply styles directly to a component in a similar way how you would define inline styles. Vera uses [Stitches](https://stitches.dev/) under the hood with a fully-typed API and support for features like tokens, media queries, or variants. |          |

### CheckboxGroup

| Name           | Type                                    | Default | Description                                                                                                          | Required |
| -------------- | --------------------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------- | -------- |
| `defaultValue` | `(string \| number)[]`                  |         | The initial value of the checkbox group                                                                              |          |
| `value`        | `(string \| number)[]`                  |         | Value of the checkbox group. This makes the group controlled, so passing `onChange` is required to update the value. |          |
| `onChange`     | `(value: (string \| number)[]) => void` |         | Event handler called when any children `Checkbox` is checked or unchecked.                                           |          |
| `isDisabled`   | `boolean`                               |         | When `true`, all checkbox inputs within the group will be disabled.                                                  |          |
