Experience System

Card

Bordered surface for grouping related content, metadata, and actions.

Installation

The components are exported from @by/experience-system. Add the package with your package manager:

pnpm add @by/experience-system

In this monorepo, depend on the workspace package (for example via workspace:* or your catalog) so imports resolve to packages/experience-system.

Composition

Use the following composition to build a Card:

Card
├── CardHeader
│   ├── CardTitle
│   ├── CardDescription (optional)
│   └── CardAction (optional)
├── CardContent (optional)
└── CardFooter (optional)

CardHeader uses a @container/card-header grid so CardAction aligns to the top trailing edge when present. CardTitle and CardDescription are plain div elements (not headings by default)—choose heading levels in the surrounding page if needed.

Usage

import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from '@by/experience-system';

Card and its parts are client components ('use client'). Use them inside a Client Component or a dynamic import when using the Next.js App Router.

<Card className="max-w-sm">
  <CardHeader>
    <CardTitle>Title</CardTitle>
    <CardDescription>Supporting text.</CardDescription>
  </CardHeader>
  <CardContent>Body content.</CardContent>
</Card>

Examples

Overview

Basic header and content.

Form layout

CardAction in the header for a secondary control, CardFooter for primary actions.

Elevation

Shadow utilities on Card for depth (shadow-sm through shadow-xl).

Interactive patterns

Link-wrapped card, selectable cards, and RadioGroup card options (focus rings on the interactive wrapper).

Clickable card (link)

Full card is a link: interactive cards have stronger outline than regular cards, use `border-neutral-alpha-6` and `border-neutral-alpha-8` for normal and hovered states respectively.

Selectable cards

Click a card to select it; selection uses a higher elevation than idle cards.
Selectable cards have stronger outline than regular cards, use `border-neutral-alpha-6` and `border-neutral-alpha-8` for normal and hovered states respectively.

Radio cards

Use RadioGroup with Radio at the start of each card; wrap the card in Label so the whole surface toggles the option. Only one card can be selected at a time.

Expandable card

CardExpandTrigger in CardAction toggles the card between collapsed and expanded states via the expanded / onExpandedChange props on Card.

Expanded content

CardExpandedContent renders only when the card is expanded. Use it for supplementary content — charts, detailed breakdowns, or any region that should stay hidden until the user expands the card.

API Reference

Subsection titles name the exports from @by/experience-system. These are layout div components (not Radix primitives).

Card

Data attributeValues
data-slotcard

Also accepts standard div attributes.

CardHeader

Data attributeValues
data-slotcard-header

Also accepts standard div attributes.

CardTitle

Data attributeValues
data-slotcard-title

Also accepts standard div attributes.

CardDescription

Data attributeValues
data-slotcard-description

Also accepts standard div attributes.

CardAction

Trailing header actions; participates in the header grid when data-slot="card-action" is present on this node.

Data attributeValues
data-slotcard-action

Also accepts standard div attributes.

CardContent

Data attributeValues
data-slotcard-content

Also accepts standard div attributes.

CardFooter

Data attributeValues
data-slotcard-footer

Also accepts standard div attributes.

Accessibility

Prefer a single primary interactive element per card (one a or button wrapping the card, or explicit buttons inside). If the whole card is clickable, put the focus ring on the wrapper and avoid nested tab stops. For radio-style cards, use RadioGroup + Radio with a Label wrapping the card so the control name matches the visible title. See MDN — Cards for generic container semantics and your product pattern library for card-specific guidance.

Source in the repo: packages/experience-system/src/components/Card/Card.tsx. Agent-oriented contracts: packages/experience-system/src/components/Card/Card.instructions.md.