BridgeHandbookDraft
For agents
Menu
Stable

Iconography

Lucide icons: one per meaning, how big, what color, and when an icon is named or hidden.

Every icon is Lucide, drawn with its own 2px line. One icon stands for one meaning across every app. An icon either sits beside words and stays silent, or stands alone and is named. Company logos are not icons: they come from BrandMark.

Lucide

  • Import from lucide-react (lucide-react-native in the mobile app). No other icon set, and no hand-drawn SVG for something Lucide has.
  • Keep Lucide's 2px line. Don't pass strokeWidth; the only exception is a tick inside something tiny (Checkbox draws its 12px tick at 3px so it doesn't look faint).
  • Inside a Button, IconButton or Tag, pass a bare icon: the component sizes it. A size class on it opts out.
  • A new icon you draw yourself sits on Lucide's 24px grid with a 2px line, round ends and corners, in currentColor.
import { MapPin, Plus } from "lucide-react";

// Inside a button: bare, the button sizes it
<Button><Plus aria-hidden="true" />Make intro</Button>

// Beside words: sized to the text, hidden from screen readers
<span className="inline-flex items-center gap-1.5 text-13 text-[var(--text-muted)]">
  <MapPin aria-hidden="true" className="size-3.5" />
  Lagos
</span>

One icon per meaning

The icons the apps use most, by what they mean. Use the same icon for the same meaning everywhere, and never one meaning's icon for another.

MeaningUseNot
Add or createPlusCirclePlus: the circle adds nothing
Close, clear, remove from a listXCircleX: a circled X reads as failed
More actions on a row or recordEllipsisVertical (was MoreVertical)Ellipsis: ActionMenu uses the upright dots
EditPencilSquarePen: two pencils for one meaning
DeleteTrash (was Trash2)X: X closes, it doesn't delete
Copy; a tick once copiedCopy then CheckClipboard: a clipboard is pasting
Opens another site or a new tabExternalLinkArrowUpRight: reads as “go on” or a number going up
Go on: the next step, see allArrowRightArrowUpRight: that's for numbers going up
Back to the page beforeArrowLeftChevronLeft: that pages back through a list
Opens a menu or a sectionChevronDown–
Goes into a row, or the next page of a listChevronRight–
Working on itLoaderCircle (was Loader2)Loader: the spoked one; use one spinner
Sync, or try againRefreshCwRotateCw: two arrows for one meaning
SucceededCircleCheck (was CheckCircle2)CircleCheckBig: two ticks for one meaning
ErrorCircleAlert (was AlertCircle)CircleX: use one error icon
Warning; can't be undoneTriangleAlert (was AlertTriangle)CircleAlert: that's an error
More about thisInfoCircleQuestionMark: use one hint icon
Done by AISparklesWandSparkles: use one AI icon; Bot: Bot is the agent itself, not what it did
People, a network; one personUsers then UserContact: a card, not a person
Introduce, or add a personUserPlusHandshake: that's a deal done
A company or fundBuildingComplex (was Building2)Briefcase: a briefcase is a job
A job or roleBriefcase–
SearchSearch–
Email; Send to send itMail then SendAtSign: @ is a mention
A link to copy or shareLink2–
A placeMapPin–
A date or a meetingCalendar–
Private, or only some people can see itLock–
SettingsSettings–

Every icon

Every icon in Lucide, read from the installed package. Search by what you need; Bridge's own icon for that meaning comes first. Icons that already mean something say so.

Click an icon to copy its import.

Every Lucide icon

When nothing in the table fits

  • Search here (or ask the agent's find_icon) for a Lucide icon that isn't already taken for another meaning.
  • Add the new meaning to the table in the same change (content/foundations/iconography/meanings.ts), so everyone uses the same icon for it from then on.
  • If Lucide has nothing, draw one on its 24px grid with a 2px line and add it to the package, never to one app. A company logo goes in BrandMark.

Sizes

Two rules give every size. Beside words, an icon is 2px bigger than the text. Inside a square or a circle, it's half the shape's width.

12px
14px
16px
18px
20px
24px

Beside words

TextIconClass
12–13px: meta, table rows, small buttons, tags14pxsize-3.5
14px: body, menus, fields, the default button16pxsize-4, the default
16px: card titles, the large button18pxsize-[18px]

In a shape

WhereIconSet by
A tiny control: the × on a tag, sort arrows, the checkbox tick12pxsize-3
Card's 36px header square18pxCard icon
ConfirmDialog's 40px warning circle20pxConfirmDialog
DataState's 48px empty and error circle24pxDataState
  • Nothing is bigger than 24px. A larger picture is an illustration, not a scaled-up icon.
  • Beside more than one line of text, line the icon up with the first line (mt-0.5), not the middle of the block.

Color

Icons take their color from what they sit in. They're quiet at rest, darken on hover, and turn blue only when something is on or picked.

WhenColorFor example
Beside wordsThe words' color: it inheritsA muted icon in a muted meta row
Controls at rest--text-mutedIcon buttons, filter chevrons, row actions
Hovered--text-primaryAn icon button under the pointer
On, or picked--primaryAn active filter, the sorted column's arrow
Section and feature icons--primary, in Card's colored squareCard headers
Empty states--text-disabledDataState's empty circle
A result--success, --error, --warning-text, beside the wordA tick beside Sent, a warning beside Failed
On a filled buttonWhite: it inheritsThe primary button's icon

Named or hidden

An icon beside words is hidden from screen readers, because the words already say it. An icon on its own is the only name its button has, so it's named. Never neither.

Icon-only buttons

Each has a name for screen readers and the same words in a tip on hover or focus.

  • Beside a label: aria-hidden="true".
  • On its own: use IconButton, which needs an aria-label. Name the action ("Copy email"), not the picture ("Copy").
  • Where the icon alone could mean more than one thing, wrap it in Tip with the same words.
  • When the action flips, the name flips with the icon: "Show details" becomes "Hide details".
  • A result icon never stands alone: a tick travels with Sent, a warning with Failed.

Icons in buttons

  • An icon in front names the action. An icon after says what happens next: a chevron opens a menu, an arrow leaves for another site.
  • One icon per button.
  • Not every button needs one. In a row of buttons, give an icon to the one that's helped by it, or to none.

Icon squares

Where an icon names a section or a topic, it sits in Card's header square: 36px, 8px corners, tinted blue, green, amber or purple by topic, with an 18px icon.

Intros this week

Who you introduced, and who said yes.

  • Squares are for topics. A round shape is a person (Avatar) or an empty state (DataState).
  • One icon per square, no text inside.

Company logos

Logos aren't icons and Lucide has none. Use BrandMark for LinkedIn, Google, Microsoft, Apple, WhatsApp, Telegram and Chrome: their own colors, at icon size.

  • Never recolor a logo to match the page. LinkedIn, WhatsApp and Telegram may be one color (mono) in a quiet row of details.
  • A logo means the company: signing in with it, going to it, or something that came from it. For an action like sharing, use a Lucide icon.

No emoji

LagosIntro sent
Do. A Lucide icon in a token color, beside the words.
📍 Lagos🎉 Intro sent
Don’t. Emoji as icons. They look different on every phone, ignore dark mode, and can't be sized or colored with the rest.
  • No emoji in labels, buttons, headings, toasts, empty states or sample data.
  • What people write themselves (messages, notes, bios) keeps its emoji.

Rules

One icon set, one icon per meaning

Every icon is Lucide at its own 2px line. Each meaning has one icon, listed on Iconography; a meaning that isn't listed gets a Lucide icon nobody else uses, added to the list in the same change. No other icon set, no emoji in the interface, and no hand-drawn company logos: BrandMark draws them.