Zetta v1.6

Components · Data display & feedback

Tag

A pill that labels or categorises — a keyword, a person, a filter. Tags can be plain, removable, or links. On its own a tag is neutral grey; hovering a removable or linked tag tints it toward Primary.

Preview

Design Research #engineering Marketing

Build with the skill

No package to install — hand this to your AI to generate or migrate the component in your stack.

Prompt for your AI
Apply the Zetta "Tag" component to this project using the zetta-design-md skill.

WHEN TO USE
- Migrating or fixing existing code (the common case): audit the current implementation against the `tag` spec (variants: default, removable, linked) and CORRECT every deviation — replace off-spec values, don't only add new ones.
- New component: build it to the `tag` spec in this project's stack.

AUDIT & FIX (when the component already exists)
Compare it to the skill's spec and fix, don't just append: hardcoded colors/hex, off-scale radius, wrong fonts, dark/navy fills, shadows used in place of borders (or missing borders), brand lime used as a CTA or interaction (must be primary indigo), and any missing or wrong hover / focus / active / disabled / invalid state or missing 2px focus ring. Replace each with the correct Zetta token.

ALWAYS
- Pull the authoritative spec and tokens from the skill — never guess or hardcode values.
- Use this project's own component conventions and framework idioms.
- Honor the Zetta guardrails (brand = identity only, primary = interaction, shadows for overlays) and verify in Light, Dark, and Accessibility.

Anatomy & rules

╭──────────────╮       ╭──────────────╮
│  design      │       │  frontend ✕  │  ← removable
╰──────────────╯       ╰──────────────╯
State Background Border Notes
Default {colors.surface-muted} {colors.border-strong}
Hover {colors.surface-secondary} {colors.border-strong}
Focus {colors.surface-muted} + 2px solid {colors.border-focus} Keyboard only
Selected {colors.primary-bg} {colors.primary} Filter-selected state
Disabled {colors.disabled-bg} {colors.disabled-border} not-allowed
Remove hover Remove button shows {colors.danger} on hover Dismissible variant

When to use

  • User-defined categories, labels, or keywords applied to content items.
  • Filter chips in a search or filter bar.

When not to use

  • Workflow states — use Lozenge.
  • Numeric counts — use Badge.

Do

  • Keep tag labels concise — 1–3 words.
  • Group related tags with Tag Group so they wrap consistently.
  • Make the remove button a distinct focus target from the tag label.

Don't

  • Don't use more than 5–6 tags per item before collapsing into a "+N more" overflow.
  • Don't use tags as navigation — use links or breadcrumbs.
  • Tag labels: noun or short noun phrase, 1–3 words. "Design", "In progress", "High priority".
  • Title case for category tags, sentence case for status/content tags.
  • Remove button aria-label: "Remove [tag label] tag".
  • Never truncate tag text — if too long, reconsider the label.

Keyboard

Key Behavior
Tab Move focus to the tag or its remove button
Enter / Space Activate the focused tag — follow link (linked) or select/deselect (filter context)
Delete / Backspace Remove the focused tag (dismissible variant)

Accessibility

  • Remove button: aria-label="Remove [tag label]" — not just "Remove".
  • Tag Group: role="list" with aria-label describing the collection.
  • Each tag: role="listitem".
  • Linked tag: role="link" with descriptive aria-label if the visible text alone is insufficient.

Spec

Values and token references resolved straight from the Zetta spec.

tag
backgroundColor
{colors.surface-muted}
textColor
{colors.ink}
borderColor
{colors.hairline}
borderWidth
1px
borderRadius
{rounded.full}
fontFamily
Geist
fontSize
12px
fontWeight
400
lineHeight
1.5
paddingX
{spacing.sm}
paddingY
{spacing.xs}
display
inline-flex
alignItems
center
gap
{spacing.xs}
tag-hover
backgroundColor
{colors.primary-bg}
textColor
{colors.primary}
borderColor
{colors.primary}
tag-focus
outline
2px solid {colors.border-focus}
outlineOffset
2px
tag-remove
iconSize
{icons.sizeMap.sm}
iconColor
{colors.muted}
cursor
pointer
borderRadius
{rounded.full}
padding
{spacing.xs}
tag-remove-hover
iconColor
{colors.ink}
backgroundColor
{colors.surface-pressed}
tag-linked
textColor
{colors.primary}
cursor
pointer
textDecoration
none
tag-linked-hover
textDecoration
underline
tag-group
display
flex
flexWrap
wrap
gap
{spacing.xs}
alignItems
center