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”.
The frosted-glass box most of Bridge sits in: lists, tables, forms and tiles.
import { … } from "@brdgapp/ui/components/card"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.
size="md").href).onSelect, selected).bare).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.
Emails Bridge sends you
A weekly summary, and new intro requests.
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.
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.
Title. 16px bold --text-primary, the card's heading (h2 by default). 14px in a header strip. An optional ⓘ hint beside it.
Description. Optional. One line of 13px --text-muted under the title.
Meta. Optional. 12px --text-muted at the top right: a date, a “New” Tag.
Action. Optional. One control on the right: a link button, an IconButton or a menu.
Footer. Optional. Buttons on the right, under a divider. A picture (CardMedia) can also run across the top, edge to edge.
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.
Made or received in the last month
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.
Open
Jonas Becker → Hannah Weiss
None ticked
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.
The whole card opens the network and rises on hover. A picture can run across the top.
Smaller corners and padding for tiles in a grid.
2 intros
Leah Okonkwo asked 2 days ago
14 people
Since last Monday
3 this week
Earliest: Priya Natarajan
A header strip, then rows edge to edge.
4 companies
| Company | Stage |
|---|---|
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 |
| State | What happens |
|---|---|
| Rest | Glass over the page background. |
| Hover, link | Rises 2px with a soft shadow. |
| Hover, pick | A light grey tint. A list of rising cards would jump about. |
| Selected | A blue border and a light blue tint, and screen readers hear it's the current one. |
| Focus | A 2px blue outline around the card. |
| Disabled | Faded to 60%; can't be clicked. |
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.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.meta), as a word: never a colored edge on the card.className is for layout only (w-full, max-w-md, col-span-2). Never a padding, corner or color.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
Usesize="md" for tiles in a grid and lg for big cards.Don't
Setrounded-[14px] p-7 by eye.Do
Make a clickable card withhref or onSelect, and let buttons inside just work.Don't
PutonClick 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.as to match the page's outline.| Keys | Action |
|---|---|
| Tab | Moves to the card, then to each control inside it. |
| Enter | Opens the card's page, or picks it. |
| Space | Picks a card that opens beside the list. |
Card
The glass box.
| Prop | Type | Default | Description |
|---|---|---|---|
size | "lg" | "md" | "sm" | "lg" | Big card (16px corners, 24px padding), tile (12px, 20px) or list item (12px, 16px). |
flush | boolean | false | No padding, for a table or list edge to edge. |
bare | boolean | false | No glass: a row inside another card or pane. |
href | string | — | The whole card goes to this page. Rises on hover. |
linkAs | ElementType | "a" | Your router's link, like Next Link, for href. |
onSelect | () => void | — | The whole card picks this item. Tints on hover. |
selected | boolean | false | The open one: blue border and tint. |
disabled | boolean | false | Faded and can't be clicked. |
label | string | — | The card's name when there's no CardHeader. Clickable cards need one. |
className | string | — | Layout only. |
CardHeader
Title, with an optional icon, description and action.
| Prop | Type | Default | Description |
|---|---|---|---|
title | ReactNode | — | The card's name. |
icon | ReactNode | — | 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. |
hint | string | — | A short explanation in an ⓘ beside the title: what a number counts, what a term means. |
leading | ReactNode | — | Anything else before the title: an Avatar, a logo, a Checkbox. |
meta | ReactNode | — | Small things at the top right: a date, a Tag. |
compact | boolean | false | A 14px title, for sm cards. |
description | ReactNode | — | One muted line under the title. |
action | ReactNode | — | One control on the right. |
strip | boolean | false | A 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.
| Prop | Type | Default | Description |
|---|---|---|---|
src | string | — | The picture. |
alt | string | — | What it shows, or "" for decoration. |
height | number | 128 | In pixels. |
CardFooter
Buttons on the right, under a line.
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | — | The buttons, main one last. |
What it's built from and where it's used, read from the code. When you change it, check these too.