Card

A composable card component for displaying content with flexible layout.

#OP-6894

Variants

Card takes a self-scoped variant (soft, surface, outline, ghost) and color (neutral, accent). These style the card's own chrome only; they never cascade into the controls inside it. neutral (default) tracks the app theme's neutral color; accent tints the chrome with the brand accent. Set an app-wide default with <Theme cardVariant cardColor>; a per-card prop overrides it.

color=neutral

soft

surface

outline

ghost

solid

color=accent

soft

surface

outline

ghost

solid

Usage

import {
  Card,
  CardHeader,
  CardIcon,
  CardTitle,
  CardDescription,
  CardContent,
  CardFooter,
  CardSkeleton,
} from '@epilot/spark-ui/card'
<Card>
  <CardHeader>
    <CardIcon>
      <ClockIcon />
    </CardIcon>
    <CardTitle>#OP-6894</CardTitle>
  </CardHeader>
</Card>

Wrapping content that has no header, title, description, or footer shape? Reach for Box instead. It's the same chrome, with none of Card's content slots.

Examples

With Icon and Description

#OP-6894

Pending approval

Order Summary

Review your order details

2x Items · Total: €487.00

Radius

none

md

2xl

full

Loading Skeleton

Interactive

Pass render with an <a href/> or <button/> to make the whole card the click target: it gains a hover tint, focus ring, and disabled styles. Don't nest other interactive controls inside an interactive card.

<Card color="accent" render={<a href="/meters" />} variant="soft">
  <CardIcon>
    <MaterialSymbol name="speed" />
  </CardIcon>
  <CardTitle>Submit meter reading</CardTitle>
  <CardDescription>Takes about a minute</CardDescription>
</Card>

API Reference

Components

  • Card - Root container; takes variant + color (see props below)
  • CardHeader - Header section with horizontal layout for icon and title
  • CardIcon - Slot for icon or avatar
  • CardTitle - Primary heading text
  • CardDescription - Secondary descriptive text
  • CardContent - Main content area
  • CardFooter - Footer section for actions
  • CardSkeleton - Loading placeholder with animated skeleton

Card props

PropTypeDefaultDescription
variant'soft' | 'surface' | 'outline' | 'ghost'knob/softContainer chrome, scoped to the card (never cascades into child controls). Unset follows the app-level data-card-variant.
color'neutral' | 'accent''neutral'Chrome palette. neutral tracks the app theme's neutral color; accent tints the chrome with the brand accent.
radius'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | 'full''2xl'Corner radius for this card instance. Each step maps to the matching Tailwind rounded-* utility, so it still scales with the page-wide Roundness knob.
renderReactElementBase UI polymorphism. Pass <a href/> or <button/> to make the card interactive (hover tint, focus ring, disabled styles).

Set app-wide defaults with the Theme provider's cardVariant / cardColor props; a per-card prop overrides them. variant/color style only the card's own chrome: a Button or field inside the card keeps its own styling.

On this page