An interactive pill: a filter you toggle, or a token you remove. If it only states a fact it is a Badge — interactivity is the whole boundary between the two, and it changes the element, the states, and the keyboard map. Chip borrows Badge's pill and nothing else: it rides the control height because a thing you click needs a target, and takes the control triad because a chip is precisely the generic control those roles name.
Click any of them. Selection lives in aria-pressed, so the fill and the announcement can never disagree — but a native button only activates, it never changes that attribute by itself, so the toggle here is the host behaviour the contract assigns. The tick is decorative; the label carries the meaning.
Remove them — by click, or by tabbing to an X and pressing Enter. Tab reaches only the X, never the pill, and focus lands on the next chip’s X rather than nowhere, which is the contract’s rule about not stranding a keyboard user. Removal is permanent; reload to get the row back.
Two shapes, because the element has to change. A removable chip cannot be a button: its dismiss control is one, and a button inside a button is invalid HTML. So its root is a span, the X owns the whole interaction, and the label is inert text — which is also why it has no pressed state and no hover on the pill itself.
| Example | Shape | Root | Tab reaches | Usage |
|---|---|---|---|---|
| Selectable | button[aria-pressed] | The pill | Filters and toggles — the default | |
| Pina Bausch | Removable | span + button | The X only | Tokens the user entered — recipients, tags, applied filters |
Badge's scale exactly — same heights, same paddings, and the same size.pill-icon 12/14/16px glyph ladder — because chips and badges share rows in dense interfaces, and two pill scales in one table read as a mistake rather than a distinction. One caveat that does not go away by choosing: sm is 20px, under the 24px minimum target size, so it leans on the spacing exception and is the wrong choice where a finger will hit it.
| Example | Size | Modifier | Height | Usage |
|---|---|---|---|---|
| Small | --sm | size.icon.md | Dense tables and toolbars, pointer-precise surfaces only | |
| Medium | ds-chip | size.icon.lg | The default, and the smallest safe touch target | |
| Large | --lg | size.control.sm | Filter bars that are the subject of the view |
The unselected chip keeps the full control triad. Selected takes the inverted pair rather than selection.bg, which resolves to the same neutral step as control.bg in dark mode — a selected chip would vanish against an unselected one exactly where a filter row needs reading at a glance.
| Example | State | Driver | Fill | Usage |
|---|---|---|---|---|
| Rest | default | control.bg | Available, not applied | |
| Hover | :hover | control.bg-hover | The pill steps up; the label does not move | |
| Active | :active | control.bg-active | Pressed, before the toggle lands | |
| Focus | :focus-visible | focus.ring | The one shared ring, same as every other control | |
| Pressed | [aria-pressed="true"] | action.primary.bg | Applied, and it keeps its fill under the pointer. The state is pressed, not selected: aria-pressed is a two-state control, aria-selected is one option among a set | |
| Pressed + hover | [aria-pressed]:hover | action.primary.hover | Scoped away from the unselected hover, which outranked it on specificity and dropped a selected filter to the grey fill | |
| Disabled | :disabled | action.disabled.bg | A filter that cannot apply to the current data |
A chip does something. That is the entire difference from a Badge.
| Verdict | Rule |
|---|---|
| Do | Pick the shape by what the user can do: a filter that toggles is the selectable button with aria-pressed; a token the user removes is the removable span with its own dismiss button. |
| Do | Carry selection in aria-pressed, never in a class alone — the state is the announcement as much as the fill. |
| Do | Move focus deliberately after a removal; a chip that disappears from under the caret strands keyboard users. |
| Don’t | Use a Chip for something that only states a fact — that is a Badge, and the two must not be swapped for looking alike. |
| Don’t | Mix sizes in one row, or reach for sm where a finger will hit it — at 20px it falls under the 24px target minimum and relies on the spacing exception a packed row does not meet. |
| Don’t | Nest a dismiss button inside a button chip. That is invalid HTML, and the reason the removable shape exists at all. |