Skip to content

ComponentsDisplay

Card

A surface that groups related content and actions. Four surface styles, three padding sizes, a header with an action slot and optional hairline, an inset surface for previews, and a footer for actions. Server-component safe.

Source
Sign in
Welcome back. Enter your details.

Installation

pnpm dlx shadcn@latest add @desyne/card

The CLI installs dependencies and any other components this one uses.

Usage

tsx
import {
  Card,
  CardAction,
  CardContent,
  CardDescription,
  CardFooter,
  CardHeader,
  CardInset,
  CardTitle,
} from "@/components/ui/card";
tsx
<Card>
  <CardHeader>
    <CardTitle>Usage this month</CardTitle>
    <CardDescription>Resets on the 1st.</CardDescription>
  </CardHeader>
  <CardContent>…</CardContent>
  <CardFooter>…</CardFooter>
</Card>

Plain elements, no client JavaScript

Every card part is a styled <div> with no React Aria behavior and no "use client" directive, so cards render in server components. Put interactive children (buttons, fields, links) inside and they bring their own behavior.

When to use

  • Card: a self-contained group of content with its own heading, such as a stat, a settings section, a pricing tier or a preview.
  • Item: a single row inside a list (media, a title, a quiet second line and actions). Stack items inside a card rather than stacking cards.
  • Alert: a message that needs attention, not a container.
  • Dialog or Sheet: content that should interrupt or overlay the page.
  • Avoid wrapping a whole page in one card, and avoid nesting outline cards; use filled or CardInset for an inner surface.

Anatomy

tsx
<Card>                  {/* surface: variant, size (sets --card-px) */}
  <CardHeader>          {/* grid: title + description, action on the right */}
    <CardTitle />       {/* a leading svg becomes an icon */}
    <CardDescription />
    <CardAction />      {/* top-right slot: button, badge, menu */}
  </CardHeader>
  <CardContent>         {/* horizontally padded body */}
    <CardInset />       {/* optional muted inner surface */}
  </CardContent>
  <CardFooter />        {/* row of actions or meta text */}
</Card>
PartRendersNotes
Card<div>Root. Flex column with vertical padding and a gap between parts. Sets the --card-px variable used by the other parts.
CardHeader<div>Two-row grid. Switches to two columns when it contains a CardAction. separator draws an inset hairline underneath.
CardTitle<div>Medium-weight title. Any direct svg child is sized to 16px and spaced as a leading icon.
CardDescription<div>Muted supporting text.
CardAction<div>Pinned to the top-right of the header, spanning both rows.
CardContent<div>Adds the card's horizontal padding.
CardInset<div>A rounded, muted surface for previews, code, media or empty states. Add your own padding.
CardFooter<div>Horizontal flex row with the card's horizontal padding.

The parts render as <div> for layout flexibility. CardTitle is not a heading element; if the card title should appear in the document outline, put an <h2>/<h3> inside it.

Examples

Variants

outline is the default and suits most dashboard surfaces. elevated lifts featured content with a soft shadow, filled is a muted panel with no border for secondary or nested content, and ghost keeps the spacing and slots with no surface at all.

Outline
The default. A hairline border for most dashboard surfaces.
variant="outline"
Elevated
A soft shadow that lifts featured content off the page.
variant="elevated"
Filled
A muted fill with no border, for secondary or nested panels.
variant="filled"
Ghost
No surface at all. Keeps the spacing and slots only.
variant="ghost"

Sizes

size controls the vertical padding, the gap between parts and the --card-px horizontal padding every part reads. sm (12px) suits dense grids, md (16px) is the default and lg (24px) suits forms and focused content.

Size sm
12px padding and gap. Dense grids and sidebars.
Size md
16px padding and gap. The default.
Size lg
24px padding and gap. Forms and focused pages.

Header, action and inset

Pass separator to CardHeader for an inset hairline aligned with the content. An svg inside CardTitle becomes a leading icon, CardAction holds one quiet action in the top-right corner, and CardInset is the muted surface for the headline figure.

Product health
Health score87

An icon title, an inset divider and one quiet action: the anatomy every widget card shares.

Add border-b to CardHeader or border-t to CardFooter for full-width dividers; the parts add matching padding on the bordered side automatically. Use this for settings sections where the footer holds the save action.

Workspace name
Shown in the sidebar, invitations and email notifications.

Max. 32 characters.

Media

