Skip to content
ShineUI
Install

Chip

Removable tokens.

<sui-chip>MiscStable

About

Removable token for a filter row, a recipient list or a category picker. The X emits suiRemove with the chip's value and the host owns the list, so the chip never removes itself. Set clickable when the chip is an action, selected to paint it solid, and disabled to sink it and swallow clicks. Keep labels short ("Status: Open").

Usage

<sui-chip label="Status: Open" removable></sui-chip> <script type="module"> import { defineCustomElements } from "@shineui/core/loader"; import "@shineui/core/shineui.css"; defineCustomElements(); const el = document.querySelector("sui-chip"); el.addEventListener("suiRemove", (e) => console.log(e.detail)); </script>
import { SuiChip } from "@shineui/react"; import "@shineui/core/shineui.css"; export function Example() { return <SuiChip label="Status: Open" removable onSuiRemove={(e) => console.log(e.detail)} />; }
<script setup> import { SuiChip } from "@shineui/vue"; import "@shineui/core/shineui.css"; const onChange = (e) => console.log(e.detail); </script> <template> <SuiChip label="Status: Open" removable @sui-remove="onChange" /> </template>
import { Component } from "@angular/core"; import { SuiChip } from "@shineui/angular"; @Component({ standalone: true, imports: [SuiChip], template: `<sui-chip label="Status: Open" removable (suiRemove)="onChange($event)"></sui-chip>`, }) export class Example { onChange(e: CustomEvent) { console.log(e.detail); } }

Basic

A plain chip is static text with a remove control. The X is a real button named "Remove {label}", so a screen reader reads the filter and the action separately.

<sui-chip label="Status: Open" removable></sui-chip>
// setup(root): properties and events setup(root) { const chip = root.querySelector('sui-chip'); chip.addEventListener('suiRemove', () => chip.remove()); }

Icons and initials

An icon takes a Font Awesome class; initial renders a 22px avatar bubble for recipient chips. Both are decorative, so keep the person or the meaning in the label.

<div style="display:flex;flex-wrap:wrap;gap:10px;align-items:center"> <sui-chip label="Aug 1 to Aug 15" icon="fa-regular fa-calendar"></sui-chip> <sui-chip label="Falls City Supply" icon="fa-regular fa-building"></sui-chip> <sui-chip initial="RM" label="Rhonda Mills"></sui-chip> <sui-chip initial="GC" label="Greg Cockerel"></sui-chip> </div>

Images

image fills the same 22px bubble as initial and is decorative, so keep the name in label. A picture that fails to load falls back to initial, which is why the second chip shows letters.

<div style="display:flex;flex-wrap:wrap;gap:10px;align-items:center"> <sui-chip image="/docs/assets/imagery/manufacturing-160.webp" label="Kestrel Logistics" removable></sui-chip> <sui-chip image="/docs/assets/imagery/does-not-exist.jpg" initial="RM" label="Rhonda Mills" removable></sui-chip> <sui-chip image="/docs/assets/imagery/manufacturing-160.webp" label="Kestrel Logistics" size="sm" removable></sui-chip> </div>

Sizes and states

md is 28px, sm is 22px for chips living inside a field. selected paints solid navy; disabled sinks the chip, swallows clicks and disables its remove control.

<div style="display:flex;flex-wrap:wrap;gap:10px;align-items:center"> <sui-chip label="Bills" removable></sui-chip> <sui-chip label="Bills" size="sm" removable></sui-chip> <sui-chip label="Reconciled" selected removable></sui-chip> <sui-chip label="Locked period" disabled removable></sui-chip> </div>

Clickable chips

Set clickable when the chip acts as a button: it becomes role="button" and focusable, and aria-pressed reports selected. Removing never counts as a chip click, because the X stops propagation.

Showing Open.
<div style="display:flex;flex-wrap:wrap;gap:10px;align-items:center"> <sui-chip id="cp-open" label="Open" clickable selected></sui-chip> <sui-chip id="cp-paid" label="Paid" clickable></sui-chip> <sui-chip id="cp-overdue" label="Overdue" clickable></sui-chip> <span id="cp-picked" style="font:460 13px/1.6 var(--font-sans);color:var(--ink-muted)">Showing Open.</span> </div>
// setup(root): properties and events setup(root) { const out = root.querySelector('#cp-picked'); const chips = Array.from(root.querySelectorAll('sui-chip')); chips.forEach((chip) => { chip.addEventListener('click', () => { chips.forEach((c) => (c.selected = c === chip)); out.textContent = `Showing ${chip.label}.`; }); }); }

