BridgeHandbookDraft
For agents
Menu
ExperimentalmoleculeData display

Card

The frosted-glass box most of Bridge sits in: lists, tables, forms and tiles.

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

Usage

Card is the frosted-glass box most of Bridge sits in: a list, a table, a form, a tile, an item in a feed or an inbox. It comes in three sizes, can be a link to a page (href) or picked from a list to open beside it (onSelect, selected), and has a header with an icon or avatar, a date or tag, and one action. Buttons, checkboxes and links inside a clickable card keep working on their own. Inside another card it becomes a bare row (bare). The usual mistakes are a flat white box, a card inside a card, and a clickable card keyboards can't reach.

When to use

  • Any block of related content on a page: a list of intros, a table, a settings form, a profile section.
  • Tiles on a dashboard or in a feed (size="md").
  • A whole card that goes to a page, like a network in a grid (href).
  • An item people pick from a list to open beside it: an intro in the inbox, an activity in the feed (onSelect, selected).
  • A row inside another card or pane, like the activity on a profile (bare).

When not to use

  • Inside another card. Group with dividers or a light bordered box instead.
  • For a single number on a dashboard. Use StatBox instead.
  • For a short preview that opens on hover. Use Hover card instead.
  • For something that floats over the page, like a dialog or a menu. Use Dialog instead.

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.

Glass, once

Cards, panels, empty states and the navigation are frosted glass over the page background, never flat white boxes. A glass card never sits inside another glass card: inside a card, group things with dividers or a light bordered box.

The frame stays

A card never disappears because its data is missing. Loading, empty and failed are three bodies inside the same frame (icon, title and hint stay put), and a failure offers Try again. Returning null on error deletes the feature from the page: the person can't tell broken from empty.

Anatomy

Notifications

Emails Bridge sends you

Updated today

A weekly summary, and new intro requests.

  1. Surface. Frosted glass (liquid-glass) over the page background. lg: 16px corners, 24px padding. md: 12px, 20px. sm: 12px, 16px. flush: no padding. bare: no glass, a row.

  2. Icon or avatar. Optional. icon: a 36px square with 8px corners, a color at 8% behind an 18px icon of that color: blue by default, or green, amber or purple by topic. leading: anything else, like an Avatar, a logo or a checkbox.

  3. Title. 16px bold --text-primary, the card's heading (h2 by default). 14px in a header strip. An optional ⓘ hint beside it.

  4. Description. Optional. One line of 13px --text-muted under the title.

  5. Meta. Optional. 12px --text-muted at the top right: a date, a “New” Tag.

  6. Action. Optional. One control on the right: a link button, an IconButton or a menu.

  7. Footer. Optional. Buttons on the right, under a divider. A picture (CardMedia) can also run across the top, edge to edge.

Examples

A list card

Icon, title, one action, and the card's own loading, empty and error states under the header. Use the demo data controls to try them.

Recent intros

Made or received in the last month

Cards you pick from a list

Click a card to open it beside the list: it tints on hover and turns blue when open. The checkbox inside still works on its own. Tab to a card and press Enter.

  • Jonas Becker → Hannah Weiss

    NewYesterday
    WaitingCEO, Nimbletide → Angel investor
  • Fatima Al-Sayed → Isabella Rossi

    2 days ago
    SentCo-founder & COO, Furrowmint → Halcyra Bio
  • Priya Natarajan → Leah Okonkwo

    4 days ago
    AcceptedCo-founder & CEO, Quillbase → Saltmarsh Partners
  • Kwame Asante → Leah Okonkwo

    6 days ago
    Changes askedCEO, Halcyra Bio → Saltmarsh Partners

Open

Jonas Becker → Hannah Weiss

None ticked

Rows inside a card

Inside a card, items are bare rows split by dividers, never cards in a card. They still open on click, and the face still shows its hover card.

Network activity

Intros made in your network

  • Jonas Becker was introduced to Hannah Weiss

    Yesterday
  • Fatima Al-Sayed was introduced to Isabella Rossi

    2 days ago
  • Priya Natarajan was introduced to Leah Okonkwo

    4 days ago

Tiles

Smaller corners and padding for tiles in a grid.

Waiting for you

2 intros

Leah Okonkwo asked 2 days ago

New in your network

14 people

Since last Monday

Follow-ups due

3 this week

Earliest: Priya Natarajan

A table in a card

A header strip, then rows edge to edge.

Portfolio companies

4 companies

CompanyStage

Quillbase

AI contract review for legal teams

Seed

Ferrolink

Freight booking software for small carriers

Series A

Nimbletide

Payments for online marketplaces

Pre-seed

Furrowmint

Farm-to-shop grocery supply

Seed

States

