Skip to content
Cloaked Design SystemCards

Card

The generic surface primitive, composed from typed slots for regions, text, and summary figures, and optionally pressable.

Implementation preview
COMPLETE STORYBOOK REFERENCE

Every example. In one place.

Explore every named example, including states, compositions, and theme variants.

13 stories
SELECTED EXAMPLE

Playground

Open controls
Playground selectedOpen canvas
Example sourcepackages/design-system/src/components/cards/Card/Card.stories.tsxExport Playground

Implementation preview Local Storybook build 0.2.0-preview.1. Source specification status does not approve this runtime.

Stories + source JSON ↗

Local specification source status: preview. Implementation preview pending sign-off.

The generic surface primitive, composed from typed slots for regions, text, and summary figures, and optionally pressable.

Design-owned component contract ↗Version 0.2.0-preview.1 · Implementation preview pending sign-off
Implementation API 10 entry points · source-derived preview

Read the actual callable API and preserve its composition constraints. Each union branch is a complete alternative; props marked forbidden cannot be supplied.

import { Card } from '@cloakedinc/design-system';
CardCardProps

packages/design-system/src/components/cards/Card/CardRoot/CardRoot.tsx:11

PropTypePresenceNotes
surfaceCardSurface | undefinedOptionalSurface fill. Defaults to `default`; `highlight` swaps in the banner container color.Source default: 'default'
radiusCardRadius | undefinedOptionalCorner radius for the card surface. Defaults to `lg`.Source default: 'lg'
layoutCardLayout | undefinedOptionalDirection slots flow. Defaults to `stack`; `split` sits them side by side with an 8px gap.Source default: 'stack'
paddingCardPadding | undefinedOptionalPadding on the surface itself. Defaults to `none` because the slots pad themselves — `default` adds 16px that stacks on top of any padded slot.Source default: 'none'
childrenReact.ReactNodeRequired
classNamestring | undefinedOptional
styleReact.CSSProperties | undefinedOptional
onPress(() => void) | undefinedOptionalProviding this renders the root as a pressable `<button>` rather than a `<div>`.
ariaLabelstring | undefinedOptionalAccessible label for pressable cards when visible copy is not sufficient.
hapticHapticFeedback | undefinedOptionalHaptic feedback for successful presses. Defaults to `true` (`light`).Source default: true
testIdstring | undefinedOptional`data-testid` on the root element.
silhouetteboolean | undefinedOptionalMarks the card as a silhouette measurement target. The attribute is presence-only, so `false` is normalized away rather than rendered: `data-silhouette="false"` would still match the `[data-silhouette]` query and opt the card in.
Card.HeaderCardZoneProps

packages/design-system/src/components/cards/Card/CardSlots/CardSlots.tsx:12

PropTypePresenceNotes
childrenReact.ReactNodeRequired
classNamestring | undefinedOptional
styleReact.CSSProperties | undefinedOptional
layoutCardSlotLayout | undefinedOptionalFlow direction inside the slot. Defaults to `stack`.
paddingCardSlotPadding | undefinedOptionalDefaults to `default` (16px). `compact` and `spacious` change only the vertical padding.
gapCardSlotGap | undefinedOptionalSpace between the slot's own children. Defaults to `sm` (8px).
alignCardAlign | undefinedOptionalCross-axis alignment. Unset applies no class and leaves the flex default.
justifyCardJustify | undefinedOptionalMain-axis distribution; `between` maps to `space-between`. Unset leaves the flex default.
divider"top" | "bottom" | undefinedOptionalDraws a `--cds-divider` rule on that edge of the slot.
growboolean | undefinedOptionalLets the slot absorb leftover space. `Card.Body` already does this without the prop.
Card.BodyCardZoneProps

packages/design-system/src/components/cards/Card/CardSlots/CardSlots.tsx:47

