Card

Displays a card with header, content, and footer.

Basic
Title + description + body — the most common layout.
Cards are surface-level containers that host related content. Everything in this library uses them to scope a demo.
Installation
$Terminal
npx shadcn@latest add https://sdk-components.thesqd.com/r/card.json
Usage
Pass `title`, `description`, `action`, `footer` as props. Children render inside `<CardContent>` automatically.
TSImport
import { Card } from "@/components/ui/card";
TSExample
import { Card } from "@/components/ui/card";

export function Example() {
  return (
    <Card
      title="Heads up"
      description="You can add components to your app using the squad-ui CLI."
    >
      Card content goes here.
    </Card>
  );
}
Composition
Anatomy of the Card primitive.
Card                              (single component — pass content as props)
├── icon={LucideIcon}            (optional — FeaturedIcon above the title)
│   ├── iconColor="brand"         (color token; default "brand")
│   ├── iconVariant="gradient"    (gradient | flat; default "gradient")
│   └── iconSize="lg"             (sm | md | lg | xl | 2xl; default "lg")
├── title={<ReactNode>}           (renders into the header title slot)
├── description={<ReactNode>}     (multi-line / JSX is fine)
├── action={<Button … />}         (optional — top-right of the header)
├── footer={<ReactNode>}          (optional — bordered footer strip)
├── type="default" | "comment" | "image-card"
├── image={url | <Image/>}         (type="image-card" — full-bleed media at the top)
├── imageAlt="…"                   (alt text when image is a URL)
├── ratio="W:H" | "W/H"            (type="image-card" — aspect ratio of the WHOLE card; image fills the remaining space)
├── imageRatio="W:H" | "W/H"       (type="image-card" — aspect ratio of just the image; default "16:9"; ignored when ratio is set)
├── href="…"                       (type="image-card" — makes the whole card a clickable <a>; pair with target / rel)
├── onClick={fn}                   (makes the whole card interactive — cursor-pointer, hover shadow, focus ring, keyboard activation)
├── tag={"New" | <Badge …/>}       (type="image-card" — overlay badge in the top-left of the image)
├── showCornerTab                 (pins a corner tab tinted to match the card outline)
├── cornerTabContent={text | <Comp/>}  (tab contents — string or any ReactNode)
├── cornerTabPosition="top-right" (top-right | top-left | bottom-right | bottom-left)
├── cornerTabClassName="…"        (override the tab's padding / text / background)
├── children                      (auto-wrapped in <CardContent> unless contentWrapper="none")
├── size="default" | "sm"
└── contentWrapper="card-content" | "none"

Need a non-standard layout (e.g. an image-only card, custom header grid, or
two stacked content sections)? The slot exports — CardHeader, CardTitle,
CardDescription, CardAction, CardContent, CardFooter — are still exported
from the same file as an escape hatch. Drop the prop API for that one card
and compose the slots directly.
Basic
Title + description + body — the most common layout.
Basic
Title + description + body — the most common layout.
Cards are surface-level containers that host related content. Everything in this library uses them to scope a demo.
Content only
Pass just `children` — no `title` or `description`. The body fills the whole padded surface.
Cards are surface-level containers that host related content. With no title or description, the body fills the whole padded surface.
With icon
Pass any lucide icon to `icon` to render a `FeaturedIcon` above the title. Tune it with `iconColor`, `iconVariant`, and `iconSize`.
Brand
`onClick` makes the whole card interactive. Click me for a toast.
Amber
`iconColor` tints the FeaturedIcon — mirrors the Badge palette.
Flat indigo
`iconVariant="flat"` swaps the gradient chip for a soft flat tint.
With action
`action` slots a secondary control into the top-right of the header.
With action
action slots a secondary control into the top-right of the header.
Use this for links that jump to a fuller view or toggles that affect the card's contents.
Small size
size="sm" tightens the paddings and shrinks the title — useful for dense grids.
Small size
size="sm" tightens the paddings and shrinks the title.
Useful for dense grids of cards where a lot of surfaces share the viewport.
Image card
Pass `type="image-card"` plus `image`, `title`, and `description` for a full-bleed media tile. Use `imageRatio` to shape the image alone (default `"16:9"`); use `ratio` to lock the **whole card** to a target aspect — the image then fills the remaining space above the caption.
Modern kitchen with grey cabinetry
New
Linked card
`href` makes the whole card clickable. `tag` overlays a Badge in the top-left.
Modern kitchen with grey cabinetry
Square card
`ratio="1:1"` — whole card is square; image fills the remaining space.
Modern kitchen with grey cabinetry
Portrait card
`ratio="4:5"` — portrait card; image fills above the caption.
Corner tab
Set `showCornerTab` and `cornerTabContent` to pin a little tab to a corner of the card — its background matches the card's outline. The content can be plain text or any component. Move it with `cornerTabPosition` and restyle it with `cornerTabClassName`.
New
Text tab
`cornerTabContent` takes a plain string for the default styled tab.
The tab background matches the card's outline.
Pro
Component tab
Pass any ReactNode — here an icon + label.
Render whatever you like inside the tab.
Component tab
Drop any component into the tab — here a tiny `CircularProgress`.
The tab concavely flows into the card's top-right corner.
Pricing grid
Two cards laid out in a responsive two-column grid with per-card footers.
Plan — Team
For growing squads that need more room.

$29/mo

Plan — Business
For larger orgs with advanced needs.

$79/mo

API Reference
Props exposed by the Card component.
PropTypeDefaultDescription
titleReactNodeHeading rendered inside the auto-emitted CardHeader.
descriptionReactNodeSubheading. Accepts strings or JSX (multi-line, links, code).
iconComponentType<{ className?: string }>Lucide icon (or any `({ className }) => JSX`) rendered as a `FeaturedIcon` above the title.
iconColorFeaturedIconColor"brand"Color token for the `icon`'s FeaturedIcon.
iconVariant"gradient" | "flat""gradient"Surface treatment for the `icon`'s FeaturedIcon.
iconSize"sm" | "md" | "lg" | "xl" | "2xl""lg"Size of the `icon`'s FeaturedIcon.
actionReactNodeTop-right slot inside the header — typically a small button or link.
footerReactNodeFooter strip. Wrap multiple buttons in a flex row to align them.
size"default" | "sm""default"`sm` tightens paddings and shrinks the title — good for dense grids.
contentWrapper"card-content" | "none""card-content"When the prop API is in use, children are wrapped in `<CardContent>` by default. Set to `"none"` to render them inline (no padding).
type"default" | "comment" | "image-card""default"`image-card` swaps the layout for a full-bleed image at the top with a controllable aspect ratio, then title + description below. `comment` renders an avatar + name + time header.
imagestring | ReactNode`type="image-card"` — image URL (rendered as `<img>` with `object-cover`) or any ReactNode (e.g. `<Image>` from next/image).
imageAltstringAlt text used when `image` is a URL.
ratiostring`type="image-card"` — aspect ratio for the **whole card** (image + caption). Accepts `"W:H"` / `"W/H"`. When set, the image fills the remaining space above the caption. Leave undefined for auto-height.
imageRatiostring"16:9"`type="image-card"` — aspect ratio for the **image** only. Accepts `"W:H"` / `"W/H"` (e.g. `"4:3"`, `"1:1"`). Ignored when `ratio` is set.
hrefstring`type="image-card"` — makes the entire card a clickable link (renders as `<a>`). Pair with `target` / `rel` as needed. Adds a hover shadow + subtle image zoom.
targetHTMLAttributeAnchorTargetAnchor target when `href` is set.
relstringAnchor rel when `href` is set.
tagReactNode`type="image-card"` — overlay badge in the top-left corner of the image. Pass a string for a default `<Badge>` or any ReactNode (e.g. `<Badge variant="secondary">…</Badge>`) for full control.
showCornerTabbooleanfalseRender a small corner tab clipped to one corner of the card, tinted to match the card's outline (`ring-foreground/10`). Requires `cornerTabContent`.
cornerTabContentReactNodeContent shown inside the corner tab. Pass a string/number for the default styled tab, or any ReactNode (including your own component).
cornerTabPosition"top-right" | "top-left" | "bottom-right" | "bottom-left""top-right"Which corner the tab sits in.
cornerTabClassNamestringExtra classes for the tab element — override its padding, text, or background.
onClick(e) => voidClick handler. On any card it makes the whole surface interactive — adds `cursor-pointer`, a hover shadow, a focus ring, and keyboard activation (Enter/Space) with `role="button"`.
classNamestringOverride or extend the resolved Card classes.