ChipList

A list of chips that shows up to maxRows rows and folds the rest into a +N button. +N opens a popover with the folded chips. Name the list with aria-label or aria-labelledby.

With onRemove, each chip gets a remove button. Once chips drops the focused chip, focus moves to the chip that now fills its place, else the one before it, else +N, else the list.

<ChipList.Root
  aria-label="Tags"
  chips={tags}
  maxRows={1}
  onRemove={(index) => setTags((current) => current.filter((_, i) => i !== index))}
/>

In the popover, Tab past the last chip goes on to the control after +N, Shift+Tab from the first chip returns to +N, and Escape closes it and returns to +N.

One row / Two rows

designtokensaccessibilitya-very-long-tag-that-stays-putreactdensitydark modedocs
designtokensaccessibilitya-very-long-tag-that-stays-putreactdensitydark modedocs

Read-only

designtokensaccessibilitya-very-long-tag-that-stays-putreactdensitydark modedocs

When to use

When: Chips outside a text field, such as applied filters, read-only tags or recipients, capped at maxRows with a +N count.

When not: Typing new chips → Field.ChipInput. Picking from options → Combobox recipe. Selectable or toggle chips → Checkbox / Button.Root. One chip → Chip.Root. Your own markup around the fold → useChipList.

Props

ChipList.Root props
NameTypeRequiredDefaultDescription
chipsreadonly string[]yes—Chip labels, in order.
maxRowsnumberno—Rows to show before folding the rest into +N. Without it, every chip wraps onto as many rows as it needs.
getKey(value: string, index: number) => stringno—A stable, unique key for each chip, so focus can follow it when chips change. Without it, chips are matched by value, so focus can land on another chip with the same value.
onRemove(index: number, value: string) => voidno—Renders a remove button on each chip. Once chips drops the focused chip, focus moves to the chip that now fills its place, else the one before it, else +N, else the list.
removeLabel(value: string) => stringno—Remove button name. Default is the removeChip string from StringsProvider, Remove {value} in English.
removeIconReact.ReactNodeno—Remove button content, such as an icon from your own set. Without it, the CSS draws a cross.
overflowLabel(n: number) => stringno—+N button name. Default is the moreChips string from StringsProvider, {n} more in English.
panelLabel(n: number) => stringno—Name of the popover with the folded chips. Default is the moreChipsPanel string from StringsProvider, {n} more chips or 1 more chip in English.