# Chips

> Slug: `chips` · Category: Selection

## When to use

A single component with three behaviors via the `variant` prop:

- `variant="toggle"` — a fieldset of independent on/off chips (multi-select).
- `variant="radio"` — a fieldset of single-select chips.
- `variant="button"` — a row of dismissible (×) chips representing applied tags/filters.

## When NOT to use

- Filter buttons that open a menu — use `FilterChip`.
- Long lists or rich content (icon + body + price) — use `StyledRadioGroup`.
- Standard form inputs — use `Checkbox`, `RadioGroup`, or `Select`.

## Variants & decision tree

| Behavior | `variant` | Use case |
|---|---|---|
| Multi-select pills | `toggle` | Feature filters: "5G", "Unlimited" |
| Single-select pills | `radio` | Sort by, billing cycle |
| Dismissible tags | `button` | Active filter summary, applied tags |

## States

Per chip: unchecked, checked (toggle/radio), hover, focused, pressed, unavailable (`isUnavailable`). Sizes: `small` (default), `xs`.

## Props

| Prop | Type | Default | Description |
|---|---|---|---|
| `variant` | `'toggle' \| 'radio' \| 'button'` | — | Required. Behavior selector. |
| `chips` | `ChipOption[]` | — | Array of `{ id, label, checked?, isUnavailable?, name? }`. |
| `legend` | `string` | — | Fieldset legend (toggle/radio variants). |
| `size` | `'small' \| 'xs'` | `'small'` | Chip size. |
| `inverse` | `boolean` | `false` | Dark-background styling. |
| `onChipChange` | `(chipId, checked) => void` | — | toggle variant only. |
| `onChipSelect` | `(chipId) => void` | — | radio variant only. |
| `onChipRemove` | `(chipId) => void` | — | button variant only. |
| `checkmarkIcon` | `ReactNode` | built-in | Override toggle checkmark. |
| `closeIcon` | `ReactNode` | built-in | Override button × icon. |

## Usage examples

```tsx
// Multi-select toggles
<Chips
  variant="toggle"
  legend="Features"
  chips={[
    { id: 'f-5g', label: '5G', checked: feats.has('5g') },
    { id: 'f-unl', label: 'Unlimited', checked: feats.has('unl') },
  ]}
  onChipChange={(id, checked) => toggleFeature(id, checked)}
/>

// Single-select sort
<Chips
  variant="radio"
  legend="Sort by"
  chips={[
    { id: 's-price', label: 'Price', name: 'sort', checked: sort === 's-price' },
    { id: 's-name', label: 'Name', name: 'sort' },
  ]}
  onChipSelect={(id) => setSort(id)}
/>

// Applied filters (dismissible)
<Chips
  variant="button"
  chips={appliedFilters.map((f) => ({ id: f, label: f }))}
  onChipRemove={(id) => removeFilter(id)}
/>
```

## Composition

Use above lists, tables, and product grids for filter and sort affordances. Combine `variant="button"` (active filters bar) with `FilterChip` (filter trigger).

## Accessibility

`toggle` and `radio` variants render a real `<fieldset>` with `<legend>` — provide `legend`. Chip labels are visible text and serve as accessible names. `isUnavailable` disables the chip and applies a struck-through visual. The button variant chips are semantic buttons with `aria-label="Remove {label}"`.

## Do / Don't

- DO match `variant` to user intent: multi-select → toggle, single-select → radio, applied tags → button.
- DO provide `legend` for toggle/radio variants.
- DON'T mix variants in the same group.
- DON'T import `ChipsToggle`, `ChipsRadioGroup`, etc. — they don't exist as separate exports.
