---
title: CheckboxGroup
description: Multi-select checkbox group with card, list, and table layout variants.
sidebar:
  order: 7
search:
  tags: [multiple selection, checked, options, table]
---

# CheckboxGroup

> Multi-select checkbox group with card, list, and table layout variants.

## Import

```tsx
import { CheckboxGroup } from 'moraine'
```

## Slot Structure

Fieldset with an optional legend grouping multiple Checkbox items.

```text
root
└── fieldset
    ├── legend (optional)
    └── root (Checkbox, ×n)
```

## Examples

### Variants

List, card, and table variants with shared items data.

```tsx
function Variants() {
  const ITEMS = [
    { value: 'alpha', label: 'Alpha', description: 'Primary rollout channel' },
    { value: 'beta', label: 'Beta', description: 'Early access channel' },
    { value: 'stable', label: 'Stable', description: 'Production channel' },
  ]

  return (
    <div class="gap-4 grid lg:grid-cols-3 sm:grid-cols-2">
      <div class="p-4 b-(1 border) rounded-lg">
        <CheckboxGroup legend="List" items={ITEMS} defaultValue={['alpha']} />
      </div>
      <div class="p-4 b-(1 border) rounded-lg">
        <CheckboxGroup legend="Card" items={ITEMS} variant="card" defaultValue={['beta']} />
      </div>
      <div class="p-4 b-(1 border) rounded-lg">
        <CheckboxGroup legend="Table" items={ITEMS} variant="table" defaultValue={['stable']} />
      </div>
    </div>
  )
}
```

### Sizes

Size scale from xs to xl in card variant.

```tsx
function Sizes() {
  const ITEMS = [
    { value: 'alpha', label: 'Alpha', description: 'Primary rollout channel' },
    { value: 'beta', label: 'Beta', description: 'Early access channel' },
    { value: 'stable', label: 'Stable', description: 'Production channel' },
  ]

  const SIZES = ['xs', 'sm', 'md', 'lg', 'xl'] as const

  return (
    <div class="gap-3 grid lg:grid-cols-3 sm:grid-cols-2">
      <For each={SIZES}>
        {(size) => (
          <div class="p-4 b-(1 border) rounded-lg">
            <CheckboxGroup
              legend={`Size ${size}`}
              items={ITEMS}
              variant="card"
              size={size}
              defaultValue={size === 'xs' ? ['alpha'] : ['stable']}
            />
          </div>
        )}
      </For>
    </div>
  )
}
```

### Orientation

Vertical and horizontal layouts with the same item set.

```tsx
function Orientation() {
  return (
    <div class="gap-4 grid md:grid-cols-2">
      <div class="p-4 b-(1 border) rounded-lg space-y-1">
        <CheckboxGroup legend="Vertical" items={ITEMS} defaultValue={['beta']} />
      </div>
      <div class="p-4 b-(1 border) rounded-lg space-y-1">
        <CheckboxGroup
          legend="Horizontal"
          items={HORIZONTAL_ITEMS}
          orientation="horizontal"
          defaultValue={['alpha']}
          classes={{
            fieldset: 'flex-wrap',
            item: 'min-w-26 flex-1',
          }}
        />
      </div>
    </div>
  )
}
```

### Indicator

Start/end/hidden indicator positions in list layout.

```tsx
function Indicator() {
  return (
    <div class="gap-4 grid md:grid-cols-2 xl:grid-cols-3">
      <For each={INDICATORS}>
        {(indicator) => (
          <div class="p-4 b-(1 border) rounded-lg space-y-1">
            <p class="text-xs text-muted-foreground">Indicator: {indicator}</p>
            <CheckboxGroup
              legend="Channels"
              items={ITEMS}
              indicator={indicator}
              defaultValue={['beta']}
            />
          </div>
        )}
      </For>
    </div>
  )
}
```

### Controlled + Disabled Items

Controlled selected values with per-item disabled state.

```tsx
function ControlledDisabledItems() {
  const ITEMS = [
    { value: 'alpha', label: 'Alpha', description: 'Primary rollout channel' },
    { value: 'beta', label: 'Beta', description: 'Early access channel' },
    { value: 'stable', label: 'Stable', description: 'Production channel' },
  ]

  const [value, setValue] = createSignal<string[]>(['beta'])

  return (
    <div class="max-w-2xl space-y-3">
      <CheckboxGroup
        legend="Controlled channels"
        variant="table"
        orientation="horizontal"
        items={[
          ...ITEMS,
          { value: 'legacy', label: 'Legacy', description: 'Frozen channel', disabled: true },
        ]}
        value={value()}
        onChange={setValue}
      />
      <p class="text-xs text-muted-foreground">Selected: {value().join(', ') || 'none'}</p>
    </div>
  )
}
```

## API Reference

### Attributes

#### `root`

Group container that owns checkbox collection state and layout.

#### `fieldset`

Fieldset element that groups checkbox options for accessibility.

##### ARIA Attributes

| Attribute | Type | Description |
| --- | --- | --- |
| aria-labelledby | boolean \| string \| undefined | References the element that labels the control or region. |

#### `legend`

Legend text that labels the checkbox group.

#### `item`

Wrapper for one checkbox option in the group.

#### `container`

Text column for an option label and description.

#### `control`

Visible checkbox control for an individual option.

##### Data Attributes