Events

The X emits suiRemove with the chip's value, or its label without one, and so do Backspace and Delete while the X or a clickable chip holds focus. The chip body reports the native click, only when clickable is set. A disabled chip emits neither.

Idle.
<div style="display:flex;flex-wrap:wrap;gap:10px;align-items:center"> <sui-chip id="cp-ev-a" label="Status: Open" value="status:open" removable clickable></sui-chip> <sui-chip id="cp-ev-b" label="Aug 1 to Aug 15" icon="fa-regular fa-calendar" removable clickable></sui-chip> <sui-chip id="cp-ev-c" label="Locked period" removable disabled></sui-chip> <span id="cp-log" style="font:460 13px/1.6 var(--font-sans);color:var(--ink-muted)">Idle.</span> </div>
// setup(root): properties and events setup(root) { const log = root.querySelector('#cp-log'); root.querySelectorAll('sui-chip').forEach((chip) => { chip.addEventListener('suiRemove', (e) => { log.textContent = `suiRemove: ${e.detail}.`; chip.remove(); }); chip.addEventListener('click', () => { log.textContent = `Clicked ${chip.label}.`; }); }); }

Keyboard

KeyAction
TabReaches a clickable chip, or the remove button of a plain one; a clickable chip removes with Backspace or Delete and its X is a pointer target only.
Enter SpaceClicks a clickable chip. Ignored on a plain or disabled chip.
Backspace DeleteOn the remove button, or on a focused clickable chip, emits suiRemove the way the X does. Ignored on a disabled chip or one that is not removable.

API

<sui-chip>

Properties

PropertyAttributeTypeDefaultDescription
clickableclickablebooleanfalseThe chip is an action: role="button", focusable, Enter and Space click it, aria-pressed reports selected, and the pointer cursor and hover tint appear. Clicks are the host's native click event; there is no suiClick.
disableddisabledbooleanfalseSunken, non-interactive state. Swallows clicks.
iconiconstringstring | undefinedFont Awesome class shown before the label, e.g. "fa-regular fa-calendar".
imageimagestringstring | undefinedPicture shown in the 22px avatar bubble before the label, for a recipient chip with a real photo. Decorative: the person stays in label. When the image fails to load the chip falls back to initial, so give both for a chip that must always show a face.
initialinitialstringstring | undefinedOne or two letters shown in a 22px avatar bubble before the label.
labellabelstring''Chip text. Also names the remove control ("Remove {label}").
removableremovablebooleanfalseShows the X control; clicking it emits suiRemove. Backspace and Delete on the focused control, or on a focused clickable chip, emit the same event.
selectedselectedbooleanfalseSolid brand selected state.
sizesize"md" | "sm"'md'Chip height: md 28px (default), sm 22px for chips inside fields (input tags, multi-select).
valuevaluestringstring | undefinedWhat the chip stands for, the key the host's list knows it by: a recipient's address, a filter's id. suiRemove carries it, so a listener on the list can drop the right entry even when two chips share a label. Falls back to label when unset.

Events

EventDetailReactVueDescription
suiRemovestringonSuiRemove@sui-removeFires when the remove control is activated: a click on the X, or Backspace or Delete while the X or a clickable chip holds focus. Detail is the chip's value, or its label when it has none, as every suiRemove in the library carries the item that went. The control stops propagation, so removing never counts as a chip click, and a disabled chip does not emit.

Methods

MethodSignatureDescription
setFocus()setFocus() => Promise<void>Moves focus to the chip's tab stop: the chip itself when it is clickable, else its remove control. A chip with neither, or a disabled one, has no tab stop and keeps focus where it is. The host's own focus() does the same.

Theming

Every design token this element can render with, read from its own stylesheets and the ones it imports. Set a token on :root or on any ancestor and every use below follows it. The values shown are the ones in the theme you are viewing. The list is read per stylesheet, so an element that imports a shared drawing module lists that module's tokens too, whether or not it paints with all of them.

See also