v1.0.0

<bmx-chip>

A small labelled thing: a filter that is on, a recipient on an email, a tag on a document.

11 properties · 2 events · 2 methods · 4 parts

Example

Design Open issues Assigned to me Documentation
Amara Okonkwo Grace Hopper Dana Scott Archived
Three forms, three genuinely different elements. A static chip is a <span> and takes no focus, because a focus stop that does nothing when pressed reads as a broken control. A selectable one is a real <button> carrying aria-pressed, so it announces its state and answers to Space without a line of key handling. And the cross is a button named “Remove Amara Okonkwo”, not “close” and not the glyph — a cross that is not a button is the commonest defect in this pattern.
One tab stop per chip. When the body is focusable the cross is reached with Delete or Backspace, which is what a keyboard user already does in every recipient field they have used; two stops per chip would turn a row of eight recipients into sixteen Tab presses. bmxRemove is a request — the chip does not take itself out of the document, because the list belongs to you — and it is cancelable.
Show markup
<div class="row" style="gap: 0.5rem; align-items: center">
  <bmx-chip>Design</bmx-chip>
  <bmx-chip selectable value="open">Open issues</bmx-chip>
  <bmx-chip selectable selected value="mine">Assigned to me</bmx-chip>
  <bmx-chip href="/docs/webcomponents/bmx/bmx-chip.html">Documentation</bmx-chip>
</div>

<div class="row" style="margin-block-start: 1.5rem; gap: 0.5rem; align-items: center">
  <bmx-chip removable value="amara">
    <bmx-avatar slot="start" name="Amara Okonkwo" decorative
      style="--bmx-avatar-size: 1.375rem; --bmx-avatar-ring: none"></bmx-avatar>
    Amara Okonkwo
  </bmx-chip>
  <bmx-chip removable value="grace">Grace Hopper</bmx-chip>
  <bmx-chip selectable removable value="dana">Dana Scott</bmx-chip>
  <bmx-chip disabled>Archived</bmx-chip>
</div>

<div class="row" style="margin-block-start: 1.5rem">
  <span class="note">
    Three forms, three genuinely different elements. A static chip is a <code>&lt;span&gt;</code> and takes no focus,
    because a focus stop that does nothing when pressed reads as a broken control. A selectable one is a real
    <code>&lt;button&gt;</code> carrying <code>aria-pressed</code>, so it announces its state and answers to Space
    without a line of key handling. And the cross is a button named <em>&ldquo;Remove Amara Okonkwo&rdquo;</em>, not
    &ldquo;close&rdquo; and not the glyph &mdash; <strong>a cross that is not a button is the commonest defect in this
    pattern</strong>.
  </span>
</div>

<div class="row" style="margin-block-start: 1rem">
  <span class="note">
    One tab stop per chip. When the body is focusable the cross is reached with Delete or Backspace, which is what a
    keyboard user already does in every recipient field they have used; two stops per chip would turn a row of eight
    recipients into sixteen Tab presses. <code>bmxRemove</code> is a <em>request</em> &mdash; the chip does not take
    itself out of the document, because the list belongs to you &mdash; and it is cancelable.
  </span>
</div>
<bmx-chip>Design</bmx-chip>
<bmx-chip selectable selected value="uk">United Kingdom</bmx-chip>
<bmx-chip removable value="ada@example.com">Ada Lovelace</bmx-chip>

THE ONE DECISION THAT MATTERS

A chip is three different things and they look almost identical. It can be static - a label, and nothing a user can do to it. It can be selectable - a filter they turn on and off. It can be removable - a recipient they can take off the list. And to anyone not using a mouse those three are not variations on a component: they are a piece of text, a toggle button, and a piece of text with a button beside it.

So this component draws a genuinely different element for each. A static chip is a <span> and takes no focus, because a focus stop that does nothing when pressed is worse than none. A selectable chip is a real <button> carrying aria-pressed, so it announces its state and answers to Space and Enter without a line of key handling. A removable chip renders a real <button> for its X.

A cross that is not a button is the commonest defect in this pattern and it is worth naming: drawn as an icon inside the chip's own text, it cannot be reached, cannot be pressed, and does not tell anybody what it would do. The X here is a button with its own accessible name - "Remove Ada Lovelace", not "close" and not the glyph.