PropTypePresenceNotes
childrenReact.ReactNodeRequired
classNamestring | undefinedOptional
styleReact.CSSProperties | undefinedOptional
layoutCardSlotLayout | undefinedOptionalFlow direction inside the slot. Defaults to `stack`.
paddingCardSlotPadding | undefinedOptionalDefaults to `default` (16px). `compact` and `spacious` change only the vertical padding.
gapCardSlotGap | undefinedOptionalSpace between the slot's own children. Defaults to `sm` (8px).
alignCardAlign | undefinedOptionalCross-axis alignment. Unset applies no class and leaves the flex default.
justifyCardJustify | undefinedOptionalMain-axis distribution; `between` maps to `space-between`. Unset leaves the flex default.
divider"top" | "bottom" | undefinedOptionalDraws a `--cds-divider` rule on that edge of the slot.
growboolean | undefinedOptionalLets the slot absorb leftover space. `Card.Body` already does this without the prop.
Card.FooterCardFooterProps

packages/design-system/src/components/cards/Card/CardSlots/CardSlots.tsx:82

PropTypePresenceNotes
onPress(() => void) | undefinedOptionalProviding this renders the footer as a pressable `<button>` rather than a `<div>`.
ariaLabelstring | undefinedOptionalAccessible label for the pressable footer when visible copy is not sufficient.
hapticHapticFeedback | undefinedOptionalHaptic feedback for successful presses. Defaults to `true` (`light`).Source default: true
testIdstring | undefinedOptional`data-testid` on the footer element.
childrenReact.ReactNodeRequired
classNamestring | undefinedOptional
styleReact.CSSProperties | undefinedOptional
layoutCardSlotLayout | undefinedOptionalFlow direction inside the slot. Defaults to `stack`.
paddingCardSlotPadding | undefinedOptionalDefaults to `default` (16px). `compact` and `spacious` change only the vertical padding.
gapCardSlotGap | undefinedOptionalSpace between the slot's own children. Defaults to `sm` (8px).
alignCardAlign | undefinedOptionalCross-axis alignment. Unset applies no class and leaves the flex default.Source default: 'center'
justifyCardJustify | undefinedOptionalMain-axis distribution; `between` maps to `space-between`. Unset leaves the flex default.Source default: 'center'
divider"top" | "bottom" | undefinedOptionalDraws a `--cds-divider` rule on that edge of the slot.
growboolean | undefinedOptionalLets the slot absorb leftover space. `Card.Body` already does this without the prop.
Card.StackCardStackProps

packages/design-system/src/components/cards/Card/CardSlots/CardSlots.tsx:132

PropTypePresenceNotes
as"div" | "span" | undefinedOptionalElement to render. Defaults to `div`; use `span` where only phrasing content is allowed.Source default: 'div'
childrenReact.ReactNodeRequired
classNamestring | undefinedOptional
styleReact.CSSProperties | undefinedOptional
layoutCardSlotLayout | undefinedOptionalFlow direction inside the slot. Defaults to `stack`.
paddingCardSlotPadding | undefinedOptionalDefaults to `default` (16px). `compact` and `spacious` change only the vertical padding.
gapCardSlotGap | undefinedOptionalSpace between the slot's own children. Defaults to `sm` (8px).
alignCardAlign | undefinedOptionalCross-axis alignment. Unset applies no class and leaves the flex default.
justifyCardJustify | undefinedOptionalMain-axis distribution; `between` maps to `space-between`. Unset leaves the flex default.
divider"top" | "bottom" | undefinedOptionalDraws a `--cds-divider` rule on that edge of the slot.
growboolean | undefinedOptionalLets the slot absorb leftover space. `Card.Body` already does this without the prop.
Card.TitleCardTextSlotProps

packages/design-system/src/components/cards/Card/CardTextSlots/CardTextSlots.tsx:10

PropTypePresenceNotes
childrenReact.ReactNodeRequired
Card.DescriptionCardTextSlotProps

packages/design-system/src/components/cards/Card/CardTextSlots/CardTextSlots.tsx:21

PropTypePresenceNotes
childrenReact.ReactNodeRequired
Card.MetricCardMetricProps

