# CheckboxGroup (w-checkbox-group)

## Description

Checkboxes allow users to select one or more options from a number of choices.

Wrap individual checkboxes in a checkbox group.

[Warp component reference](https://warp-ds.github.io/docs/components/checkbox/frameworks/elements)

## Usage

Checkbox lets users select one or more options. Use it for independent yes/no choices, multi-select lists, and terms or consent confirmations.

Use `w-checkbox-group` when several checkboxes share one label, help text, optional indicator, or required validation.

### Basic Checkbox

```html
<w-checkbox name="newsletter" value="yes">Sign up for updates</w-checkbox>
```

The slotted text becomes the checkbox label.

### Checked State

Use `checked` when the checkbox should be selected by default.

```html
<w-checkbox name="alerts" value="email" checked>Email alerts</w-checkbox>
```

Listen for the `change` event when you need to react to user changes.

```html
<w-checkbox id="newsletter" name="newsletter" value="yes">Sign up for updates</w-checkbox>

<script>
  const checkbox = document.querySelector('#newsletter');

  checkbox.addEventListener('change', () => {
    console.log(checkbox.checked);
  });
</script>
```

### Form Submission

`w-checkbox` is form-associated. When checked, it submits its `name` and `value` with the form. When unchecked or disabled, it submits nothing.

```html
<form>
  <w-checkbox name="newsletter" value="yes">Sign up for updates</w-checkbox>
  <w-button type="submit">Submit</w-button>
</form>
```

If no `value` is set, the submitted value defaults to `on`.

### Required

Use `required` when one standalone checkbox must be checked before form submission, such as accepting terms.

```html
<form>
  <w-checkbox name="terms" value="accepted" required>Accept the terms</w-checkbox>
  <w-button type="submit">Continue</w-button>
</form>
```

For a set of options where at least one option is required, put `required` on `w-checkbox-group` instead.

### Checkbox Group

Use `w-checkbox-group` to group related options under a shared label and help text.

```html
<w-checkbox-group label="Interests" help-text="Select all that apply" name="interests">
  <w-checkbox value="housing">Housing</w-checkbox>
  <w-checkbox value="jobs">Jobs</w-checkbox>
  <w-checkbox value="travel">Travel</w-checkbox>
</w-checkbox-group>
```

The group name is applied to child checkboxes that do not have their own `name`.

### Indeterminate

Use `indeterminate` when a parent checkbox represents a mixed set of child selections.

```html
<w-checkbox name="all-notifications" indeterminate>All notifications</w-checkbox>
```

Indeterminate is a visual state. When the user clicks the checkbox, the indeterminate state is cleared and the checkbox becomes checked.

### Invalid

Set `invalid` when validation is managed outside the component.

```html
<w-checkbox name="terms" value="accepted" invalid>Accept the terms</w-checkbox>
```

When possible, place clear error text near the checkbox or group so users know how to correct the error.

## Accessibility

Checkbox group renders the child checkboxes inside an element with `role="group"`. The group label is connected to the group, and help text is connected when provided.

### Provide A Group Label

Use `label` to describe the shared question or topic.

```html
<w-checkbox-group label="Interests" name="interests">
  <w-checkbox value="housing">Housing</w-checkbox>
  <w-checkbox value="jobs">Jobs</w-checkbox>
  <w-checkbox value="travel">Travel</w-checkbox>
</w-checkbox-group>
```

The group label should not duplicate every option label. It should explain what the options are about.

### Use Help Text For Extra Context

Use `help-text` for instructions, constraints, or validation feedback.

```html
<w-checkbox-group label="Interests" help-text="Select all that apply" name="interests">
  <w-checkbox value="housing">Housing</w-checkbox>
  <w-checkbox value="jobs">Jobs</w-checkbox>
  <w-checkbox value="travel">Travel</w-checkbox>
</w-checkbox-group>
```

Keep help text short and actionable.

### Required Groups

Use `required` on the group when at least one option must be selected.

```html
<w-checkbox-group label="Preferences" required help-text="Choose at least one" name="preferences">
  <w-checkbox value="email">Email</w-checkbox>
  <w-checkbox value="sms">SMS</w-checkbox>
</w-checkbox-group>
```

Do not put `required` on each child checkbox for a "choose at least one" requirement. That would mean every option must be selected.

### Validation Feedback

Do not rely on invalid styling alone. Provide clear help text that explains what the user needs to do.

```html
<w-checkbox-group label="Preferences" invalid help-text="Select at least one option" name="preferences">
  <w-checkbox value="email">Email</w-checkbox>
  <w-checkbox value="sms">SMS</w-checkbox>
</w-checkbox-group>
```

When the group is invalid, the invalid state is also shared with child checkboxes for consistent styling and accessibility state.

### Checkbox Labels

Each child checkbox still needs its own clear label.

```html
<w-checkbox-group label="Contact preferences" name="contact">
  <w-checkbox value="email">Email</w-checkbox>
  <w-checkbox value="sms">SMS</w-checkbox>
  <w-checkbox value="push">Push notifications</w-checkbox>
</w-checkbox-group>
```

Avoid option labels that only make sense visually, such as "Yes" or "This one", unless the group label gives enough context.

## Examples

### Basic

<elements-example>

```html
<w-checkbox name="newsletter" value="yes">Sign up for updates</w-checkbox>
```

</elements-example>

### Checked

<elements-example>

```html
<w-checkbox name="alerts" value="email" checked>Email alerts</w-checkbox>
```

</elements-example>

### Required

<elements-example>

```html
<form>
  <w-checkbox name="terms" value="accepted" required>Accept the terms</w-checkbox>
  <w-button type="submit">Continue</w-button>
</form>
```

</elements-example>

### Invalid

<elements-example>

```html
<w-checkbox name="terms" value="accepted" invalid>Accept the terms</w-checkbox>
```

</elements-example>

### Disabled

<elements-example>

```html
<w-checkbox name="newsletter" value="yes" disabled>Sign up for updates</w-checkbox>
```

</elements-example>

### Indeterminate

<elements-example>

```html
<w-checkbox name="all-notifications" indeterminate>All notifications</w-checkbox>
```

</elements-example>

### Checkbox Group

<elements-example>

```html
<w-checkbox-group label="Interests" help-text="Select all that apply" name="interests">
  <w-checkbox value="housing">Housing</w-checkbox>
  <w-checkbox value="jobs">Jobs</w-checkbox>
  <w-checkbox value="travel">Travel</w-checkbox>
</w-checkbox-group>
```

</elements-example>

### Required Checkbox Group

<elements-example>

```html
<w-checkbox-group label="Preferences" required help-text="Choose at least one" name="preferences">
  <w-checkbox value="email">Email</w-checkbox>
  <w-checkbox value="sms">SMS</w-checkbox>
  <w-checkbox value="push">Push notifications</w-checkbox>
</w-checkbox-group>
```

</elements-example>

### Form Associated

<elements-example>

```html
<form>
  <w-checkbox name="newsletter" value="yes">Sign up for updates</w-checkbox>
  <w-button type="submit">Submit</w-button>
</form>
```

</elements-example>

## Styling API

This section documents the supported styling hooks for `<w-checkbox>` and `<w-checkbox-group>`.

Use these hooks to customize appearance without relying on internal structure or selectors.

Before changing the default styles, remember that doing so can result in less consistent experiences for users across the product. Prefer defaults.

- Prefer **component tokens** for size, spacing, and state styling.
- Use **parts** only for small, local tweaks.
- Avoid relying on internal class names or selectors.

## w-checkbox

### Parts

The checkbox exposes a small set of parts that can be targeted for last‑mile layout or typography tweaks.

| Part | Targets | Typical use |
|---|---|---|
| `base` | wrapper element | layout adjustments (spacing, alignment) |
| `control` | checkbox control (box) | minor alignment or sizing tweaks |
| `input` | native `<input type="checkbox">` | focus / outline adjustments |
| `label` | label content | typography tweaks |

Example:

```css
w-checkbox::part(label) {
  font-weight: 600;
}

w-checkbox::part(control) {
  margin-top: 1px;
}
```

Parts are intended as an **escape hatch**.
Prefer component tokens for anything state‑ or size‑related.

### Component tokens

Component tokens (`--w-c-checkbox-*`) act as inputs to the checkbox styling.
They can be set directly on the component or inherited from a parent container.

```css
.settings-panel {
  --w-c-checkbox-gap: 12px;
}
```

Defaults are defined internally; setting a token is always optional.


#### Layout & size

| Token | Purpose | Default |
|---|---|---|
| `--w-c-checkbox-gap` | space between control and label | `8px` |
| `--w-c-checkbox-control-size` | width/height of the control | `2rem` |
| `--w-c-checkbox-radius` | border radius of the control | `4px` |
| `--w-c-checkbox-border-width` | border width | `1px` |


#### Colors

| Token | Purpose | Default |
|---|---|---|
| `--w-c-checkbox-bg` | control background | theme default |
| `--w-c-checkbox-border-color` | control border color | theme default |
| `--w-c-checkbox-bg-checked` | background when checked | theme default |
| `--w-c-checkbox-border-color-checked` | border when checked | theme default |
| `--w-c-checkbox-icon-color` | icon color | theme default |


#### Invalid state

| Token | Purpose | Default |
|---|---|---|
| `--w-c-checkbox-border-color-invalid` | border color when invalid | theme default |
| `--w-c-checkbox-bg-invalid-checked` | background when invalid and checked | theme default |


#### Disabled state

| Token | Purpose | Default |
|---|---|---|
| `--w-c-checkbox-bg-disabled` | background when disabled | theme default |
| `--w-c-checkbox-border-color-disabled` | border when disabled | theme default |
| `--w-c-checkbox-bg-disabled-checked` | background when disabled and checked | theme default |

#### Focus

| Token | Purpose | Default |
|---|---|---|
| `--w-c-checkbox-outline-width` | focus outline width | `2px` |
| `--w-c-checkbox-outline-color` | focus outline color | theme default |
| `--w-c-checkbox-outline-offset` | focus outline offset | theme default |

#### Motion

| Token | Purpose | Default |
|---|---|---|
| `--w-c-checkbox-transition` | transition for control | `150ms cubic-bezier(0.4, 0, 0.2, 1)` |

Transitions are automatically disabled when `prefers-reduced-motion: reduce` is active.


## w-checkbox-group

The checkbox-group component uses direct CSS styling rather than component tokens. Customization is limited to ensure consistent form control patterns across the design system.

### Styling

The checkbox-group provides minimal styling hooks:

| Element | Current styling | Note |
|---|---|---|
| Label | `font-size: var(--w-font-size-s)`<br>`line-height: var(--w-line-height-s)`<br>`font-weight: 700`<br>`color: var(--w-s-color-text)` | Uses semantic tokens |
| Optional indicator | `font-weight: 400`<br>`color: var(--w-s-color-text-subtle)` | Matches form control pattern |
| Help text | `font-size: var(--w-font-size-xs)`<br>`line-height: var(--w-line-height-xs)`<br>`color: var(--w-s-color-text-subtle)` | Error state: `--w-s-color-text-negative` |
| Checkbox spacing | `gap: 16px` | Spacing between checkboxes |
| Wrapper spacing | `gap: 16px` | Spacing between label and group |


## Implementation notes

### Architecture note

This component uses a `<div>` wrapper instead of the more semantic `<fieldset>` element. Note that `w-radio-group` uses `<fieldset>`, which provides better accessibility and follows HTML best practices. This inconsistency exists for historical reasons and may be addressed in a future major version to align both on the more semantic approach.

**Why this matters:** `<fieldset>` with `<legend>` provides automatic grouping semantics and better screen reader support. The current `<div>` + `role="group"` implementation works but requires manual ARIA wiring.

**TODO:** Consider aligning w-checkbox-group to use `<fieldset>` in a future major version after assessing backwards compatibility implications (CSS selectors, etc.).

## `<w-checkbox-group>` API

Unless otherwise noted all properties are HTML attributes (as opposed to JavaScript object properties).

### Properties

| Name | Type | Default | Summary |
|-|-|-|-|
| checkValidity (JS only) | `checkValidity() => boolean` | `-` | Checks whether the group passes constraint validation |
| focus (JS only) | `focus(options?: FocusOptions) => void` | `-` | Sets focus on the checkbox group. |
| help-text | `string \| undefined` | `-` | Help text displayed below the checkbox group. |
| invalid | `boolean` | `false` | Whether the checkbox group is visually invalid. |
| label | `string \| undefined` | `-` | The group label displayed above the checkboxes. |
| name | `string \| undefined` | `-` | The name applied to child checkboxes when they do not provide one. |
| optional | `boolean` | `false` | Whether to show optional text next to the label. |
| reportValidity (JS only) | `reportValidity() => boolean` | `-` | Checks validity and shows the validation message if invalid |
| required | `boolean` | `false` | Whether at least one checkbox in the group must be selected. |
| shadowRootOptions (JS only) | `object` | `{ ...LitElement.shadowRootOptions, delegatesFocus: true, }` | - |

### Property Details

#### checkValidity (JS only)

Checks whether the group passes constraint validation

- Type: `checkValidity() => boolean`
- Default: `-`

#### focus (JS only)

Sets focus on the checkbox group.

- Type: `focus(options?: FocusOptions) => void`
- Default: `-`

#### help-text

Help text displayed below the checkbox group.

Use this for supporting guidance or validation feedback. When required validation fails, the group replaces this text with the localized required message.

- Type: `string | undefined`
- Default: `-`

#### invalid

Whether the checkbox group is visually invalid.

Use this to show an externally managed validation error for the group. The invalid state is also shared with child checkboxes for consistent styling and accessibility state.

- Type: `boolean`
- Default: `false`

#### label

The group label displayed above the checkboxes.

Use this to describe the shared question or topic for the checkbox options. The label is connected to the internal group for assistive technologies.

- Type: `string | undefined`
- Default: `-`

#### name

The name applied to child checkboxes when they do not provide one.

Use this when the grouped checkboxes should submit values under the same form field name. Individual checkboxes can still override the group name with their own `name`.

- Type: `string | undefined`
- Default: `-`

#### optional

Whether to show optional text next to the label.

Use this to indicate that selecting an option from the group is not required.

- Type: `boolean`
- Default: `false`

#### reportValidity (JS only)

Checks validity and shows the validation message if invalid

- Type: `reportValidity() => boolean`
- Default: `-`

#### required

Whether at least one checkbox in the group must be selected.

Required validation is managed by the group. The individual checkboxes provide the submitted form values.

- Type: `boolean`
- Default: `false`

#### shadowRootOptions (JS only)



- Type: `object`
- Default: `{ ...LitElement.shadowRootOptions, delegatesFocus: true, }`

