Component

Card

Compose linked, static, or button-backed editorial cards from image, body, footer, tag, and action slots.

Interactive preview

Usage

Import the component entry and start with its smallest complete example.

Import

import { Card } from "@chitrank2050/monoline-ui/card"

Basic usage

<Card href="/blog/tunic-storefront" size="md">
  <Card.Image ratio="landscape" placeholder>
    <Card.ImageCaption>COVER · STOREFRONT</Card.ImageCaption>
  </Card.Image>
  <Card.Body>
    <Card.Header>
      <Card.Meta>
        <span>2022</span>
        <span>Professional</span>
      </Card.Meta>
      <Card.Title>Tunic Storefront</Card.Title>
      <Card.Eyebrow>Tunic · Advisor → Founding Eng, 2022–23</Card.Eyebrow>
      <Card.Description lines={3}>
        A headless commerce framework for boutique brands. Replaces three SaaS tools with a single Next.js app.
      </Card.Description>
    </Card.Header>
  </Card.Body>
  <Card.Footer>
    <Card.TagList totalCount={4}>
      <Badge variant="muted" size="sm">Next.js</Badge>
      <Badge variant="muted" size="sm">Sanity</Badge>
      <Badge variant="muted" size="sm">Vercel</Badge>
    </Card.TagList>
    <Card.Action>View <Card.Arrow /></Card.Action>
  </Card.Footer>
</Card>

Usage guidance

Choose the component for its interaction model and semantics before customizing its appearance.

01
Use when

Card suits a content summary that stays static or acts as one link or button.

02
Avoid when

A clickable card would contain several independent controls.

03
Accessibility

Card selects native anchor, button, or div semantics from href and onClick, defaults button cards to type button, and requires the chosen root to have a clear accessible name.

04
Server Component

This component can render without adding a Monoline client boundary when its children and props are serializable.

API reference

Props, slots, and callbacks available on this component.

sizesm | md | lgCard radius and internal slot spacing
hrefstringRender the card as a native anchor for internal or external links
target"_self" | "_blank" | "_parent" | "_top"Native anchor target
relstringNative anchor rel. Defaults to noopener noreferrer for target=_blank
Card.Image.ratio"square" | "portrait" | "landscape" | "wide"Reserved image area preset
Card.Image.placeholderbooleanRenders the built-in media placeholder
Card.ImageCaptionReactNodeBottom-aligned media label with built-in fade
Card.EyebrowReactNodeSecondary mono line under the title
Card.Description.lines2 | 3 | 4Built-in description clamping
Card.TagList.totalCountnumberComputes a smart +N marker from rendered tags vs total count
asChildbooleanRender child through Radix Slot
childrenReactNodeCard slots and content

Design tokens

Theme variables this component reads for color, spacing, and motion.

--surfaceCSS varCard background
--borderCSS varDefault card outline
--shadow-cardCSS varHover elevation
--duration-shortCSS varImage color and surface feedback timing

Implementation

The source used by the example above, including any state it needs.

import { Badge } from "@chitrank2050/monoline-ui/badge"
import { Card } from "@chitrank2050/monoline-ui/card"

export function ProjectCard() {
  return (
    <Card href="/projects/tunic-storefront">
      <Card.Image ratio="landscape" placeholder>
        <Card.ImageCaption>COVER · STOREFRONT</Card.ImageCaption>
      </Card.Image>
      <Card.Body>
        <Card.Header>
          <Card.Meta>
            <span>2022</span>
            <span>Professional</span>
          </Card.Meta>
          <Card.Title>Tunic Storefront</Card.Title>
          <Card.Eyebrow>Tunic · Advisor → Founding Eng, 2022–23</Card.Eyebrow>
          <Card.Description lines={3}>
            A headless commerce framework for boutique brands. Replaces three SaaS tools with a single Next.js app.
          </Card.Description>
        </Card.Header>
      </Card.Body>
      <Card.Footer>
        <Card.TagList totalCount={4}>
          <Badge variant="muted" size="sm">Next.js</Badge>
          <Badge variant="muted" size="sm">Sanity</Badge>
          <Badge variant="muted" size="sm">Vercel</Badge>
        </Card.TagList>
        <Card.Action>View <Card.Arrow /></Card.Action>
      </Card.Footer>
    </Card>
  )
}