// preview in
saved for every page

Chip

Compact choices that filter a list, or small removable values like people and labels. ChipGroup gathers filter chips under one name with arrow-key navigation.

Built on Base UIPattern WAI-ARIA Button (toggle)Client componentSource ↗
minimal · light · #3fa34d
defaultPressed
disabled

Installation

Set up Camaleo once (Installation), then import what you need. The skin you load styles it.

import { Chip, ChipGroup } from "@camaleo/react";

Anatomy

A filter chip is a toggle button with a check that shows while pressed. An input chip (with onRemove) is a span with a remove button at the end.

checkIn reviewremove
[data-slot="chip"][data-slot="chip-check"] · avatar · [data-slot="chip-remove"]label (children)

Examples

Every example is a real file you can copy. They all wear the skin, mode and brand from the bar above.

minimal · light · #3fa34d

Showing 17 of 42 tickets

Filters with a count

Press the chips. Counts in the labels set expectations, and a role="status" line announces how many results are left.

Single selection

multiple={false} keeps one chip pressed at a time, but people can still unpress it. When an empty choice is not allowed, use a radio group.

DesignUrgentQ4 launch

Removable

Remove a label. onRemove turns the chip into an input chip, removeLabel names its button "Remove Urgent", and focus stays in the list instead of falling to the page body.

ASAna SouzaMLMarcus Lee

People, with an avatar

avatar takes a small Avatar. Its initials are decoration: the name in the chip and in removeLabel is what assistive tech reads.

On its own

A single Chip is a toggle with aria-pressed, good for one quick filter like "Only unread" above a list.

With an icon

An icon helps people scan a long set. Mark it data-slot="icon" and aria-hidden; the text still carries the meaning.

Archived tickets can't be filtered while the yearly cleanup runs.

Disabled, with a reason

Arrow keys skip a disabled chip. Say why it is off in text linked with aria-describedby, or people think the filter is broken.

In context

Chips sit above results, inside filter panels and in share dialogs. These are whole pieces of UI you can copy, in the skin you picked.

Filter homes

Lisbon · Nov 14 – Nov 18 · 2 guests

Amenities

Bedrooms

Filter panelCard · ChipGroup · Chip · Button

Share “Q3 revenue”

People you add can view and comment.

People with access

  • ASAna Souza
  • MLMarcus Lee
  • PNPriya Nair
Share with peopleCard · Field · Input · Chip · Avatar · Button

19 results

  • Under $200
  • Rated 4+
  • Free cancellation
Applied filtersChip · Button · Text

Guidelines

DoOne to three words.

Short labels keep a row of chips scannable and fit on a phone.

Don’tSentences in chips.

They break the row into ragged lines and take longer to scan than one or two words.

DoChips filter, buttons act.

Pressing a chip changes what you see; an action like "Export" stays a button.

Don’tChips as action buttons.

A chip announces "pressed" or "not pressed", which makes no sense for "Delete".

Props

PropTypeDefaultDescription
avatarReactNode—Shown before the text, usually a small Avatar.
onRemove(() => void)—Makes it an input chip (a person, a value) with a remove button instead of a toggle. Without it, the chip is a filter toggle with a check while pressed.
removeLabelstring—Accessible name of the remove button (translatable); defaults to "Remove {text}".
pressedboolean—Whether the toggle button is currently pressed. This is the controlled counterpart of defaultPressed.
defaultPressedbooleanfalseWhether the toggle button is currently pressed. This is the uncontrolled counterpart of pressed.
disabledbooleanfalseWhether the component should ignore user interaction.
onPressedChange(pressed, details) => void—Callback fired when the pressed state is changed.
valuestring—A unique string that identifies the toggle when used inside a toggle group.
renderReactElement | (props, state) => ReactElement—Allows you to replace the component's HTML element with a different tag, or compose it with another component. Accepts a ReactElement or a function that returns the element to render.

ChipGroup takes value, defaultValue and onValueChange (arrays of chip values), multiple (true by default), disabled and orientation. Give it a name with aria-label or aria-labelledby.

Styling hooks

Restyle it without forking: target the attributes, or set the tokens on a parent, a skin or the chip itself.

Attributes

data-slot"chip" · "chip-group" · "chip-check" · "chip-remove"
data-variantfilter · input
data-pressedpresent on a pressed filter chip
data-disabledpresent when disabled

Tokens it reads

Color

--cml-accent-text--cml-border--cml-fg--cml-fg-secondary--cml-focus-offset--cml-focus-ring--cml-focus-width--cml-surface-raised

Shape & size

--cml-radius-pill

Type & motion

--cml-duration-fast--cml-ease-standard--cml-font-control--cml-font-weight-control

This component only

--cml-chip-bg--cml-chip-border--cml-chip-fg--cml-chip-font-size--cml-chip-height--cml-chip-letter-spacing--cml-chip-on-fg--cml-chip-on-shadow--cml-chip-on-translate--cml-chip-radius--cml-chip-shadow--cml-chip-text-transform--cml-corner-shape--cml-disabled-opacity--cml-item-highlight
/* square chips, only in this toolbar */
.report-filters [data-slot="chip"] {
  --cml-chip-radius: var(--cml-radius-control);
}

Accessibility

TabMoves focus into the group, to one chip, and out again. Inside an input chip, it reaches the remove button.
Arrow keysMove between the chips of a ChipGroup.
Enter / SpacePresses or unpresses the focused chip, or activates the remove button.
Was this page helpful? · Edit this page on GitHub