<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
<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.
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><span></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><button></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>“Remove Amara Okonkwo”</em>, not
“close” and not the glyph — <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> — the chip does not take
itself out of the document, because the list belongs to you — 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
| Property | Attribute | Type | Default | Description |
|---|---|---|---|---|
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
| Event | Detail | Description |
|---|---|---|
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
| Method | Signature | Description |
|---|---|---|
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
| Slot | Description |
|---|---|
(default) |
The chip's text. |
start |
An avatar or an icon, before the text. |
CSS shadow parts
| Part | Description |
|---|---|
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
| Property | Description |
|---|---|
--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. |