Skip to content

Checkbox Group

Provides shared state to a series of checkboxes.

Apples

Usage guidelines

Anatomy

Checkbox Group is composed together with Checkbox. Import the components and place them together:

vue
<script setup lang="ts">
import {
  CheckboxGroup,
  CheckboxIndicator,
  CheckboxRoot,
} from 'base-ui-vue'
</script>

<template>
  <CheckboxGroup>
    <CheckboxRoot>
      <CheckboxIndicator />
    </CheckboxRoot>
  </CheckboxGroup>
</template>

Examples

Labeling a checkbox group

Label the group with aria-labelledby and a sibling label element:

vue
<div id="protocols-label">
Allowed network protocols
</div>

<CheckboxGroup aria-labelledby="protocols-label">
  <!-- checkboxes -->
</CheckboxGroup>

Each checkbox can still be labeled with a wrapping label:

vue
<label>
  <CheckboxRoot value="http" />
  HTTP
</label>

Rendering as a native button

By default, CheckboxRoot renders a <span> element to support enclosing labels. Prefer rendering each checkbox as a native button when using sibling labels (for/id).

vue
<div id="protocols-label">
Allowed network protocols
</div>

<CheckboxGroup aria-labelledby="protocols-label">
  <div>
    <label for="protocol-http">HTTP</label>
    <CheckboxRoot
      id="protocol-http"
      value="http"
      as="button"
      :native-button="true"
    >
      <CheckboxIndicator />
    </CheckboxRoot>
  </div>
</CheckboxGroup>

Native buttons with wrapping labels are supported by using renderless mode so the hidden input is placed outside the label:

vue
<script setup lang="ts">
import { CheckboxGroup, CheckboxRoot, Slot } from 'base-ui-vue'
</script>

<template>
  <div id="protocols-label">Allowed network protocols</div>

  <CheckboxGroup aria-labelledby="protocols-label">
    <CheckboxRoot
      v-slot="{ props, ref }"
      value="http"
      :as="Slot"
      :native-button="true"
    >
      <label>
        <button :ref="ref" v-bind="props" />
        HTTP
      </label>
    </CheckboxRoot>
  </CheckboxGroup>
</template>

Form integration

Use Field and Fieldset for group labeling and form integration:

vue
<script setup lang="ts">
import {
  CheckboxGroup,
  CheckboxIndicator,
  CheckboxRoot,
  FieldRoot,
  FieldsetLegend,
  FieldsetRoot,
  Form,
  FieldItem,
  FieldLabel,
} from 'base-ui-vue'
</script>

<template>
  <Form>
    <FieldRoot name="allowedNetworkProtocols">
      <FieldsetRoot as="div" :render="CheckboxGroup">
        <FieldsetLegend>Allowed network protocols</FieldsetLegend>
        <FieldItem>
          <FieldLabel>
            <CheckboxRoot value="http">
              <CheckboxIndicator />
            </CheckboxRoot>
            HTTP
          </FieldLabel>
        </FieldItem>
        <FieldItem>
          <FieldLabel>
            <CheckboxRoot value="https">
              <CheckboxIndicator />
            </CheckboxRoot>
            HTTPS
          </FieldLabel>
        </FieldItem>
        <FieldItem>
          <FieldLabel>
            <CheckboxRoot value="ssh">
              <CheckboxIndicator />
            </CheckboxRoot>
            SSH
          </FieldLabel>
        </FieldItem>
      </FieldsetRoot>
    </FieldRoot>
  </Form>
</template>

Parent checkbox

You can build a checkbox that controls the other checkboxes in the group:

  1. Make CheckboxGroup a controlled component.
  2. Pass an array of all the child checkbox values to the all-values prop on the CheckboxGroup component.
  3. Add the parent boolean prop to the parent CheckboxRoot.

The group controls the parent checkbox's indeterminate state when some, but not all, child checkboxes are checked.

Nested parent checkbox

Nested groups can use the same pattern for cascading selection:

API reference

PropTypeDefaultDescription
asstring | Component'div'The element or component used for the group root.
valuestring[]undefinedNames of the checkboxes in the group that should be ticked. To render an uncontrolled checkbox group, use the default-value prop instead.
default-valuestring[][]Names of the checkboxes in the group that should be initially ticked. To render a controlled checkbox group, use the value prop instead.
all-valuesstring[][]Names of all checkboxes in the group. Use this when creating a parent checkbox.
disabledbooleanfalseWhether the component should ignore user interaction.
classany | ((state: State) => any)undefinedCSS class applied to the element, or a function that returns a class based on the component's state.
styleStyleValue | ((state: State) => StyleValue)undefinedStyle applied to the element, or a function that returns a style object based on the component's state.
EmitsTypeDescription
value-change(value: string[], details: EventDetails) => voidEmitted when a checkbox in the group is ticked or unticked. Provides the new value as an argument.
AttributeDescription
data-disabledPresent when the checkbox group is disabled.
data-validPresent when the checkbox group is valid.
data-invalidPresent when the checkbox group is invalid.
data-dirtyPresent when the checkbox group's value has changed.
data-touchedPresent when the checkbox group has been touched.
data-filledPresent when the checkbox group has a selected value.
data-focusedPresent when a checkbox in the group is focused.