Card

A generic, shadcn-style content surface. Compose the parts explicitly so each card can carry its own header layout, body shape, or action row without per-prop overrides on the Root.

Bloom the aromatics

~3 min · medium effort

Warm the oil over medium heat, then add the spices and stir until they smell like themselves.
Footer actions sit here.
Customize
Variant
default
Slots

Installation

npx shadcn@latest add https://craftbits.dev/r/card.json

Usage

import { Card } from "@craft-bits/core";
 
<Card.Root variant="elevated">
  <Card.Header>
    <Card.Title>Bloom the aromatics</Card.Title>
    <Card.Description>~3 min · medium effort</Card.Description>
  </Card.Header>
  <Card.Content>
    Warm the oil over medium heat, then add the spices and stir until they
    smell like themselves.
  </Card.Content>
  <Card.Footer>
    <button>Mark done</button>
  </Card.Footer>
</Card.Root>

Anatomy

  • Card.Root — outer surface. Owns the variant (border + lift) and the vertical-stack rhythm (gap-4) between Header, Content, and Footer.
  • Card.Header — tight stack (gap-1) for Title + optional Description.
  • Card.Title — primary heading. Renders as <h3>. Serif, [text-wrap:balance].
  • Card.Description — supporting copy. <p>, muted tone, [text-wrap:pretty].
  • Card.Content — body slot.
  • Card.Footer — bottom row. flex items-center gap-2 so a row of buttons baselines cleanly.

Variants

  • default — 1px border on the elevated surface, no shadow. The base.
  • elevated — same border + soft two-layer lift shadow (neutral RGB at low alpha — never pure black). Use when the card is the page's primary read.
  • ghost — no border, transparent surface. Composes inside other chrome without doubling the frame.

Props

Card.Root

PropTypeDefaultDescription
variant'default' | 'elevated' | 'ghost''default'Surface treatment.
classNamestringMerged onto the root <div> via cn().

Card.Header / Card.Content / Card.Footer each accept HTMLAttributes<HTMLDivElement>. Card.Title renders <h3>. Card.Description renders <p>.

Accessibility

  • Card.Root renders a plain <div> — no implicit role. Wrap a grid of cards in <ul> / <li> (or supply role="list" / role="listitem") when the order is semantically meaningful.
  • Card.Title is an <h3>. Keep the document outline correct by placing the card under an <h2> section.
  • Card.Description is a <p>, not a heading.
  • The lift shadow on variant="elevated" is decorative; the border still carries the affordance at high-contrast / forced-colors.
  • No motion — safe for users with prefers-reduced-motion: reduce.

Credits

  • Extracted from: algoflashcards (src/platform/ui/card.tsx). The source was a flat 6-slot shadcn card with a size prop and rounded-4xl baked in. The library extract drops CardAction (compose your own button row inside Card.Footer), replaces bg-card / text-card-foreground / ring-foreground/8 with cb-* semantic tokens, and exposes the size knob as a variant matrix (default / elevated / ghost) so the shadow story stays explicit.