Build / Molecules
Card
The surface every MeetCard experience is built on.
Compose with CardHeader, CardBody, and CardFooter. Those sections
bleed their dividers to the card's edge automatically, so padding stays a
single decision made once on Card.
import { Card } from '@meetcard/deck'Example
<Card as="article" interactive> <CardHeader divided> <Heading level={3}>Ada Lovelace</Heading> <Badge tone="success">Connected</Badge> </CardHeader> <CardBody><Text tone="muted">Analytical Engine, London</Text></CardBody> </Card>Stories
Source
const Default = () => <Card style={{ maxWidth: 360 }}>
<Text>A card is the base surface for every MeetCard experience.</Text>
</Card>;The standard composition. Note that padding is set once on Card — the
section dividers bleed to the edge on their own.
Source
const Composed = () => <Card style={{ maxWidth: 360 }}>
<CardHeader divided>
<Heading level={3} size="sm">Ada Lovelace
</Heading>
<Badge tone="success" dot>Connected
</Badge>
</CardHeader>
<CardBody>
<Text size="sm" tone="muted">Head of Partnerships · MeetCard
</Text>
</CardBody>
<CardFooter divided>
<Button size="sm">Share card</Button>
<Button size="sm" variant="ghost">Dismiss
</Button>
</CardFooter>
</Card>;Every surface. brand is the one solid fill, and it carries deck-solid-
surface so content inside stays legible.
Source
const Surfaces = () => (
<Stack direction="row" gap={16} wrap>
{(['elevated', 'default', 'subtle', 'brand'] as const).map((surface) => (
<Card key={surface} surface={surface} style={{ width: 160 }}>
<Text size="sm">{surface}</Text>
</Card>
))}
</Stack>
);Every elevation. sm is for cards on the page; md and up are for things
that float over it.
Source
const Elevations = () => (
<Stack direction="row" gap={24} wrap>
{(['xs', 'sm', 'md', 'lg', 'xl'] as const).map((elevation) => (
<Card key={elevation} elevation={elevation} style={{ width: 120 }}>
<Text size="sm">{elevation}</Text>
</Card>
))}
</Stack>
);interactive adds the tactile lift. It is visual only — the card still
needs a real focusable child, which is why the button below is present.
Source
const Interactive = () => <Card interactive style={{ maxWidth: 360 }}>
<CardHeader>
<Heading level={3} size="sm">Tap target
</Heading>
</CardHeader>
<CardBody>
<Text size="sm" tone="muted">Hover to see the lift; tab to see focus surface the whole card.
</Text>
</CardBody>
<CardFooter>
<Button size="sm" variant="secondary">Open
</Button>
</CardFooter>
</Card>;Props
| Prop | Type | Default | Description |
|---|---|---|---|
as | 'div' | 'article' | 'section' | 'li' | 'div' | — |
elevation | Shadow | 'none' | 'sm' | Elevation step. Figma maps sm to cards; md+ is for floating UI. |
interactive | boolean | false | Adds hover/press affordance. Visual only — pair it with a real focusable child (a link or button) so the card is reachable by keyboard. |
padding | (typeof space)[number] | 20 | Inner padding as a Deck space step. Defaults to 20. |
surface | 'default' | 'subtle' | 'elevated' | 'brand' | 'elevated' | — |
Also accepts everything from HTMLAttributes, so id, data-* and event handlers pass straight through.