Card
A flexible container component used to group related content, metrics, and actions into structured surfaces. Supports compound sections (Header, Body, Footer, Divider), hover elevation, and interactive keyboard clickability.
tsx
import { Card } from '@nofinite/nui';Interactive Preview
Loading preview...
Anatomy & Compound Components
Card is designed to be composed semantically using modular compound components:
tsx
<Card hover>
<Card.Header>
<h3 className="text-base font-semibold">Card Title</h3>
</Card.Header>
<Card.Body>
<p className="text-sm text-muted">Card body content.</p>
</Card.Body>
<Card.Divider />
<Card.Footer>
<Button size="sm" variant="primary">Action</Button>
</Card.Footer>
</Card>| Component | Description |
|---|---|
Card | The root container applying the card superclass, border, and elevation. |
Card.Header | Top header area for titles, icon badges, and status chips. |
Card.Body | Main content container with responsive padding. |
Card.Divider | Semantic horizontal rule between card sections. |
Card.Footer | Bottom action bar with flexible alignment for action triggers. |
Usage Examples
1. Dashboard Metric Card
Combine Card with Badge and Button for dashboard views:
tsx
import React from 'react';
import { Card, Badge, Button } from '@nofinite/nui';
export default function AnalyticsCard() {
return (
<Card hover className="w-full max-w-sm">
<Card.Header className="flex items-center justify-between">
<div>
<span className="text-xs font-semibold text-muted uppercase tracking-wider">Total Revenue</span>
<h3 className="text-2xl font-bold text-default mt-1">$45,231.89</h3>
</div>
<Badge variant="success">+20.1%</Badge>
</Card.Header>
<Card.Body>
<p className="text-sm text-muted">
Monthly recurring revenue grew by $8,120 compared to the previous 30-day billing cycle.
</p>
</Card.Body>
<Card.Footer className="flex justify-end gap-2">
<Button size="sm" variant="outline">Reports</Button>
<Button size="sm" variant="primary">View Analytics</Button>
</Card.Footer>
</Card>
);
}2. Interactive & Clickable Card
Add clickable to transform the entire card into an accessible, focusable action trigger:
tsx
import React from 'react';
import { Card } from '@nofinite/nui';
export default function SelectablePlanCard() {
return (
<Card
clickable
onClick={() => alert('Plan selected!')}
className="w-full max-w-sm"
>
<Card.Header>
<h4 className="text-base font-bold text-default">Pro Plan</h4>
<p className="text-xs text-muted">For fast-growing product teams</p>
</Card.Header>
<Card.Body>
<div className="text-2xl font-extrabold text-default mb-2">$49<span className="text-xs font-normal text-muted">/mo</span></div>
<p className="text-sm text-muted">Includes unlimited projects, advanced telemetry, and priority support.</p>
</Card.Body>
</Card>
);
}Keyboard Interaction (for Clickable Cards)
| Key | Behavior |
|---|---|
| Tab | Moves keyboard focus to the clickable card surface. |
| Enter | Activates the card's onClick action handler. |
| Space | Activates the card's onClick action handler. |
Accessibility (WAI-ARIA)
- Interactive Semantics: When
clickableis enabled, the card receivesrole="button",tabIndex={0}, and active scaling feedback. - Keyboard Handling: Automatically handles Enter and Space key events, matching native button accessibility.
- Focus Rings: Renders native focus-visible rings using NUICSS
--border-focusdesign tokens. - Polymorphism: Supports
asChildto delegate rendering to Next.js<Link>or custom navigation wrappers.
Design Tokens & NUICSS Superclasses
| Superclass / Token | Type | Usage |
|---|---|---|
card | Superclass | Base container surface with rounded corners and border. |
bg-surface | Token | Background surface (--bg-surface). |
border-default | Token | Structural border (--border-default). |
hover:shadow-md | Utility | Elevated shadow applied when hover is true. |
text-default | Token | Primary content text (--fg-default). |
text-muted | Token | Secondary helper text (--fg-muted). |
Best Practices
Do
- Use
hoverfor cards that contain links or primary CTAs to indicate interactivity. - Combine
Card.Header,Card.Body, andCard.Footerfor clear visual hierarchy. - Use
clickablewhen the entire card surface is an action target.
Don't
- Do not place nested interactive buttons inside a
clickablecard (nesting interactive controls violates HTML5 standards). - Avoid overcrowding card footers with more than two primary action buttons.
API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
clickable | boolean | false | If true, makes the card interactive via mouse and keyboard (Enter/Space) |
hover | boolean | false | If true, adds a shadow elevation effect on hover |
asChild | boolean | false | If true, delegates rendering to child element using Slot |