Components

Chips

The friendly little label. Identity, not state — tags, taxonomy entries, references. Officially a chip is a flat pill: eggshell fill, warm hairline, type that stays out of the way. It names things without judging them, and a row of them scans easily on any record.

Chip is Beta. It covers three usages: a static identity label, a removable input chip (a user-applied tag with an X affordance), and a selectable filter / choice chip (a toggle with a check glyph). For a status that judges a record, reach for Badge; for a full multi-select field with a menu, reach for Selector.

Usages

One component, three jobs. Static chips have no handlers and stay out of the tab order. Removable chips carry their own remove button. Selectable chips render the label as a toggle button with aria-pressed — selected gets the gold treatment AND a check glyph, so it never rests on color alone (ADR-0017).

Q2 auditNMLS-23456
usage: identity
A static nominal label. System-applied taxonomy, immutable identifiers. Not interactive.
SOC 2
usage: input
A user-applied entity — a manual tag, an attached reference. The X removes it; the X is its own tab stop with its own accessible name.
usage: filter
An independent toggle in a set. Click or press Space / Enter to flip it; selected goes gold and draws the check.
usage: choice
Pick-one in a set — same control, the caller clears the siblings. Clicking the selected chip keeps it selected.
Archived-2024
state: disabled
Dimmed to 50%; toggle and remove are both blocked.

In dense context

The boundary-readability check: chips in running text must parse as discrete labels, not inline phrases. The eggshell fill against the white surface keeps each pill reading as its own little thing.

Tagged: Q2 audit NMLS-23456 marketing-compliance SOC 2
Rulebook §6.3 references BSA and OFAC SDN list.

Selection — filter and choice

Selected chips wear the portal’s active grammar, the same one you see on the current nav item: the gold wash with gold text — gold as active state, never as a container frame. A check glyph rides along too, like Checkbox pairs its mark — color does the talking, the glyph makes it stick (ADR-0017). A filter set toggles independently. A choice set is pick-one: the same control, with the caller clearing siblings in its own state.

Filter set — independent toggles
Each chip is aria-pressed and flips on its own. Selected takes the gold wash; the check glyph carries the state alongside the color (ADR-0017).
Choice set — pick one
One value holds at all times; clicking the selected chip keeps it. For long pick-one lists, a Selector reads better than a wall of chips.

Removable — input chips

When a chip represents user-applied state (a manual tag, an attached reference), pass onRemove for the trailing X. It is a real button — keyboard reachable, with its own accessible name. The name defaults to a translated "Remove {label}" when the label is a plain string; pass removeLabel explicitly whenever it is not. Static chips (system taxonomy, immutable identifiers) omit the remove.

Tagged references
Q2 auditNMLS-23456marketing-complianceSOC 2
Tab to a chip’s X and press Enter to remove it. The remove is a separate tab stop from any toggle.

Materiality

The spec values below document the proposed system’s ink-on-plate treatment. The official chip plays it differently: a flat opaque pill, eggshell fill behind a warm hairline, and the gold active wash with gold text when selected. Friendly, never fussy.

form
--radius-sm corners, --space-px-2 × --space-2 padding.

A full pill — round ends, soft and friendly. The pill shape is what says "label" against the squarer cards and buttons.

surface
--ink-100 fill behind a --ink-300 hairline (--ink-800 / --ink-600 on the dark plate).

Eggshell on the white surface — a quiet fill behind the warm hairline. Gold never frames a container; the border stays neutral until selection.

selected
Frame darkens to --fg-1; a --space-3 check glyph appears.

The portal’s active grammar: the gold-50 wash, gold-700 text, a touch more weight — plus the check glyph, so color-blind users get the state too (ADR-0017).

remove
--space-4 hit box, --space-3 Lucide X at 1.75px stroke, --fg-3 rising to --fg-1 on hover.

An ink affordance, not a metal button — quiet until pointed at.

motion
Frame and color settle over --dur-quick with --ease-mechanical.

A little lift on hover, a little press on click — the fun register. Reduced-motion turns it all off.

Props

children: ReactNode
The label. Keep it nominal — chips name things, they don’t judge them.
selected?: boolean
Selected state for filter / choice usage. Only meaningful with onSelectedChange; the selected chip draws the check glyph.
onSelectedChange?: (selected: boolean) => void
Makes the chip selectable: the label becomes a toggle button with aria-pressed, fired with the next selected state.
onRemove?: () => void
Renders the trailing remove button (input usage). A separate tab stop — selection and removal never nest.
removeLabel?: string
Accessible name for the remove button. Defaults to a translated "Remove {label}" when children is a plain string, else "Remove" — pass it explicitly whenever the label isn’t a string.
disabled?: boolean
Dims the chip to 50% and blocks both the toggle and the remove.
id, title, …
Standard span attributes pass through to the chip’s root element.

Usage

Identity — static nominal labelstsx
import { Chip } from '@halo-compliance/ui'

<Chip>Q2 audit</Chip>
<Chip>NMLS-23456</Chip>
Input — removable user-applied tagstsx
{tags.map((tag) => (
  <Chip
    key={tag}
    onRemove={() => setTags((prev) => prev.filter((x) => x !== tag))}
  >
    {tag}
  </Chip>
))}
Filter and choice — selectable setstsx
// Filter — independent toggles
<Chip selected={utah} onSelectedChange={setUtah}>Utah</Chip>

// Choice — pick-one; the caller clears siblings
{appetites.map((a) => (
  <Chip
    key={a}
    selected={appetite === a}
    onSelectedChange={() => setAppetite(a)}
  >
    {a}
  </Chip>
))}

When to use

  • Naming things on a record — tags, taxonomy entries, references; identifiers that label without judging.
  • Editable sets — user-applied tags or attached references the user can take back (the removable variant).
  • Compact filtering or pick-one above a list — a short row of toggles where a Selector menu or a checklist would be heavier than the job.

Antipatterns

  • Status in a chip. A chip never judges. "Flagged", "Active", severity of any kind — that is a Badge, with its semantic tone and icon pairing.
  • A chip as an action. If clicking navigates or commits something, it is a Button or a Link. The chip’s only verbs are select and remove.
  • Long pick-one lists as choice chips. A dozen chips is a wall; pick-one beyond a handful of options is a Selector.
  • A non-string label without removeLabel. The default accessible name can only be derived from a plain-string label — anything richer needs an explicit removeLabel.
  • /badge — the status sibling: semantic tones, icon pairing, judgment.
  • /selector — the full multi-select field; its selected values render as removable chips.
  • /checkbox — the same selection semantics (aria-pressed, glyph paired with the state).
  • /tokens--radius-sm, --ink-100, and the duration / easing tokens.