Chip

A compact value: a tag, a filter or an applied selection, in one untoned look.

import { Chip } from "@usefragments/ui";Source

Preview

<Chip>Design</Chip>

Usage

Use when

  • Filtering a list by tag or category
  • Multi-select from a compact set
  • Showing filters the user can dismiss

Avoid when

  • Read-only status — use Badge
  • Switching views — use Tabs
  • On/off state — use Switch
  • A main call to action — use Button

Implementation notes

  • One to three words per chip; long labels truncate
  • One look, never toned: a chip that reports a state is a Badge
  • A static tag renders a span; it becomes a button only when it selects or clicks
  • Chip.Group when chips share selection state; name it with aria-label
  • onRemove only when the chip is genuinely dismissible
  • Pass an explicit value when children are custom JSX

Installation

pnpm add @usefragments/ui

Import styles once from @usefragments/ui/styles. See the installation guide for framework and theme setup.

Anatomy

Import Chip once, then compose its parts with dot notation.

  • Chip.Group

Examples

With Icon

A leading glyph or avatar.

import { Hash } from '@phosphor-icons/react';

<Chip icon={<Hash />}>release</Chip>

Selectable

A toggle: the selection wash with the ring as its edge.

const [selected, setSelected] = React.useState(true);

<Chip selected={selected} onClick={() => setSelected((value) => !value)}>
  Open
</Chip>

Removable

The X control has its own label and a micro hit area.

<Chip onRemove={() => {}}>design</Chip>

Group

Shared selection, reported through onValueChange.

const [value, setValue] = React.useState(['open']);

<Chip.Group aria-label="Status filters" value={value} onValueChange={setValue}>
  <Chip value="open">Open</Chip>
  <Chip value="draft">Draft</Chip>
  <Chip value="merged">Merged</Chip>

API reference

Component props
Prop
Type
Default
Description
childrenRequiredReact.ReactNodeNot setChip label; truncates when the chip runs out of room
Group.aria-labelstring | undefinedNot set—
Group.aria-labelledbystring | undefinedNot set—
Group.childrenRequiredReact.ReactNodeNot set—
Group.defaultValuestring[] | undefinedNot setDefault selected values (uncontrolled)
Group.onValueChange((value: string[]) => void) | undefinedNot setCalled with the next selected values
Group.valuestring[] | undefinedNot setControlled selected values
iconReact.ReactNodeNot setLeading glyph or avatar
onRemove(() => void) | undefinedNot setMakes the chip removable: an X control with its own label and a micro hit area
removeLabelstring | undefined"Remove <label>" for a text label, else "Remove"Accessible name of the remove control; defaults to "Remove <label>" for a text label
selectedboolean | undefinedNot setSelected state. Setting it (or onClick, or Chip.Group) makes the chip a toggle button with aria-pressed; selected paints the selection wash and ring
valuestring | undefinedNot setValue identifier used by Chip.Group for selection tracking
disabledboolean | undefinedfalseDims the chip once and disables its controls
onClickMouseEventHandler<HTMLButtonElement> | undefinedNot setClick handler; makes the chip a button
type"button" | "submit" | "reset" | undefinedbuttonsubmitresetbutton—

Accessibility

  • A selectable chip is a toggle button; selection is reported via aria-pressed
  • A static tag is plain text, not a button
  • Chip.Group renders role="group" and needs aria-label or aria-labelledby
  • The remove control carries its own label ("Remove design") and a 24px hit area
  • Disabled chips are skipped by keyboard and pointer
  • BadgesiblingBadge reports a state in colour; Chip is an untoned value, static or selectable
  • ToggleGroupalternativeUse ToggleGroup for mutually exclusive options
  • ButtonalternativeUse Button for primary actions, Chip for selection/filtering

Next steps