AI
NUI logov3.1.0

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>
ComponentDescription
CardThe root container applying the card superclass, border, and elevation.
Card.HeaderTop header area for titles, icon badges, and status chips.
Card.BodyMain content container with responsive padding.
Card.DividerSemantic horizontal rule between card sections.
Card.FooterBottom 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)

KeyBehavior
TabMoves keyboard focus to the clickable card surface.
EnterActivates the card's onClick action handler.
SpaceActivates the card's onClick action handler.

Accessibility (WAI-ARIA)

  • Interactive Semantics: When clickable is enabled, the card receives role="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-focus design tokens.
  • Polymorphism: Supports asChild to delegate rendering to Next.js <Link> or custom navigation wrappers.

Design Tokens & NUICSS Superclasses

Superclass / TokenTypeUsage
cardSuperclassBase container surface with rounded corners and border.
bg-surfaceTokenBackground surface (--bg-surface).
border-defaultTokenStructural border (--border-default).
hover:shadow-mdUtilityElevated shadow applied when hover is true.
text-defaultTokenPrimary content text (--fg-default).
text-mutedTokenSecondary helper text (--fg-muted).

Best Practices

Do

  • Use hover for cards that contain links or primary CTAs to indicate interactivity.
  • Combine Card.Header, Card.Body, and Card.Footer for clear visual hierarchy.
  • Use clickable when the entire card surface is an action target.

Don't

  • Do not place nested interactive buttons inside a clickable card (nesting interactive controls violates HTML5 standards).
  • Avoid overcrowding card footers with more than two primary action buttons.

API Reference

PropTypeDefaultDescription
clickablebooleanfalseIf true, makes the card interactive via mouse and keyboard (Enter/Space)
hoverbooleanfalseIf true, adds a shadow elevation effect on hover
asChildbooleanfalseIf true, delegates rendering to child element using Slot