| Attribute | Type | Description |
| --- | --- | --- |
| data-checked | string \| undefined | Present when the item is checked or selected. |
| data-disabled | string \| undefined | Present when the component or item is disabled. |
| data-indeterminate | string \| undefined | State or slot attribute exposed for styling hooks and selectors. |
| data-invalid | string \| undefined | Present when the field has a validation error. |
| data-readonly | string \| undefined | Present when the field is read-only. |
| data-required | string \| undefined | Present when the field is required. |

##### ARIA Attributes

| Attribute | Type | Description |
| --- | --- | --- |
| aria-checked | boolean \| string \| undefined | Accessibility attribute forwarded by the rendered component. |
| aria-disabled | boolean \| string \| undefined | Indicates that the control is disabled. |
| aria-labelledby | boolean \| string \| undefined | References the element that labels the control or region. |
| aria-readonly | boolean \| string \| undefined | Indicates that the control value cannot be changed by the user. |
| aria-required | boolean \| string \| undefined | Indicates that user input is required. |
| role | string | Defines the semantic role exposed to assistive technology. |

#### `indicator`

Visual checked or indeterminate state layer for an option.

##### Data Attributes

| Attribute | Type | Description |
| --- | --- | --- |
| data-checked | string \| undefined | Present when the item is checked or selected. |
| data-disabled | string \| undefined | Present when the component or item is disabled. |
| data-indeterminate | string \| undefined | State or slot attribute exposed for styling hooks and selectors. |
| data-readonly | string \| undefined | Present when the field is read-only. |
| data-required | string \| undefined | Present when the field is required. |

#### `icon`

Check or indeterminate icon rendered for an option state.

#### `wrapper`

Inner layout wrapper used by grouped checkbox variants.

#### `label`

Primary label text for an option.

#### `description`

Supporting description for an option.

### Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| checkedIcon | IconT.Name | — | Default checked icon for all items. |
| class | ClassValue | — | Class applied to the component root or trigger element. |
| classes | CheckboxGroupT.Classes \| undefined | — | — |
| defaultValue | string[] \| undefined | — | The default value of the input (uncontrolled). |
| disabled | boolean \| undefined | false | Whether the input is disabled. |
| id | string \| undefined | — | The ID of the input element. |
| indeterminateIcon | IconT.Name | — | Default indeterminate icon for all items. |
| indicator | "hidden" \| "end" \| "start" \| undefined | — | Default indicator position for all items. |
| items | (string \| CheckboxGroupT.Item<TTrue, TFalse>)[] \| undefined | — | Array of items to render in the group. |
| legend | JSX.Element | — | Legend for the checkbox group. |
| name | string \| undefined | — | The name of the input element, used for form submission. |
| onChange | ((value: string[]) => void) \| undefined | — | Callback when the selected values change. |
| orientation | "horizontal" \| "vertical" \| undefined | — | — |
| readOnly | boolean \| undefined | false | Whether the input is read-only. |
| ref | JSX.HTMLElementTags["div"] extends { ref?: infer Ref; } ? Ref : never \| undefined | — | — |
| required | boolean \| undefined | false | Whether the input is required. |
| size | "xs" \| "sm" \| "md" \| "lg" \| "xl" \| undefined | — | — |
| style | JSX.CSSProperties \| undefined | — | — |
| styles | CheckboxGroupT.Styles \| undefined | — | — |
| value | string[] \| undefined | — | The current value of the input (controlled). |
| variant | "list" \| "table" \| "card" \| undefined | — | — |

### Items

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| checkedIcon | IconT.Name | — | Custom checked icon for this item. |
| description | JSX.Element | — | Description for the group item. |
| disabled | boolean \| undefined | — | Whether the item is disabled. |
| indeterminate | boolean \| undefined | — | Whether the item is indeterminate. |
| indeterminateIcon | IconT.Name | — | Custom indeterminate icon for this item. |
| label | JSX.Element | — | Label for the group item. |
| value | string \| undefined | — | Value of the group item. |

### ARIA

Accessibility attributes and roles emitted by the component markup.

| Attribute | Type | Description |
| --- | --- | --- |
| aria-checked | boolean \| string \| undefined | Accessibility attribute forwarded by the rendered component. |
| aria-disabled | boolean \| string \| undefined | Indicates that the control is disabled. |
| aria-hidden | boolean \| string \| undefined | Hides decorative content from assistive technology. |
| aria-labelledby | boolean \| string \| undefined | References the element that labels the control or region. |
| aria-readonly | boolean \| string \| undefined | Indicates that the control value cannot be changed by the user. |
| aria-required | boolean \| string \| undefined | Indicates that user input is required. |
| role | string | Defines the semantic role exposed to assistive technology. |

### Data Attributes

State and slot attributes exposed for styling hooks and selectors.

| Attribute | Type | Description |
| --- | --- | --- |
| data-checked | string \| undefined | Present when the item is checked or selected. |
| data-disabled | string \| undefined | Present when the component or item is disabled. |
| data-indeterminate | string \| undefined | State or slot attribute exposed for styling hooks and selectors. |
| data-invalid | string \| undefined | Present when the field has a validation error. |
| data-readonly | string \| undefined | Present when the field is read-only. |
| data-required | string \| undefined | Present when the field is required. |
| data-slot | string | Identifies the rendered slot for styling hooks and selectors. |
