Chip

Compact labels for metadata such as types, statuses, and values, optionally clickable or removeable.

Installation

  1. Install the package.
npm install @hashintel/ds-components
  1. Import the component.
import { Chip } from "@hashintel/ds-components";

export const EntityTypeChip = () => (
  <Chip color="blue" variant="defined">
    Person
  </Chip>
);

When to use

  • Do: Use Chip to label an object with compact metadata: an entity's type, a property value, a status, a version.
  • Do: Use onClick when the token itself opens something, such as a filter chip that opens its editor.
  • Do: Use color to tell categories apart at a glance, keeping each color's meaning consistent across a view.

When not to use

  • Don't: Don't use chips for actions or navigation — a chip's primary purpose is to label something. Prefer a Button or Link.
  • Don't: Don't use chips for counts that annotate another element, like an unread count on an icon — use Badge.
  • Don't: Don't use chips to pick one value from a visible set — use SegmentedControl, or RadioGroup in forms.

Examples

Basic

The default chip is defined, grey, and md-sized.

Variants

Variants set emphasis. defined (default) has a solid border for standalone labels, soft and outline sit quieter inside busy UI, and ghost shows no fill or border until hovered or focused — for metadata that shouldn't compete with content.

Colors

Color categorizes: give each category one color and keep the mapping stable across the product. grey is the default. The label must still carry the meaning — never rely on color alone.

Sizes

md is the default. Use xxs-sm inside dense tables and metadata rows, and lg/xl next to headings. Icons, dots, and spinners inside the chip scale with it.

Round shape

shape="round" renders a pill. Use it for status chips, and keep one shape per chip group — mixing shapes reads as a difference in meaning.

Prefix and suffix

prefix and suffix add a slot on either side of the label. A slot's content is an iconName, a status dot, a loading spinner, or arbitrary children such as a count or version.

Status dot

A dot prefix draws a small circle in the chip's text color, with three fill states — filled, partiallyFilled, empty — for lifecycle or progress readings. The dot is hidden from assistive technology, so the label must state the status.

Loading

A loading: true affix shows a spinner. Swapping the affix to a success mark when work completes can help communicate finished progress.

Affix styles

An affix's variant shapes its edge treatment: straight (default) draws a divider between slot and label, naked drops the divider, badge fills the slot and bleeds to the chip's edge, and angle slants the boundary.

Clickable

onClick turns the whole chip into a real <button> with hover and focus styles. Reserve it for token-level interactions such as opening a filter's editor. Consider promoting anything that reads as an action to Button. An affix with its own onClick becomes a separate button beside the clickable centre (aria-label required).

Removeable

removeable appends a close button that calls onRemove. Name each removal through its aria-label — the default name is just "Remove". removeable and suffix are mutually exclusive.

Behavior

  • A static chip renders as a <div>, onClick alone renders one <button>, and onClick combined with an interactive affix or removeable renders a <div> containing a separate button per segment.
  • Labels never wrap. Under a width constraint the label truncates with an ellipsis. Wrap the chip in Tooltip when the full value matters.

Content

  • Write labels as nouns or values, 1–3 words, sentence case: "Person", "Draft", "3 properties". Prefer labels under 20 characters.
  • Keep affix text to a short token: a count ("12"), a version ("v2"), a stage ("beta").

Accessibility

Clickable chips, interactive affixes, and the remove control implement the WAI-ARIA button pattern.

  • Status dots are aria-hidden, so they never produce an unlabeled announcement.
  • Chips pass through aria-* attributes for contextual labelling.

What you must do

  • The default aria label for the remove button is "Remove". Generally you should re-label the action with the chip contents through removeable.aria-label, for ex: "Remove 'Ready Status'", so that buttons are distinguishable in a list.
  • Move focus to a sensible neighbour after removing a chip; the component doesn't manage focus for you.
  • State status in the label text — dots and colors are invisible to assistive technology.

API reference

Chip

PropType
size
"xxs" |⁠ "xs" |⁠ "sm" |⁠ "md" |⁠ "lg" |⁠ "xl"
default: "md"
shape
"round" |⁠ "default"
default: "default"
color
ChipColor
default: "grey"
variant
"ghost" |⁠ "soft" |⁠ "outline" |⁠ "defined"
default: "defined"
onClick
(() => void)
prefix
PrefixOrSuffix
removeable
false |⁠ { onRemove: () => void; "aria-label"?: string; tabIndex?: number; } |⁠ undefined
suffix
PrefixOrSuffix

PrefixOrSuffix

The object shape prefix and suffix take.

PropTypeDescription
iconName
"function" |⁠ "filter" |⁠ "at" |⁠ "circle" |⁠ … 137 more
dot
"filled" |⁠ "partiallyFilled" |⁠ "empty"
loading
boolean
children
ReactNode
variant
"straight" |⁠ "badge" |⁠ "angle" |⁠ "naked"
default: "straight"
aria-label
string
onClick
(() => void)

Was this page helpful?

On this page