packages/design-system/src/components/cards/Card/CardMetric/CardMetric.tsx:11

PropTypePresenceNotes
valueReact.ReactNodeRequiredThe figure, rendered at `display-2` in the card's text color.
unitReact.ReactNodeOptionalSuffix beside the value, at body size and bottom-aligned. Nothing renders when omitted.
Card.DeltaCardDeltaProps

packages/design-system/src/components/cards/Card/CardDelta/CardDelta.tsx:20

PropTypePresenceNotes
valueReact.ReactNodeRequiredChange text, rendered as-is — include any sign or unit you want shown.
direction"up" | "down" | undefinedOptionalWhich way the figure moved. Sets the marker, and the tone unless `tone` overrides it. Defaults to `up` and is never inferred from `value`.Source default: 'up'
toneCardDeltaTone | undefinedOptionalOverrides the tone `direction` implies, for a figure whose sentiment runs against its arrow — spam calls falling is `down` and `success`. Without it, `up` is success and `down` is danger.
markerCardDeltaMarker | undefinedOptionalMarker shape. Defaults to `caret`.Source default: 'caret'
classNamestring | undefinedOptional
ariaLabelstring | undefinedOptionalAccessible name for the pill, replacing its visible text. Pass the unabbreviated figure when `value` is compacted, so `1.8k this week` is not what a screen reader has to interpret.
testIdstring | undefinedOptional`data-testid` on the pill wrapper; the caret and the text carry none.
Card.StatusIndicatorStatusIndicatorProps

packages/design-system/src/components/status/StatusIndicator/StatusIndicator.tsx:25

PropTypePresenceNotes
childrenReact.ReactNodeRequired
tone"neutral" | "info" | "success" | "warning" | "danger" | undefinedOptionalSemantic status color for the dot; maps to the `--cds-status-*` tokens. Defaults to `neutral`.Source default: 'neutral'
classNamestring | undefinedOptional
testIdstring | undefinedOptionalOptional test selector.

Only explicit destructured parameter initializers are extracted. Other runtime defaults remain in implementation source.

Overview

The generic surface primitive. Compose it from typed slots — Card.Header / Card.Body / Card.Footer, Card.Title / Card.Description, Card.Metric / Card.Delta — rather than raw markup. surface encodes emphasis. For a selectable option, use SelectionCard.

Use when

surface is the semantic decision: a plain container versus a tinted prompt.

Slots own their own padding, so the root usually keeps padding="none". layout="split" lays the top-level slots in a row instead of a column; it is available but not currently used in app code — stack is the norm.

Composition

Header (title + description) over a body list — the canonical slot arrangement.

The summary-card pattern pairs Card.Metric + Card.Delta in a header with a body stat list and a footer link.

Pressable

Pass onPress to turn the whole card into a tap target, or Card.Footer onPress for a pressable footer only.

Usage by variant

ChoiceUse whenAvoid when
Surface: defaultThe standard container for grouping content, metrics, and lists. Nearly every card in the app is default.A moment you want to actively steer the user toward — that earns highlight.
Surface: highlightA tinted surface that steers users toward a short next step — a setup prompt or inline CTA (ProfileSetupCard).Ordinary content. Rare by design — at most one per screen so the highlight keeps its pull.

Component specification

