Chip

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.

Chip · Filter row

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.

Chip · Token row
Pina Bausch Octavia Butler Isamu Noguchi Sister Rosetta Tharpe

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.

Shapes

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.

ExampleShapeRootTab reachesUsage
Selectablebutton[aria-pressed]The pillFilters and toggles — the default
Pina BauschRemovablespan + buttonThe X onlyTokens the user entered — recipients, tags, applied filters

Sizes

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.

ExampleSizeModifierHeightUsage
Small--smsize.icon.mdDense tables and toolbars, pointer-precise surfaces only
Mediumds-chipsize.icon.lgThe default, and the smallest safe touch target
Large--lgsize.control.smFilter bars that are the subject of the view

States

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.

ExampleStateDriverFillUsage
Restdefaultcontrol.bgAvailable, not applied
Hover:hovercontrol.bg-hoverThe pill steps up; the label does not move
Active:activecontrol.bg-activePressed, before the toggle lands
Focus:focus-visiblefocus.ringThe one shared ring, same as every other control
Pressed[aria-pressed="true"]action.primary.bgApplied, 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]:hoveraction.primary.hoverScoped away from the unselected hover, which outranked it on specificity and dropped a selected filter to the grey fill
Disabled:disabledaction.disabled.bgA filter that cannot apply to the current data

Usage notes

A chip does something. That is the entire difference from a Badge.

VerdictRule
DoPick 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.
DoCarry selection in aria-pressed, never in a class alone — the state is the announcement as much as the fill.
DoMove focus deliberately after a removal; a chip that disappears from under the caret strands keyboard users.
Don’tUse a Chip for something that only states a fact — that is a Badge, and the two must not be swapped for looking alike.
Don’tMix 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’tNest a dismiss button inside a button chip. That is invalid HTML, and the reason the removable shape exists at all.