Skip to main content

Overview

Team overview
Summary of active members.
12 members active this week.
Flat card
Subtle container without elevation.
+12.5%
Total Revenue
$48,295
Card is a versatile surface container. It comes in several variants: default (border + shadow), flat (no shadow), hoverable (interactive), stat (KPI display), and media (image header).

Installation

npm install @araf-ds/core

Usage

import {
  Card,
  CardContent,
  CardDescription,
  CardFooter,
  CardHeader,
  CardStat,
  CardTitle,
} from "@araf-ds/core"

export default function Example() {
  return (
    <Card>
      <CardHeader>
        <CardTitle>Team overview</CardTitle>
        <CardDescription>Summary of your active team members.</CardDescription>
      </CardHeader>
      <CardContent>
        <p>12 members active this week.</p>
      </CardContent>
      <CardFooter>
        <Button variant="outline" size="sm">View all</Button>
      </CardFooter>
    </Card>
  )
}

Variants

Default Card

The standard card with a 1px border, light shadow, and 12px border radius.
Team overview
Summary of your active team members.
12 members active this week.
<Card>
  <CardHeader>
    <CardTitle>Team overview</CardTitle>
    <CardDescription>Summary of your active team members.</CardDescription>
  </CardHeader>
  <CardContent>
    <p>12 members active this week.</p>
  </CardContent>
  <CardFooter>
    <Button variant="outline" size="sm">View all</Button>
  </CardFooter>
</Card>

Flat Card

No shadow — use inside panels or sections that already have a container.
Flat card
Simple content in a flat, no-shadow container.
<Card variant="flat">
  <CardContent>
    Simple content in a flat container.
  </CardContent>
</Card>

Hoverable (Clickable) Card

Adds a hover transition and cursor pointer — use for navigable cards.
Project Alpha
Due March 31
65% complete
<Card variant="hover" onClick={() => navigate("/project/1")}>
  <CardHeader>
    <CardTitle>Project Alpha</CardTitle>
    <CardDescription>Due March 31</CardDescription>
  </CardHeader>
  <CardContent>
    <Progress value={65} />
  </CardContent>
</Card>

Stat Card

Optimized layout for KPI metrics with trend indicators.
+12.5%
Total Revenue
$48,295
−3.1%
Active Users
3,842
<Card>
  <CardStat
    label="Total Revenue"
    value="$48,295"
    trend="positive"
    change={12.5}
    icon={<DollarSignIcon />}
  />
</Card>

With Media

Attach an image or visual header above the card content.
Project name
Description of the project goes here.
<Card>
  <div className="aspect-video w-full overflow-hidden rounded-t-xl">
    <img src="/thumbnail.jpg" alt="Project" className="w-full h-full object-cover" />
  </div>
  <CardHeader>
    <CardTitle>Project name</CardTitle>
  </CardHeader>
  <CardContent>Description here.</CardContent>
</Card>

API Reference

Card

variant
string
default:"default"
Visual style. Values: default · flat · hover
onClick
() => void
Makes the card interactive. Automatically applies hover cursor and focus ring.
className
string
Additional class names for the card container.

CardFooter

align
string
default:"start"
Footer content alignment. Values: start · end · between

CardStat

label
string
required
The metric label text (e.g. “Total Revenue”).
value
string | number
required
Primary metric value displayed prominently.
trend
string
Trend direction for color coding. Values: positive · negative · neutral
change
number
Percentage change value (e.g. 12.5 renders as +12.5%).
icon
ReactNode
Icon displayed in the stat card header area.

Accessibility

  • Hoverable cards rendered with onClick should include a focusable element or use role="button" with tabIndex={0} and keyboard handler
  • CardTitle renders as <h3> by default — adjust heading level with the as prop to maintain document heading hierarchy
  • Media images inside cards must have descriptive alt text
  • Avoid putting interactive elements inside a card that is itself clickable — this creates nested interactivity issues

Do’s & Don’ts

Do

  • Use CardStat for KPI displays — it provides consistent metric layout
  • Use variant="hover" only for cards that are genuinely navigable or clickable
  • Keep card content focused on a single topic or entity
  • Use CardFooter align="between" when you need both a label and an action button

Don't

  • Don’t nest a clickable card inside another clickable card
  • Don’t use Card as a modal replacement — use Modal or Sheet instead
  • Don’t use variant="hover" on non-interactive cards — it creates false affordance
  • Don’t overload a card with too many actions — limit to 1–2 per card