Chip
The interactive counterpart to Badge — same pill, but a real button.
Overview
Chip is what you use when a person can click or dismiss a pill. It renders the same recipe as Badge on a real button root, so it takes focus, fires on Enter and Space, and is announced as actionable.
It exists because a clickable span is not a control. Badge deliberately has no onClick, which is what stops the inaccessible version from being written again.
Heights come from Badge's size map rather than a second copy of the numbers, so a Chip and a Badge in the same row always agree.
Choosing between the pills: interactive → Chip. Read-only with a semantic colour → Badge. A user-picked colour → StatusBadge or Tag. The full rubric is in Badges, Chips and Tags.
Basic Usage
import { Chip } from '@fsai/shared-ui';
<Chip label="Filter" onClick={applyFilter} />
<Chip label="Operations" color="blue" Icon="Suitcase" onClick={openTeam} />Removable
Provide onRemove to show a trailing remove control:
<Chip label={tag.name} color="blue" onRemove={() => removeTag(tag.id)} />A removable chip keeps a plain span wrapper so the remove control can be its own button — nesting a button inside a button is invalid markup, and the remove action is the thing being operated. It is announced as Remove <label> when the label is a string, and Remove otherwise.
You can combine both: onClick on the chip body, onRemove on the trailing control.
Sizes
Three steps, shared with Badge. The height derives from the type token plus padding and border — it is not pinned, so it responds to the surface's type scale. See Control Heights.
<Chip label="Small" size="sm" />
<Chip label="Medium" size="md" /> {/* default */}
<Chip label="Large" size="lg" />Props
| Prop | Type | Default | Description |
|---|---|---|---|
label | ReactNode | — | Required. Chip content. |
color | 'blue' | 'gray' | 'orange' | 'red' | 'green' | 'dark-red' | 'black' | 'purple' | 'white' | 'gray' | Semantic colour treatment. |
size | 'sm' | 'md' | 'lg' | 'md' | Size step. Height derives from it. |
shape | 'rounded' | 'pill' | 'rounded' | Corner treatment. |
Icon | IconName | ComponentType<SVGAttributes<...>> | — | Leading icon. Ignored when imageSrc is set. |
imageSrc | string | null | — | Leading image thumbnail. Takes precedence over Icon. |
dot | boolean | false | Renders a leading colour dot. Ignored when Icon or imageSrc is set. |
dotColor | string | — | Tints only the dot, for a colour that is user data. Surface and text stay on color. |
suffix | ReactNode | — | Trailing content, before the remove control. |
onClick | MouseEventHandler<HTMLButtonElement> | — | Click handler. |
onRemove | () => void | — | Shows a trailing remove control. |
removeIcon | IconName | CrossSmall | Override for the remove icon. |
disabled | boolean | false | Disables the chip and its remove control. |
className | string | — | Additional classes. |
style | CSSProperties | — | Inline styles on the root. |
Guidelines
- Do use
Chipfor any pill a person clicks, toggles, or dismisses - Do keep labels short — chips truncate in narrow columns
- Do use
dotColorwhen the colour is user data rather than a design decision - Don't put a
Chipinside a row that is already abutton— use aBadgethere - Don't pin a height on a chip; it must respond to the type scale
- Don't reach for
Chipwhen nothing happens on click — that is aBadge