For an edge-to-edge cover, remove the top padding with pt-0 and clip the corners with overflow-hidden. The cover can be an image, video or illustration.

Conference
Design Systems Summit 2026
Two days of talks on tokens, accessibility and component APIs.
Nov 12–13, 2026 Lisbon, Portugal

Stat cards

A description, a large tabular value in CardTitle and a trend Badge in CardAction make a compact KPI tile. Use size="sm" in grids.

Active users
12,480
+8.2%
vs. last 7 days
Open incidents
7
-3
vs. last 7 days

Interactive cards

isInteractive only adds a pointer cursor and hover feedback; it does not make the card focusable or clickable. Put a real link inside and stretch it over the card with an after:absolute after:inset-0 overlay, so middle-click, "open in new tab" and keyboard focus keep working. has-[a:focus-visible] moves the focus ring to the card.

Guides, concepts and the full API reference.
Copy-paste starting points for common screens.

Loading

Mirror the final layout with Skeleton blocks so nothing shifts when data arrives. Mark the card aria-busy while it loads.

Empty state

Use CardInset as a quiet frame for an empty state, with one clear action to fill it.

Webhooks

No endpoints yet

Send events to your own services when deployments finish or fail.

Recipes

Pricing tiers

Two tiers side by side. The featured plan uses elevated with a ring and a "Popular" badge in CardAction; size="lg" gives the content room.

Starter
For side projects and small teams.

$0/ user / month

  • 3 projects
  • 1,000 events / day
  • Community support
Team
For growing teams shipping every week.
Popular

$24/ user / month

  • Unlimited projects
  • 250,000 events / day
  • Role-based access
  • Email support

Settings section

A notification settings panel: a header with an icon and hairline, a list of Switches with descriptions, and a bordered footer for the save action.

Email notifications
Choose what lands in your inbox.

Team members

A card that holds a list of Item rows with Avatars, role badges and a per-row menu button. px-2 on CardContent lets row hover backgrounds reach closer to the edge.

Team members
3 of 5 seats used on the Team plan.
OM
Olivia Martin

olivia@northwind.io

Owner
JL
Jackson Lee

jackson@northwind.io

Admin
IN
Isabella Nguyen

isabella@northwind.io

Member

Accessibility

  • Cards have no role. They're visual grouping only; screen readers read the content in order.
  • CardTitle renders a <div>. When the card's title is a real section heading, render a heading element inside it (for example <CardTitle><h3>…</h3></CardTitle>) so it shows up in the heading outline.
  • For a card that navigates, use a real link (see Interactive cards); don't put onClick on the card <div>. Keep other interactive elements outside the stretched link's overlay, or raise them with relative z-10.
  • isInteractive is purely visual. It doesn't add focus, a role or keyboard handling.
  • If a card is a meaningful landmark (for example a named region of a dashboard), add role="region" and aria-labelledby pointing at its title.

Styling

Data attributes

AttributeOnPresent when
data-slot="card"CardAlways
data-slot="card-header"CardHeaderAlways
data-separatorCardHeaderseparator is true
data-slot="card-title"CardTitleAlways
data-slot="card-description"CardDescriptionAlways
data-slot="card-action"CardActionAlways. CardHeader switches to two columns when it contains one.
data-slot="card-content"CardContentAlways
data-slot="card-inset"CardInsetAlways
data-slot="card-footer"CardFooterAlways

Card also sets the group/card Tailwind group, so children can react to hover with group-hover/card:….

Padding variable

Every part reads its horizontal padding from --card-px, which size sets. Override it to change the padding everywhere at once:

tsx
<Card className="[--card-px:--spacing(5)]">…</Card>

cardVariants

The tailwind-variants function behind Card. Use it to give another element (a <section>, a link, a React Aria GridListItem) the card surface.

tsx
import { cardVariants } from "@/components/ui/card";

<section className={cardVariants({ variant: "elevated", size: "lg" })}>…</section>;

API Reference

Card

Prop

Type

Also accepts every prop of <div>.

CardHeader

Prop

Type

Also accepts every prop of <div>.

CardTitle / CardDescription / CardAction / CardContent / CardInset / CardFooter

No extra props. Each accepts every prop of <div>.

cardVariants

Prop

Type

  • Item: list rows to place inside a card.
  • Badge: status and trend labels for card actions.
  • Skeleton: loading placeholders that match a card's layout.
  • Separator: dividers between sections of a card.