Browse all of Kata

Tag chip

Source docs/design/components/tag-chip.mdMarkdown

On this page

A pill you pick. Interactive chips filter or choose; readonly chips label a session's tags.

Light

Interactive

Kata

Selected

Kata

Pressed · not yet drawn

Kata

Focus · not yet drawn

Kata

Readonly

Sparring

Filter · removable

Green stripe

Dark

Interactive

Kata

Selected

Kata

Pressed · not yet drawn

Kata

Focus · not yet drawn

Kata

Readonly

Sparring

Filter · removable

Green stripe

Source: TagChip.tsx, exported from the barrel as TagChip. Filter rules: search-filter. Chips vs. a sheet: sheet-picker.

When to use it

  • Interactive: two to six options that stay visible while you choose (a session's tags), or the active filters under a search field.
  • Readonly: tags shown inside something else that is already pressable, like a session row.

Not as a checkbox — a chip is a value you are picking, a checkbox is a decision about something already there. Not for seven or more options — use a sheet. Not for a rank: rank is always rows, because a chip cannot carry a swatch and its ring.

Anatomy

Part Interactive Selected Readonly
Fill surface.card brand.red surface.tag
Edge 1px border.control 1px brand.red none
Label 13/400, text.primary 13/400, brand.onRed 12/400, text.secondary
Padding spacing.s8 × spacing.s12 same, so selecting never resizes spacing.s6 × spacing.s12
Shape radius.pill radius.pill radius.pill

A row of chips wraps with spacing.s8 between them.

States

  • Default and selected as drawn. Selected is red because red is Kata's selected state.
  • Pressed: opacity.pressed 0.85 is the target; the component does not draw a press state today.
  • Focus: a 2px border.focus ring, drawn on the page behind the chip.
  • Removable filter: an active filter chip carries its own × and removes itself on tap.
  • Disabled: none. An option that cannot be chosen is not shown.

Content

  • One or two words, sentence case.
  • Chips wrap. They never scroll sideways, because a filter you cannot see is a filter you forget is on.
  • More than two active filters get a "Clear all" text link after them.

Accessibility

  • An interactive chip should announce role button and accessibilityState={{ selected }}.
  • The chip's drawn height is about 34pt, under the 44pt target; give it hitSlop or a 44pt row around it.
  • brand.onRed on brand.red is 5.00:1 in both themes, so the selected label is legible.
  • A readonly chip's surface.tag fill is nearly the page's colour. That is why it is never a control: it has no visible edge.

Known gaps in the shipped component. TagChip sets no accessibilityRole or accessibilityState, draws no pressed or focus state, and its labels use literal 13/12 sizes with weight 400 rather than typography.label. The search-filter chapter still describes the pre-Kata ink fill for a selected filter; the code and Kata use red.

Do and don't

KataSparringWeaponsSelf-defenceConditioningForms

Do

Chips wrap. Every filter stays in sight.

KataSparringWeaponsSelf-defenceConditioningForms

Don’t

A sideways scroll hides exactly the filters at the end.

Code

import { TagChip } from '../../components/ui';

{tags.map((tag) => (
  <TagChip
    key={tag.id}
    variant="interactive"
    label={tag.label}
    selected={chosen.has(tag.id)}
    onPress={() => toggle(tag.id)}
    testID={`session-tag-${tag.id}`}
  />
))}