Card
Free · MITEight surfaces (elevated, glass, gradient border, neo, inset…) with shadow, padding, radius and accent stripes, plus hover layers (lift, 3D tilt, pointer spotlight, glow, scale) and a looping border beam.
Installation
$ npx shadcn@latest add https://goodui.dev/r/card.jsonThe file lands in components/goodui/card.tsx and is yours to edit. With the @goodui registry added, npx shadcn@latest add @goodui/card works too.
Usage
import { CalendarPlus } from "lucide-react"
import { Card, CardFooter } from "@/components/goodui/card"
import { Badge } from "@/components/goodui/badge"
import { Button } from "@/components/goodui/button"
export function NextBooking() {
return (
<Card
className="max-w-sm"
accent="left"
tone="success"
icon={<CalendarPlus />}
title="Balayage with Maya"
description="Tomorrow, 09:30 · Chair 2"
action={<Badge tone="success">Paid</Badge>}
footer={
<>
<Button size="sm">Check in</Button>
<Button size="sm" variant="ghost" tone="neutral">
Reschedule
</Button>
</>
}
>
2 hours · $180 deposit received. Client asked for a patch test.
</Card>
)
}When to use
- Grouping one thing on a dashboard or settings page: a plan, a booking, a client, a report.
- Pricing and feature grids where one card should stand out (accent, gradient-border, shadow="glow").
- Clickable tiles that need hover feedback (lift, tilt, spotlight) without another library.
- Empty states and drop zones: variant="dashed".
- A single KPI with a delta and sparkline: use stat-card, which is built on the same look.
- Content that opens into a bigger view: use expandable-card or morphing-dialog.
- Splitting sections of one long form: a separator keeps the page lighter than a stack of cards.
| If you need | Use |
|---|---|
| Default dashboard surface | variant="elevated" (default) or "outline" for flat UIs |
| Grouped settings inside a page that is already a card | variant="inset" or "soft" |
| The recommended pricing plan | variant="gradient-border" or accent="top" with shadow="glow" |
| Status or category color on a list of cards | accent="left" with a tone |
| Clickable tiles in a grid | animation="lift" (calm) or "spotlight" (pointer-following border light) |
| Hero or showcase card on a marketing page | animation="tilt" or "border-beam" |
| Over photos or gradients | variant="glass" |
| Empty state or upload area | variant="dashed" |
Examples
Featured pricing plan
<Card variant="gradient-border" shadow="glow" animation="lift" title="Studio" description="For teams up to 10 stylists">
<p className="text-3xl font-semibold">$29<span className="text-sm text-muted-foreground">/month</span></p>
<CardFooter separated>
<Button className="w-full">Start free trial</Button>
</CardFooter>
</Card>Media card with parts
<Card padding="sm" animation="spotlight" tone="info">
<CardMedia>
<img src="/reports/october.png" alt="Revenue chart for October" />
</CardMedia>
<CardHeader>
<CardTitle>October revenue</CardTitle>
<CardDescription>Up 12% on September</CardDescription>
</CardHeader>
</Card>API reference
Card
| Prop | Type | Default |
|---|---|---|
| variant Surface: elevated (default), outline, soft tint, frosted glass, gradient border, neo-brutalist, inset well or dashed. | "elevated" | "outline" | "soft" | "glass" | "gradient-border" | "neo" | "inset" | "dashed" | "elevated" |
| tone Color for the accent stripe, glow, soft tint, gradient border, hover light and icon tile. | "primary" | "neutral" | "success" | "warning" | "danger" | "info" | "primary" |
| shadow Drop shadow; glow uses the tone color. Ignored by neo, which has its own offset shadow. | "none" | "sm" | "md" | "lg" | "xl" | "glow" | "none" |
| animation Motion layer. lift, scale and glow react to hover; tilt and spotlight follow the pointer; border-beam is not a hover effect: it loops a light around the border continuously (off with reduced motion). | "none" | "lift" | "tilt" | "spotlight" | "glow" | "border-beam" | "scale" | "none" |
| padding Inner spacing and gap between parts; CardMedia and separated footers bleed by this amount. | "none" | "sm" | "md" | "lg" | "md" |
| radius | "none" | "sm" | "md" | "lg" | "xl" | "2xl" | "lg" |
| accent A tone-colored stripe on the top or left edge. | "none" | "top" | "left" | "none" |
| fullWidth false shrinks the card to its content. | boolean | true |
| title Shorthand: renders a CardHeader with this title. | React.ReactNode | — |
| description Shorthand: muted line under the title. | React.ReactNode | — |
| icon Shorthand: icon in a tinted tile beside the title. | React.ReactNode | — |
| action Shorthand: element on the right of the header (a badge, a menu button). | React.ReactNode | — |
| footer Shorthand: renders a CardFooter. | React.ReactNode | — |
Also accepts every <div> attribute.
CardHeader
| Prop | Type | Default |
|---|---|---|
| icon Icon shown in a tinted tile on the left. | React.ReactNode | — |
| action Element on the right (badge, menu, button). | React.ReactNode | — |
Also accepts every <div> attribute.
CardTitle
Also accepts every <h3> attribute.
CardDescription
Also accepts every <p> attribute.
CardContent
Also accepts every <div> attribute.
CardFooter
| Prop | Type | Default |
|---|---|---|
| separated Full-bleed top border above the footer. | boolean | — |
Also accepts every <div> attribute.
CardMedia
Also accepts every <div> attribute.
Accessibility
- Renders a plain <div>; the title shorthand and CardTitle render an <h3>. If your heading order needs another level, put your own heading inside CardHeader instead of CardTitle.
- The header icon tile is aria-hidden; put the meaning in the title.
- A focus ring is styled for keyboard focus, but the card is not focusable by default. If the whole card is clickable, put a real <a> or <button> inside rather than adding onClick to the div.
Motion
- lift: rises 4px with a deeper shadow in 250 ms (neo cards shift up-left into a bigger offset shadow). scale: grows to 1.02 in 250 ms. glow: a tone-colored ring and bloom fade in over 300 ms.
- tilt: rotates up to 4° on X and 5° on Y toward the pointer with a soft glare, and eases back in 500 ms on leave.
- spotlight: a tone-colored light and a brighter border follow the pointer and fade in over 300 ms.
- border-beam: a light runs around the border every 4 s, all the time, not only on hover.
- Touch pointers do not trigger tilt or spotlight.
- Reduced motion: transforms and transitions are off, so lift, scale and tilt do not move and border-beam is hidden. Spotlight and glow still appear, without fading.
- tilt and spotlight write CSS variables on pointermove (no React re-render). border-beam animates a registered @property angle, so keep it to one or two cards per screen.
Notes for AI
Coding agents read these rules through MCP and llms.txt, or paste this page with Copy page.
- Layers are independent props: variant, tone, shadow, animation, padding, radius, accent. tone colors accent, glow, soft tint, gradient-border, spotlight, beam and the icon tile.
- For the common layout use the shorthand props (title, description, icon, action, footer). Use the parts (CardHeader, CardTitle, CardDescription, CardContent, CardFooter, CardMedia) for custom layouts; do not mix the shorthand header with a second CardHeader.
- A string child is wrapped in CardContent only when a header is present; other children render as they are.
- CardMedia and CardFooter separated go full-bleed using the card padding, so they need padding other than "none".
- shadow is ignored on variant="neo", which has its own offset shadow. fullWidth={false} shrinks the card to its content.
FAQ
Is it compatible with shadcn's Card?
The parts have the same names (CardHeader, CardTitle, CardDescription, CardContent, CardFooter) and data-slot attributes, plus CardMedia and the layer props. CardAction is replaced by the action prop on Card or CardHeader.
Why does my tilt card not move on a phone?
Tilt and spotlight ignore touch pointers on purpose, so scrolling a list of cards does not wobble them.
Related
KPI card with seven variants, tones, shadows and sizes: count-up or rolling NumberFlow values, auto-toned delta badges (invertible for no-show rates), line, area or bar sparklines that draw in, icons, footers and a skeleton state.
A soft spotlight and a lit border follow the pointer across a card; in a group, neighboring cards' borders light up too.
Tilts toward the pointer on a spring with a moving glare, a shifting shadow and layers that float at their own depth.
Wraps any card or input and runs a light beam around its border, matching the element's corner radius automatically.