StateWhat happens
RestGlass over the page background.
Hover, linkRises 2px with a soft shadow.
Hover, pickA light grey tint. A list of rising cards would jump about.
SelectedA blue border and a light blue tint, and screen readers hear it's the current one.
FocusA 2px blue outline around the card.
DisabledFaded to 60%; can't be clicked.

Behavior

  • size: lg (16px corners, 24px padding) for record, table, settings and form cards; md (12px, 20px) for tiles and feed items; sm (12px, 16px) for items in a dense list, like the inbox.
  • strip on the header makes a tinted band across the top, split by a line, with a 14px title. Use it on dense cards and over tables.
  • flush drops the padding so a table or list runs edge to edge. Pair it with a strip header.
  • href makes the whole card a link to a page; onSelect makes it pick the item, with selected on the one that's open. An invisible link or button covers the card and takes the click and keyboard focus. Links, buttons, checkboxes and fields inside sit above it and work on their own, with no extra code.
  • A clickable card needs a name: it takes the CardHeader title, or label when there's no header.
  • bare drops the glass so the card can be a row inside another card or pane, split by dividers. It keeps clicking, hover and selected.
  • Status goes in a Tag in the header (meta), as a word: never a colored edge on the card.
  • Glass clips what's inside it. Menus and tooltips inside a card open outside it, so they're never cut off.
  • className is for layout only (w-full, max-w-md, col-span-2). Never a padding, corner or color.

Do and don't

Do

Put the card's loading, empty and error states inside it, under its header.

Don't

Hide the whole card while its data loads.

Do

Group things inside a card with dividers.

Don't

Put a card inside a card.

Do

Use size="md" for tiles in a grid and lg for big cards.

Don't

Set rounded-[14px] p-7 by eye.

Do

Make a clickable card with href or onSelect, and let buttons inside just work.

Don't

Put onClick on a div and stopPropagation on every button inside.

Do

Show status as a Tag: “Waiting”, “New”.

Don't

Show it only as a colored bar on the card's edge.

Content

  • The title names what's inside in a few words, in sentence case: “Recent intros”, “Notifications”.
  • The description adds one fact, not a sentence of instructions: “4 waiting for you”.

Accessibility

  • The title is a real heading, so screen reader users can jump between cards. Set as to match the page's outline.
  • A clickable card is one link or button named by its title, so screen readers hear “Lanternfield Founders, link” rather than everything inside.
  • The open card in a list is announced as the current one.
  • Clickable cards are reachable with Tab and open with Enter (and Space for picked cards), with a 2px blue outline on focus.
  • Controls inside a clickable card are their own Tab stops, never hidden inside another control.
KeysAction
TabMoves to the card, then to each control inside it.
EnterOpens the card's page, or picks it.
SpacePicks a card that opens beside the list.

API reference

Card

The glass box.

PropTypeDefaultDescription
size"lg" | "md" | "sm""lg"Big card (16px corners, 24px padding), tile (12px, 20px) or list item (12px, 16px).
flushbooleanfalseNo padding, for a table or list edge to edge.
barebooleanfalseNo glass: a row inside another card or pane.
hrefstring—The whole card goes to this page. Rises on hover.
linkAsElementType"a"Your router's link, like Next Link, for href.
onSelect() => void—The whole card picks this item. Tints on hover.
selectedbooleanfalseThe open one: blue border and tint.
disabledbooleanfalseFaded and can't be clicked.
labelstring—The card's name when there's no CardHeader. Clickable cards need one.
classNamestring—Layout only.

CardHeader

Title, with an optional icon, description and action.

PropTypeDefaultDescription
titleReactNode—The card's name.
iconReactNode—A bare Lucide icon, set in the colored square.
iconColor"blue" | "green" | "amber" | "purple""blue"The square's color, by topic: green for outcomes and money, amber for alumni, purple for Super Connectors.
hintstring—A short explanation in an ⓘ beside the title: what a number counts, what a term means.
leadingReactNode—Anything else before the title: an Avatar, a logo, a Checkbox.
metaReactNode—Small things at the top right: a date, a Tag.
compactbooleanfalseA 14px title, for sm cards.
descriptionReactNode—One muted line under the title.
actionReactNode—One control on the right.
stripbooleanfalseA tinted band across the top, with a 14px title.
as"h2" | "h3" | "h4""h2"The title's heading level.

CardMedia

A picture across the top, edge to edge. Put it first.

PropTypeDefaultDescription
srcstring—The picture.
altstring—What it shows, or "" for decoration.
heightnumber128In pixels.

CardFooter

Buttons on the right, under a line.

PropTypeDefaultDescription
childrenReactNode—The buttons, main one last.

Lineage

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

Used by components
None
Used in patterns
None