BridgeHandbookDraft
For agents
Menu
ExperimentalatomLabels

Tag

The soft color label for status, category and counts. Not a button; not a pill.

import { … } from "@brdgapp/ui/components/tag"

Usage

Tag is Bridge's label: the small soft-coloured box that says what something is or what state it's in — an intro's status, a category, a stage, a count. It is the one label in Bridge; never hand-make a <span> chip. The usual mistakes are making it a pill (it is 4px, never round) and using color alone to carry meaning.

When to use

  • An intro's status, using Bridge's status colors (accepted green, forwarded blue, waiting yellow, declined red, requested purple).
  • A category, stage or type: Fundraising, Seed, VC. Categories take blue, purple or grey, never the status colors (see Color).
  • A short relationship label: Mutual, Guest, Super Connector.
  • With onClick, for a label that also opens a menu, such as a category you can change.

When not to use

  • For a tiny uppercase sticker such as ALUM. Use Badge instead.
  • For a filter people switch on and off. Use FilterChip instead.
  • For an action. Labels don't do things; buttons do. Use Button instead.
  • For a person's degree (1st, 2nd). That is plain uppercase text, not a tag.

One of each

Bridge has one button, one label, one menu, one tooltip, one confirm dialog and one table. Before building a control, look for it here. Never hand-make a second version (a <button> with pill classes, a <span> chip, a new kebab), even if it looks the same today: copies drift.

The look comes from props

A component's appearance comes only from its own options (variant, size, color). className on a package component is for layout (mt-4, shrink-0, w-full), never for font size, color, padding, radius or hover. If the look needs a className, the component or the chosen option is wrong: fix that instead.

Never by color alone

Status and meaning are never carried by color alone. A colored tag has a word; a status color comes with an icon or text; a chart says in words what it shows.

Labels are boxes, controls are pills

Tags and badges have 4px corners and never become pills. Pills (rounded-full) are for things you press: buttons, filter chips, search fields, segmented controls.

Sentence case

Buttons, titles, headings, tabs, labels and statuses use sentence case: only the first word and names get a capital. "Make intro", "Intro forwarded", "Stop sharing".

Anatomy

  1. Box. 4px corners, a tint fill and a matching border, from one token family per color.

  2. Icon. Optional, before the label. 14px at sm, 16px at md.

  3. Label. SemiBold, 0.4px letter spacing. A tag is as wide as its label; to cut a long label with an ellipsis, limit the width (className="max-w-full" inside a narrow cell).

  4. Trailing slot. Optional, after the label, such as a chevron.

Examples

Colors

Bridge's intro-status colors, plus gray for categories.

FundraisingForwardedAcceptedNo reply yetDeclinedRequested

Sizes

sm for tables and dense lists; md where tags stand alone.

SeedSeed

With an icon

FerrolinkSuper Connector

Clickable

A label that opens a menu becomes a button.

Long label

Cut with an ellipsis instead of wrapping.

Cobaltwave Distributed Energy Systems

States

RestHoverFocusPressed
Grey
Blue
Green
Yellow
Red
Purple
StateWhat happens
RestTint fill, border and text from the color's token family.
Hover (clickable only)Darkens slightly.
Pressed (clickable only)Fades to 60%.
Focus (clickable only)2px blue ring.

Behavior

  • Without onClick it's a plain <span>: not focusable, not announced as a control.
  • With onClick it renders a real button through Base UI, so it gets keyboard and focus behavior.
  • Colors follow dark mode automatically.

Do and don't

Do

Map each meaning to one color and keep it the same everywhere: accepted is always green.

Don't

Pick a color because it looks nice next to its neighbor.

Do

Keep labels to one or two words.

Don't

Put a sentence in a tag. Write it as text beside it.

Content

  • One or two words, sentence case: "Accepted", "No reply yet", "Fundraising".
  • The same word for the same status everywhere in Bridge.

Accessibility

  • Color is never the only signal: the label text always says the status.
  • Every tag's text passes 4.5:1 on its fill in both themes (dark purple was lightened on 2026-11-03 to get there).
KeysAction
EnterSpaceActivates a clickable tag.

API reference

Tag

The label.

PropTypeDefaultDescription
color"grey" | "blue" | "green" | "yellow" | "red" | "purple""grey"Each maps to one token family: neutral, info, success, warning, error, purple.
size"sm" | "md""sm"12px for dense surfaces and tables; 14px where tags stand alone.
iconReactNode—A bare Lucide icon before the label.
trailingReactNode—Something after the label, such as a chevron.
onClick() => void—Makes the tag a button.
classNamestring—Layout only. Merged last.
titlestring—Deprecated: removed in 2.0. Use Tip for an explanation; a native title tooltip is slow, unstyled and missing on touch. Kept so Bridge OS could move over unchanged.
…other attributesid, aria-*, data-*, event handlers—Passed to the tag. The component's own props win where they overlap.

tagVariants

The class recipe behind Tag.

PropTypeDefaultDescription

Lineage

What it's built from and where it's used, read from the code. When you change it, check these too.

Built from
Nothing else in the package
Used by components
None

Known gaps

Where the code still differs from the system. Follow the system, not the gap.

  • Bridge OS has no orange token, so pending_auto_decline shows yellow where the intros app shows orange.

Sources

  • Bridge OS components.md → Tag / Badge / RatingPill (2026-10-29).
  • Bridge OS src/components/ui/tag.tsx and intros-table.tsx (status → color map).
  • Contrast: Tokens page.