Design HubStudio

6. Cards

Bounded containers that group related content. The most versatile primitive — and the most over-used. Every card costs a border, padding, and visual weight; reach for one only when grouping conveys meaning.

Gallery

Three configurations, all composed from the same five hooks: .card, .card-header, .card-body, .card-footer, .card-interactive.

When to use each

Three composition decisions. Cards are about choices, not variants — most card abuse is using one when raw content would read more clearly.

Card vs. raw content
Notifications
Daily summary
Run completion
Critical errors only
Card — when grouping conveys meaning
Multiple related controls or items that form a unit. The user reads the group as one thing, makes coordinated decisions about it, and the card title names that unit. Settings groups, list items in a card-list, dashboard tiles.

Notifications

Manage how Titan tells you about runs, errors, and daily activity. Settings apply to your account only.

Raw content — when grouping doesn't
A heading and paragraph that flow with the surrounding page. Wrapping prose in a card adds visual weight that hurts reading; the section heading already does the grouping. Cards aren't decoration.
Static vs. interactive
Device status
LidMate 2Online
DecapperMaintenance
Static — actions inside
The card is a grouping; specific actions live inside (in the footer or inline). The card itself isn't clickable. Used for most informational and form cards.
Active runs3View all →
Interactive — the whole card is the affordance
Whole card click navigates or expands. Use only when there's ONE obvious destination per card. Card-lists, navigation tiles, dashboard summaries. Pair with hover state via .card-interactive.
Footer — or not
Edit name
With footer — actions live here
Use a footer when the card has discrete actions (Save/Cancel, Open, Delete) or metadata (timestamp, author) that anchors the card's content. Right-align action buttons; metadata can go left.
Last sync
2 minutes ago, from controller-A
No footer — content stands alone
Skip the footer when there's nothing to put there. An empty footer or a footer that exists for visual balance is noise. Most informational cards (stat tiles, status summaries) end with the body.
Drift to avoid

Seven named anti-patterns. Cards are the easiest primitive to abuse precisely because they're so versatile.

  • Don't wrap every paragraph in a card
    Principle 5
    Cards aren't decoration. Each adds border, padding, and visual weight that competes with content. If a paragraph just continues the surrounding page, leave it as prose. Reach for a card only when grouping conveys meaning.
  • Don't nest cards within cards
    Principle 1
    A card inside a card means the inner content is wrapped in two layers of bordered scaffolding — borders, padding, and backgrounds compound. Flatten: either remove the inner card or remove the outer one. The hierarchy should come from spacing and headings, not stacked containers.
  • Don't use .card-interactive without a destination
    UX
    Hover state implies clickability. If the card hover-lifts but clicking does nothing — or only triggers an inner button's action — drop .card-interactive. A hover without a payoff is a broken affordance.
  • Don't mix card and non-card siblings at the same level
    Principle 1
    Three sections on a page, two wrapped in cards and one not — the eye reads the unwrapped section as "different" even if the content is parallel. Pick one container pattern per level of hierarchy.
  • Don't combine border + shadow + tinted background
    Principle 1
    Pick one elevation mechanism. The canonical card uses border + surface color. Adding a shadow makes the card "lifted." Adding both shadow AND a colored background tint is three elevation signals stacked — read as visual noise.
  • Don't duplicate the page section title in the card header
    Principle 1
    If the page section is titled "Notifications" and contains one card titled "Notifications", drop the card header. The page title already names what this is. Saying it twice doesn't make it more findable; it makes the layout feel padded.
  • Don't use a card as a fake button
    Principle 2
    If the entire card is meant to trigger one action with no other content, you don't want a card — you want a button. Use .btn-secondary or .btn-ghost sized appropriately. Cards are containers; buttons are actions.
Composition — workcell overview

Four cards arranged with intent. Three stat tiles up top (one interactive — it links to the runs list), one content card below it for recent activity. Each card earns its grouping; nothing is wrapped just because.

Plates today1,284+12% vs yesterday
Avg run time47 min-3 min vs last wk
Active runs3View all →
Recent activity
PlateStatusOwnerUpdated
Plate-A03Readyimad2 min ago
Plate-A04Runningdf4 min ago
Plate-A05Stalledimadjust now
Plate-B01Readyjsmith12 min ago
  • stat tiles × 3 Each card groups one metric — label, value, delta. Independent units that read horizontally
  • one interactive "Active runs" links to the runs list; only that card hover-lifts because only it has a destination
  • content card with table Header carries title + secondary action; body contains a compact table flush with the card edges (padding: 0)
  • no nested cards The table sits directly inside the card body — not wrapped in a sub-card. One container per grouping