Skip to content
HyperDesign System

Card

The section surface: 22px corners, a hairline edge drawn as a shadow, and the heading face on the title. Seven parts compose a header, a body and a footer. Source: src/components/ui/card.tsx.

Anatomy

CardHeader holds the title, description and an optional CardAction pinned top-right. CardContent is the body. CardFooter is a tinted strip with a hairline above it; the card drops its bottom padding when one is present.

Weekly digest
Sent to #eng-updates every Monday at 09:00.
Last run
Mon 09:00
Threads
42

Sizes

size sets one variable, --card-spacing, and every part pads from it. sm is for dense grids; none hands the padding to the content, for a card that wraps a table or an image.

Default
16px padding and gap.
Small
12px; the title steps down to 14px.

none: the content brings its own padding.

Interactive

variant="interactive" with asChild around a Link: the whole card is one target and lifts its shadow on hover. Focus falls back to the global outline; the variant has no focus or press style of its own yet.

Ruled header

Give CardHeader a border-b and it adds its own bottom padding, so a figure or a list sits under a hairline without extra spacing.

Usage this month
Oct 1 – Oct 28
$184.20of $250 cap

Props

Card props
PropTypeDefaultDescription
size"default" | "sm" | "none""default"Card. Sets --card-spacing (16px, 12px, 0), which every part reads for its padding and gap.
variant"default" | "interactive""default"Card. interactive adds a shadow-card-hover lift on the slow duration. No focus or press style of its own.
asChildbooleanfalseCard. Render the single child (a Link, an li, a button) as the shell, via Radix Slot.
classNamestring—Every part. Merged last.
...propsComponentProps<"div">—Every part is a div with a data-slot: card, card-header, card-title, card-description, card-action, card-content, card-footer.

Best practices

When to use

  • Group content that belongs together and can be read on its own: a setting, an integration, a summary figure.
  • Not for every block on a page. A list of rows reads better as rows divided by hairlines.

Behavior

  • One target per card. If the whole card links, don't put other buttons inside it; nested interactive elements fight for the click.
  • CardAction takes one control (a menu, a status badge). More than one belongs in the footer.
  • Keep cards on the secondary surface or the canvas; the hairline edge is tuned for both.

Accessibility

  • CardTitle is a div. When the card starts a section, pass an h2 or h3 inside it (or use asChild on a heading) so the outline makes sense.
  • An interactive card must be a real link or button via asChild, never a div with onClick.
  • Icon-only actions in CardAction need an aria-label.

Content

  • Title in sentence case, a few words. Description: one line that says what it is or when it runs.
  • Footer actions right-aligned, the primary action last.