Skip to content
Component installs need the registry setup— the Base UI shadcn project, the @vegastack namespace and the Cloudflare Access service token.
VegaStack Design

Card

A borders-only content surface for grouping related information — no shadows, with composable header, content, and footer parts.

Status
stable
Since
0.1.0
Accessibility pattern
presentational grouping

Last updated

Account activity
A summary of your recent sign-ins.
You signed in from 3 devices in the last 7 days.

Install

Add Card from the VegaStack registry. The CLI verifies the item's integrity hash before writing it.

pnpm dlx shadcn@latest add @vegastack/card

Usage

import {
  Card,
  CardAction,
  CardContent,
  CardDescription,
  CardFooter,
  CardHeader,
  CardTitle,
} from "@/components/ui/card";

<Card>
  <CardHeader>
    <CardTitle>Account activity</CardTitle>
    <CardDescription>A summary of your recent sign-ins.</CardDescription>
  </CardHeader>
  <CardContent>You signed in from 3 devices in the last 7 days.</CardContent>
</Card>;

Anatomy

Card is a compound component built from plain, server-safe divs. Compose the parts inside the root — every part forwards its ref and exposes a data-slot:

Card — data-slot="card"
CardAction — data-slot="card-action"
CardContent — data-slot="card-content"
CardDescription — data-slot="card-description"
CardFooter — data-slot="card-footer"
CardHeader — data-slot="card-header"
CardTitle — data-slot="card-title"
<Card>
  <CardHeader>
    <CardTitle>Title</CardTitle>
    <CardDescription>Supporting description text.</CardDescription>
    <CardAction>{/* optional top-right control */}</CardAction>
  </CardHeader>
  <CardContent>{/* main body */}</CardContent>
  <CardFooter>{/* actions */}</CardFooter>
</Card>
  • Card — the root surface (data-slot="card"). Borders-only, rounded-lg, bg-card text-card-foreground. Owns the size density (md / sm).
  • CardHeader — top region (data-slot="card-header"). Switches to a two-column grid when a CardAction is present.
  • CardTitle — the heading line (data-slot="card-title").
  • CardDescription — muted supporting text under the title (data-slot="card-description").
  • CardAction — an optional control anchored top-right of the header (data-slot="card-action").
  • CardContent — the main body region (data-slot="card-content").
  • CardFooter — a bottom region with a top border and muted background (data-slot="card-footer"). When a footer is present, the root drops its own bottom padding (pb-0) so the footer sits flush against the bottom edge.

Examples

A card with a header, content, and a footer action row:

Team plan
$20 / user / month, billed annually.
Popular
Everything in Pro, plus SSO, audit logs, and priority support.

Sizes

Card exposes a single size density prop (md / sm). sm tightens the internal padding (py-3 / px-3 instead of py-4 / px-4), shrinks the part gap (gap-3 vs gap-4), and steps the title down to text-sm. Set it once on the root — the header, content, and footer all react via group-data-[size=sm].

Default density
size="default"
Roomier padding (py-4 / px-4), gap-4, and a base-size title.
Compact density
size="sm"
Tighter padding (py-3 / px-3), gap-3, and a smaller title.

Playground

Toggle the density between default and small, then copy the generated JSX.

Team plan
$20 / user / month
Everything in Pro, plus SSO and audit logs.
<Card>
  <CardHeader>
    <CardTitle>Team plan</CardTitle>
    <CardDescription>$20 / user / month</CardDescription>
  </CardHeader>
  <CardContent>Everything in Pro, plus SSO and audit logs.</CardContent>
</Card>

API Reference

Card

PropTypeDefaultDescription
size"md" | "sm""md"Density of the card. sm tightens the internal padding and gaps.

Data attributes and CSS variables on Card

AttributeValues
data-sizemirrors a prop or state value
data-slot"card"

CardHeader, CardTitle, CardDescription, CardAction, CardContent, and CardFooter add no props of their own — each accepts everything a <div> accepts (className, ref, children, …).

Accessibility

  • Card is a presentational grouping element with no implicit ARIA role — give it semantic meaning through its content (a real heading inside CardTitle, a role/aria-label on the root if it is interactive).
  • CardTitle renders a styled div. When the card should participate in the page outline, place a real heading inside it, for example <CardTitle><h3>Team plan</h3></CardTitle>.
  • Interactive controls (CardAction, footer buttons) are native elements and keep their own focus rings — the card never suppresses outline.
  • Borders-only by design: the surface is distinguished by border-border, not a shadow, keeping it legible in high-contrast and forced-colors modes.
KeyAction
TabMove focus through interactive controls inside the card (actions, footer buttons).
Enter / SpaceActivate the focused control.
ContractStates tested
Behaviourdefault
Accessibilitynative-or-base-ui-semantics, browser-accessibility-test
Visualdefault

Do / Don't

Do
Group genuinely related content and put primary actions in the footer.
Don't
Add a drop shadow or nest cards inside cards — the design system is borders-only and flat.

On this page