$schema../../../specs/component-spec.schema.json
Parts
Id
root
Label
Root
Description
Surface shell carrying the surface, radius, layout, and padding.
Required
true
Id
header
Label
Card.Header
Description
Top region slot, usually title and status.
Id
body
Label
Card.Body
Description
Main region slot for content and lists.
Id
footer
Label
Card.Footer
Description
Bottom region slot, optionally pressable.
Id
stack
Label
Card.Stack
Description
Ad-hoc grouping slot within a region.
Id
title
Label
Card.Title
Description
Region heading; wraps to as many lines as the copy needs.
Id
description
Label
Card.Description
Description
Supporting region text.
Id
metric
Label
Card.Metric
Description
Large metric value with optional unit.
Id
delta
Label
Card.Delta
Description
Change label: a caret or trend marker with the movement, toned success, warning, danger, or neutral. Tone follows the direction unless the figure's sentiment runs against its arrow.
Allowed Design Choices
Variants
Container
Label
Container
Description
The single generic surface; content comes from slots.
Sizes
Surfaces
Default
Label
Default
Description
Raised surface background.
Highlight
Label
Highlight
Description
Tinted background for prompts and CTAs.
Radii
Xs
Label
Extra small
Sm
Label
Small
Md
Label
Medium
Lg
Label
Large
Description
The default corner radius.
Xl
Label
Extra large
Paddings
None
Label
None
Description
No outer padding; slots own their padding.
Default
Label
Default
Description
16-unit outer padding on the shell.
Layouts
Stack
Label
Stack
Description
Top-level slots flow in a column.
Split
Label
Split
Description
Top-level slots flow in a row.
Variants
Id
container
Label
Container
Description
Generic slotted surface.
Platforms
  • ios
  • android
  • web
SizesNone specified
Measurements
Id
surface-radius
Label
Default corner radius
Kind
exact
Token
--cds-radius-lg
Value
20
Unit
px
Applies To
  • root
Id
split-gap
Label
Split layout gap
Kind
exact
Token
--cds-space-8
Value
8
Unit
px
Applies To
  • root
Id
default-padding
Label
Default outer padding
Kind
exact
Token
--cds-space-16
Value
16
Unit
px
Applies To
  • root
Layout
Alignment
Slots stack in a column by default, or lay out in a row under the split layout.
Flow
The shell hosts typed slots; slots own their own padding, so the shell usually keeps padding none.
Notes
  • Use SelectionCard when the card is a selectable option rather than a container.
Typography And Color
Typography
Label
Title
Description
Card.Title uses the body ramp emphasis.
Token
--cds-type-body-size
Colors
Label
Default surface
Description
The default surface uses the raised background.
Token
--cds-bg-surface
Label
Highlight surface
Description
The highlight surface uses the banner container tint.
Token
--cds-banner-container
Label
Text
Description
Card content uses primary text.
Token
--cds-text-primary
Label
Delta label
Description
Card.Delta's marker and label mix 60% of the tone's solid colour with 40% primary text for readable contrast on the unchanged subtle fill. Success is shown; danger, warning and neutral follow the same calculation. This local adaptation remains preview pending human sign-off.
Token
--cds-status-success-solid
Label
Delta fill
Description
The delta pill sits on the matching subtle tint for its tone.
Token
--cds-status-success-subtle
States
Id
default
Label
Default
Description
Static container surface.
Id
highlight
Label
Highlight
Description
Tinted prompt surface.
Id
pressable
Label
Pressable
Description
onPress makes the whole card a tap target with tap feedback.
Behavior
Label
Slot composition
Description
Compose regions and figures from typed slots rather than raw markup.
Label
Pressable
Description
onPress makes the card a button; a pressable footer targets just the footer. The two are mutually exclusive — a pressable footer inside a pressable card would nest interactive controls.
Label
Silhouette measurement
Description
silhouette marks the card as a measurement target so a page can record its settled geometry for a loading placeholder. Presence-only and non-visual: it renders a data attribute and changes nothing about the card itself.
Accessibility
Label
Pressable name
Description
Give a pressable card an accessible label when visible copy is insufficient.
Label
Structure
Description
Slots keep a predictable region order for assistive tech.
Content Adaptation
Label
Region padding
Description
Slots carry their own padding tokens so the shell stays padding-free.
Label
Split content
Description
The split layout pairs a metric with supporting content in a row.
Motion Haptics
Motion
Label
Press feedback
Description
Pressable cards apply tap feedback on press.
Haptics
Label
Press haptic
Description
Pressable cards request a light haptic on a successful press.
Platform DifferencesNone specified
Implementation preview

This design-owned implementation is ready to try and review. It does not establish product approval. Imported specifications retain their original review status.

Inspect version 0.2.0-preview.1