WHY A TOGGLE BUTTON AND NOT A LISTBOX OPTION

The other reading of a selectable chip is option inside a listbox, and it is a worse fit: an option is only meaningful inside a container that owns the selection, so a chip on its own would be invalid, and a set of chips where any number can be on is a set of toggles rather than a list of choices. aria-pressed is true of the chip by itself, which means a chip works the same whether it is in a bmx-chip-set or standing alone - and that is the difference between a component and a component that only works in one place.

WHERE THE X IS IN THE TAB ORDER

When the chip's body is focusable - selectable, or a link - the X is not a separate tab stop: Delete or Backspace on the body removes it, which is the behaviour a keyboard user already knows from every recipient field they have used. Two stops per chip turns a row of eight recipients into sixteen Tab presses. When the body is not focusable the X is the only thing there is, so it takes the stop.

Properties

PropertyAttributeTypeDefaultDescription
disabled disabled boolean false Whether the chip is inert. A disabled chip keeps its place in the row and takes no focus.
href href string Turns the chip into a link.
label label string The chip's text, when it is not being slotted in. Useful from a template that builds chips from data, and it is what the remove button's accessible name is composed from.
rel rel string The link's rel. Left to the consumer rather than forced: noopener is right for almost every target="_blank" and a component that adds it silently is a component that has decided something on the consumer's behalf.
removable removable boolean false Whether the chip offers a remove button.
removeLabel remove-label string The remove button's accessible name. Composed from the chip's text by default - "Remove Ada Lovelace" - because a row of eight buttons all called "Remove" tells a screen-reader user which action they are on and nothing about which of the eight.
rovingTabindex roving-tabindex number 0 The tabindex of the chip's focusable element. Set by a parent that implements a roving tabindex - bmx-chip-set does - and not normally set by hand. It exists as a property because the element that really takes the focus is inside this component's shadow root, where a tabindex on the host cannot reach it.
selectable selectable boolean false Whether the chip can be turned on and off.
selected selected boolean false Whether it is currently on.
target target string The link's target, when href is set.
value value string What this chip stands for, reported on both of its events.

Events

EventDetailDescription
bmxChange BmxChipChangeDetail The chip was turned on or off.
bmxRemove BmxChipRemoveDetail The remove button was pressed. A request, not a notification: the chip does not take itself out of the document, because the list it belongs to is the consumer's data and a component that deleted from it would be guessing. Cancelable, so a confirmation can stop it - bmx-chip-set, which does own its data, honours the cancellation.

Methods

MethodSignatureDescription
isFocusable isFocusable() => Promise<boolean> Whether anything in this chip can take the focus.
setFocus setFocus() => Promise<void> Focus the chip. Whatever the chip's focusable element happens to be - the body when it is a toggle or a link, the remove button when it is not. Every focusable control in this library exposes this, and a parent looking for one tests for the method rather than for a tag name: a bmx-chip is not a button.

Slots

SlotDescription
(default) The chip's text.
start An avatar or an icon, before the text.

CSS shadow parts

PartDescription
chip The chip's body: the span, button or anchor.
label The text.
remove The remove button.
remove-icon The cross inside it.

CSS custom properties

PropertyDescription
--bmx-chip-background The fill when the chip is off.
--bmx-chip-border The chip's outline.
--bmx-chip-color The text colour when the chip is off.
--bmx-chip-disabled-opacity How faint a disabled chip is.
--bmx-chip-focus-ring The focus indicator.
--bmx-chip-font-size The text.
--bmx-chip-font-weight How heavy it is.
--bmx-chip-gap The space between an avatar, the text and the cross.
--bmx-chip-height The chip's height.
--bmx-chip-hover-background The fill under the pointer, on an interactive chip.
--bmx-chip-padding-inline The room either side of the text.
--bmx-chip-radius The corner radius. A pill by default.
--bmx-chip-remove-color The cross.
--bmx-chip-remove-hover-background The disc behind the cross under the pointer.
--bmx-chip-remove-size The cross's hit area.
--bmx-chip-selected-background The fill when the chip is on.
--bmx-chip-selected-border The outline when it is on.
--bmx-chip-selected-color The text colour when it is on.