A versatile card component for grouping related content. Card uses the Panel core component as its surface layer, supporting the same theming system — feedback colors, background styles, border, and radius control — while adding a structured layout with optional header (heading, subheading, leading, trailing), a content area, and an optional footer.
Card with surface.soft background
Content area for the surface.soft background variant.
Card with surface.step.1 background
Content area for the surface.step.1 background variant.
Card with surface.step.2 background
Content area for the surface.step.2 background variant.
Card with surface.step.3 background
Content area for the surface.step.3 background variant.
Card with surface.deep background
Content area for the surface.deep background variant.
Card with transparent background
Content area for the transparent background variant.
---
import Card from "../Card.astro";
import { stack } from "@pindoba/styled-system/patterns";
import { css } from "@pindoba/styled-system/css";
const backgrounds = [
"surface.soft",
"surface.step.1",
"surface.step.2",
"surface.step.3",
"surface.deep",
"transparent",
] as const;
---
<div class={stack({ gap: "md", direction: "column", width: "100%" })}>
{
backgrounds.map((bg) => (
<Card
background={bg}
header={{
heading: bg,
subheading: `Card with ${bg} background`,
}}
>
<p class={css({ margin: "0" })}>
Content area for the <strong>{bg}</strong> background variant.
</p>
</Card>
))
}
</div>Cards support semantic feedback colors. The heading, subheading, border, and background all follow the selected color palette.
Card with neutral feedback
Heading and subheading colors follow the neutral palette.
Card with primary feedback
Heading and subheading colors follow the primary palette.
Card with success feedback
Heading and subheading colors follow the success palette.
Card with warning feedback
Heading and subheading colors follow the warning palette.
Card with danger feedback
Heading and subheading colors follow the danger palette.
---
import Card from "../Card.astro";
import { stack } from "@pindoba/styled-system/patterns";
import { css } from "@pindoba/styled-system/css";
const feedbacks = [
"neutral",
"primary",
"success",
"warning",
"danger",
] as const;
---
<div class={stack({ gap: "md", direction: "column", width: "100%" })}>
{
feedbacks.map((feedback) => (
<Card
feedback={feedback}
border="default"
header={{
heading: feedback,
subheading: `Card with ${feedback} feedback`,
}}
>
<p class={css({ margin: "0" })}>
Heading and subheading colors follow the <strong>{feedback}</strong>{" "}
palette.
</p>
</Card>
))
}
</div>The size prop controls the padding of the header, content, and footer sections, as well as the heading font size.
Compact padding and font sizes
Small card body content.
Default padding and font sizes
Medium card body content.
Generous padding and font sizes
Large card body content.
---
import Card from "../Card.astro";
import { stack } from "@pindoba/styled-system/patterns";
import { css } from "@pindoba/styled-system/css";
---
<div class={stack({ gap: "lg", direction: "column", width: "100%" })}>
<div>
<h3>Small</h3>
<Card
size="sm"
header={{
heading: "Small Card",
subheading: "Compact padding and font sizes",
}}
footer={{ leading: "Footer", trailing: "Action" }}
>
<p class={css({ margin: "0" })}>Small card body content.</p>
</Card>
</div>
<div>
<h3>Medium (default)</h3>
<Card
size="md"
header={{
heading: "Medium Card",
subheading: "Default padding and font sizes",
}}
footer={{ leading: "Footer", trailing: "Action" }}
>
<p class={css({ margin: "0" })}>Medium card body content.</p>
</Card>
</div>
<div>
<h3>Large</h3>
<Card
size="lg"
header={{
heading: "Large Card",
subheading: "Generous padding and font sizes",
}}
footer={{ leading: "Footer", trailing: "Action" }}
>
<p class={css({ margin: "0" })}>Large card body content.</p>
</Card>
</div>
</div>The card’s header and footer slots accept rich content. Place an icon in the leading position to help users identify the card’s category at a glance, add a ghost button to trailing for contextual actions like settings or a menu, and use the footer trailing for primary and secondary action buttons.
Last edited 2 hours ago
An icon in the header leading slot helps users quickly identify the card's category or type at a glance.
Configure your project preferences
A ghost icon button in the header trailing slot is a common pattern for contextual actions like editing, sharing, or opening a menu.
Update your personal information
Action buttons in the footer trailing slot follow a standard confirm/cancel pattern, keeping primary actions clearly separated from the card's content.
---
import Card from "../Card.astro";
import Button from "@pindoba/astro-button";
import Badge from "@pindoba/astro-badge";
import { Icon } from "astro-icon/components";
import { stack, flex } from "@pindoba/styled-system/patterns";
import { css } from "@pindoba/styled-system/css";
---
<div class={stack({ gap: "xl", direction: "column" })}>
<div>
<h3>Icon in Header</h3>
<Card
header={{
heading: "Document",
subheading: "Last edited 2 hours ago",
}}
>
<Icon name="lucide:file-text" size={20} slot="heading-leading" />
<Icon name="lucide:clock" size={14} slot="subheading-leading" />
<Badge feedback="warning" slot="header-trailing">
<Icon name="lucide:pencil" class={css({ w: "1em", h: "1em" })} />
Draft
</Badge>
<p class={css({ margin: "0" })}>
An icon in the header leading slot helps users quickly identify the
card's category or type at a glance.
</p>
</Card>
</div>
<div>
<h3>Button in Header</h3>
<Card
header={{
heading: "Project Settings",
subheading: "Configure your project preferences",
}}
>
<Icon name="lucide:settings" size={20} slot="header-leading" />
<div class={flex({ gap: "sm", align: "center" })} slot="header-trailing">
<Badge feedback="primary" emphasis="secondary">
<Icon
name="lucide:flask-conical"
class={css({ w: "1em", h: "1em" })}
/>
Beta
</Badge>
<Button emphasis="ghost" shape="circle">
<Icon name="lucide:ellipsis" />
</Button>
</div>
<p class={css({ margin: "0" })}>
A ghost icon button in the header trailing slot is a common pattern for
contextual actions like editing, sharing, or opening a menu.
</p>
</Card>
</div>
<div>
<h3>Buttons in Footer</h3>
<Card
header={{
heading: "User Profile",
subheading: "Update your personal information",
}}
>
<Icon name="lucide:user" size={20} slot="heading-leading" />
<Badge feedback="success" slot="header-trailing">
<Icon name="lucide:circle-check" class={css({ w: "1em", h: "1em" })} />
Active
</Badge>
<p class={css({ margin: "0" })}>
Action buttons in the footer trailing slot follow a standard
confirm/cancel pattern, keeping primary actions clearly separated from
the card's content.
</p>
<div class={flex({ gap: "sm" })} slot="footer-trailing">
<Button emphasis="secondary">Cancel</Button>
<Button>Save</Button>
</div>
</Card>
</div>
</div>The passThrough prop provides escape hatches for advanced customization: style accepts any Panda CSS SystemStyleObject applied to any slot, and props forwards arbitrary HTML attributes.
Using passThrough for advanced customization
This card uses passThrough to apply custom styles to specific slots.
---
import Card from "../Card.astro";
import { stack } from "@pindoba/styled-system/patterns";
import { css } from "@pindoba/styled-system/css";
---
<div class={stack({ gap: "md", direction: "column", width: "100%" })}>
<Card
feedback="primary"
border="default"
header={{
heading: "Custom Styled Card",
subheading: "Using passThrough for advanced customization",
}}
passThrough={{
root: {
style: { borderStyle: "dashed" },
},
heading: {
style: { color: "primary.text" },
},
}}
>
<p class={css({ margin: "0" })}>
This card uses passThrough to apply custom styles to specific slots.
</p>
</Card>
</div>The Card primitive composes with Avatar, Badge, Button, and Input to express a wide range of patterns. The demos below cover the most common compositions; everything else is a recombination of the same slots.
Avatar in header.leading, timestamp as eyebrow, action buttons in header.trailing, emoji reactions and reply control in the footer.
Build #2,847 passed
@helena · 2h ago
Bundle shaved 4.2 KB after migrating the icon set to ESM, all 312 tests green, and Lighthouse held at 98 across the board. Pulling staging tomorrow morning — anyone want to pair on the rollout plan over coffee?
---
import Card from "../Card.astro";
import Avatar from "@pindoba/astro-avatar";
import Stamp from "@pindoba/astro-stamp";
import Button from "@pindoba/astro-button";
import { Icon } from "astro-icon/components";
import { stack, flex } from "@pindoba/styled-system/patterns";
import { css } from "@pindoba/styled-system/css";
---
<div class={stack({ gap: "lg", direction: "column", width: "100%" })}>
<Card
border="default"
shadow="sm"
header={{
heading: "Helena Rocha",
subheading: "@helena · 2h ago",
eyebrow: "Build #2,847 passed",
passThrough: {
trailing: { style: { alignItems: "flex-start" } },
},
}}
>
<Avatar
slot="header-leading"
name="Helena Rocha"
src="https://i.pravatar.cc/96?img=32"
size="lg"
/>
<div slot="header-trailing" class={flex({ gap: "2xs", align: "center" })}>
<Button emphasis="ghost" shape="circle" size="sm" feedback="primary">
<Icon name="lucide:reply" />
</Button>
<Button emphasis="ghost" shape="circle" size="sm">
<Icon name="lucide:archive" />
</Button>
</div>
<p class={css({ margin: "0", color: "panel.text" })}>
Bundle shaved 4.2 KB after migrating the icon set to ESM, all 312 tests
green, and Lighthouse held at 98 across the board. Pulling staging
tomorrow morning — anyone want to pair on the rollout plan over coffee?
</p>
<div
slot="footer-leading"
class={flex({ gap: "2xs", align: "center", flex: "1" })}
>
<Stamp size="sm" shape="circle" emphasis="secondary" feedback="primary">
<Icon name="lucide:sparkles" />
</Stamp>
<Stamp size="sm" shape="circle" emphasis="secondary" feedback="success">
<Icon name="lucide:rocket" />
</Stamp>
<Stamp size="sm" shape="circle" emphasis="secondary" feedback="warning">
<Icon name="lucide:coffee" />
</Stamp>
<Stamp size="sm" shape="circle" emphasis="secondary" feedback="warning">
<Icon name="lucide:star" />
</Stamp>
<Stamp size="sm" shape="circle" emphasis="secondary" feedback="danger">
<Icon name="lucide:flame" />
</Stamp>
</div>
<Button
slot="footer-trailing"
emphasis="secondary"
shape="square"
radius="inner"
size="sm"
>
<Icon name="lucide:paperclip" />
</Button>
</Card>
</div>Eyebrow + oversized heading via passThrough.heading.style, paired with a small profile row in the footer.
Today
Tomorrow
Friday
---
import Card from "../Card.astro";
import Avatar from "@pindoba/astro-avatar";
import { css } from "@pindoba/styled-system/css";
import { flex } from "@pindoba/styled-system/patterns";
const dates = [
{
eyebrow: "Today",
heading: "Aug 14",
person: { name: "Olivia Reis", src: "https://i.pravatar.cc/96?img=23" },
label: "Stand-up at 10am",
},
{
eyebrow: "Tomorrow",
heading: "Aug 15",
person: { name: "Felipe Ramos", src: "https://i.pravatar.cc/96?img=15" },
label: "Design critique",
},
{
eyebrow: "Friday",
heading: "Aug 18",
person: { name: "Marina Cruz", src: "https://i.pravatar.cc/96?img=44" },
label: "Sprint demo",
},
];
---
<div
class={css({
display: "grid",
gridTemplateColumns: "repeat(3, minmax(0, 1fr))",
gap: "md",
width: "100%",
})}
>
{
dates.map((d) => (
<Card
border="default"
shadow="sm"
header={{
eyebrow: d.eyebrow,
heading: d.heading,
passThrough: {
heading: {
style: {
fontSize: "4xl",
fontWeight: "bold",
letterSpacing: "tight",
},
},
},
}}
>
<div class={flex({ gap: "xs", align: "center", marginTop: "lg" })}>
<Avatar name={d.person.name} src={d.person.src} size="sm" />
<div class={css({ display: "flex", flexDirection: "column" })}>
<span
class={css({
fontSize: "sm",
fontWeight: "semibold",
color: "panel.text.bold",
lineHeight: "tight",
})}
>
{d.label}
</span>
<span
class={css({
fontSize: "xs",
color: "panel.text.muted",
lineHeight: "tight",
})}
>
{d.person.name}
</span>
</div>
</div>
</Card>
))
}
</div>Avatar cluster in header.leading, with a stacked layout achieved via passThrough.root.style.
Spot which design tokens are pulling weight across the codebase.
Building blocks ready to ship — plus the ones still cooking.
Designers and engineers nudging Pindoba forward, one PR at a time.
---
import Card from "../Card.astro";
import Avatar from "@pindoba/astro-avatar";
import { grid } from "@pindoba/styled-system/patterns";
import { css } from "@pindoba/styled-system/css";
const groups = [
{
heading: "42 active tokens",
subheading: "8 added this week",
body: "Spot which design tokens are pulling weight across the codebase.",
faces: [
"https://i.pravatar.cc/96?img=30",
"https://i.pravatar.cc/96?img=31",
"https://i.pravatar.cc/96?img=32",
"https://i.pravatar.cc/96?img=33",
],
},
{
heading: "16 components",
subheading: "2 in beta",
body: "Building blocks ready to ship — plus the ones still cooking.",
faces: [
"https://i.pravatar.cc/96?img=40",
"https://i.pravatar.cc/96?img=41",
"https://i.pravatar.cc/96?img=42",
],
},
{
heading: "94 contributors",
subheading: "+5 this month",
body: "Designers and engineers nudging Pindoba forward, one PR at a time.",
faces: [
"https://i.pravatar.cc/96?img=50",
"https://i.pravatar.cc/96?img=51",
"https://i.pravatar.cc/96?img=52",
"https://i.pravatar.cc/96?img=53",
],
},
];
---
<div
class={css({
display: "grid",
gridTemplateColumns: "repeat(3, minmax(0, 1fr))",
gap: "md",
width: "100%",
})}
>
{
groups.map((g) => (
<Card
border="default"
shadow="sm"
passThrough={{
root: { style: { textAlign: "center" } },
content: {
style: {
display: "flex",
flexDirection: "column",
alignItems: "center",
gap: "sm",
},
},
}}
>
<div class={grid({ columns: 2, gap: "2xs", width: "fit-content" })}>
{g.faces.slice(0, 4).map((src, i) => (
<Avatar name={`Member ${i + 1}`} src={src} size="sm" />
))}
</div>
<div
class={css({
display: "flex",
flexDirection: "column",
gap: "3xs",
marginTop: "xs",
})}
>
<span
class={css({
fontSize: "lg",
fontWeight: "semibold",
color: "panel.text.bold",
lineHeight: "tight",
})}
>
{g.heading}
</span>
<span
class={css({
fontSize: "sm",
color: "panel.text.muted",
lineHeight: "tight",
})}
>
{g.subheading}
</span>
</div>
<p
class={css({
margin: "0",
fontSize: "sm",
color: "panel.text.muted",
})}
>
{g.body}
</p>
</Card>
))
}
</div>Header with avatar preview and counter, scrollable list in content via maxHeight + overflowY, primary action pinned in footer.
helena@pindoba.dev
felipe@pindoba.dev
marina@pindoba.dev
olivia@pindoba.dev
bruno@pindoba.dev
camila@pindoba.dev
lucas@pindoba.dev
beatriz@pindoba.dev
rafael@pindoba.dev
sofia@pindoba.dev
---
import Card from "../Card.astro";
import Banner from "@pindoba/astro-banner";
import Avatar from "@pindoba/astro-avatar";
import Group from "@pindoba/astro-group";
import Button from "@pindoba/astro-button";
import { Icon } from "astro-icon/components";
import { stack, flex } from "@pindoba/styled-system/patterns";
import { css } from "@pindoba/styled-system/css";
const members = [
{
name: "Helena Rocha",
email: "helena@pindoba.dev",
src: "https://i.pravatar.cc/96?img=32",
},
{
name: "Felipe Ramos",
email: "felipe@pindoba.dev",
src: "https://i.pravatar.cc/96?img=15",
},
{
name: "Marina Cruz",
email: "marina@pindoba.dev",
src: "https://i.pravatar.cc/96?img=44",
},
{
name: "Olivia Reis",
email: "olivia@pindoba.dev",
src: "https://i.pravatar.cc/96?img=23",
},
{
name: "Bruno Carvalho",
email: "bruno@pindoba.dev",
src: "https://i.pravatar.cc/96?img=12",
},
{
name: "Camila Andrade",
email: "camila@pindoba.dev",
src: "https://i.pravatar.cc/96?img=47",
},
{
name: "Lucas Mendes",
email: "lucas@pindoba.dev",
src: "https://i.pravatar.cc/96?img=8",
},
{
name: "Beatriz Lima",
email: "beatriz@pindoba.dev",
src: "https://i.pravatar.cc/96?img=49",
},
{
name: "Rafael Costa",
email: "rafael@pindoba.dev",
src: "https://i.pravatar.cc/96?img=11",
},
{
name: "Sofia Almeida",
email: "sofia@pindoba.dev",
src: "https://i.pravatar.cc/96?img=21",
},
];
---
<div class={stack({ gap: "lg", direction: "column", width: "100%" })}>
<Card border="default" shadow="sm" header={{ heading: "Invite to project" }}>
<Group slot="header-leading" variant="stack">
<Avatar name="Pinned 1" src="https://i.pravatar.cc/96?img=60" size="sm" />
<Avatar name="Pinned 2" src="https://i.pravatar.cc/96?img=61" size="sm" />
<Avatar name="Pinned 3" src="https://i.pravatar.cc/96?img=62" size="sm" />
<Avatar size="sm" name="+38" />
</Group>
<Button slot="header-trailing" emphasis="secondary" size="sm">
Add member
<Icon name="lucide:user-plus" />
</Button>
<div class={flex({ justify: "space-between", align: "center" })}>
<span
class={css({
fontSize: "sm",
fontWeight: "semibold",
color: "panel.text.bold",
})}>Workspace members</span
>
<span
class={css({
fontSize: "xs",
color: "panel.text.muted",
fontWeight: "medium",
})}>42 active</span
>
</div>
<div
class={css({
display: "flex",
flexDirection: "column",
gap: "sm",
marginTop: "sm",
maxHeight: "320px",
overflowY: "auto",
paddingRight: "2xs",
})}
>
{
members.map((m) => (
<Banner size="sm" heading={m.name} subheading={m.email}>
<Avatar slot="leading" name={m.name} src={m.src} size="md" />
<Button
slot="trailing"
emphasis="secondary"
shape="circle"
size="sm"
>
<Icon name="lucide:plus" />
</Button>
</Banner>
))
}
</div>
<Button
slot="footer-trailing"
feedback="primary"
emphasis="primary"
size="sm"
>
<Icon name="lucide:mail" />
Send invites
</Button>
</Card>
</div>A minimal card with no header or footer — content is centered via passThrough.content.style. interactive enables hover feedback.
Folha
Coqueiro
Raiz
---
import Card from "../Card.astro";
import { Icon } from "astro-icon/components";
import { css } from "@pindoba/styled-system/css";
const brands = [
{ name: "Folha", icon: "lucide:leaf" },
{ name: "Coqueiro", icon: "lucide:palmtree" },
{ name: "Raiz", icon: "lucide:sprout" },
];
---
<div
class={css({
display: "grid",
gridTemplateColumns: "repeat(3, minmax(0, 1fr))",
gap: "md",
width: "100%",
})}
>
{
brands.map((b) => (
<Card
interactive
border="default"
shadow="sm"
passThrough={{
content: {
style: {
minHeight: "240px",
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
gap: "lg",
},
},
}}
>
<div
class={css({
display: "flex",
alignItems: "center",
justifyContent: "center",
color: "panel.text.bold",
})}
>
<Icon name={b.icon} size={48} />
</div>
<p
class={css({
margin: "0",
fontSize: "2xl",
fontWeight: "bold",
letterSpacing: "tight",
color: "panel.text.bold",
})}
>
{b.name}
</p>
</Card>
))
}
</div>Header and footer are both panel-backed, so each can carry its own background, feedback, and emphasis independent of the card body. Use it for stepped meta rows, filled hero strips, footer action zones, or success-tinted confirmation banners.
Pinned this morning
A subtly stepped header sets the meta block apart from the body without shouting — useful for activity feeds and threaded conversations.
Your workspace is set up and ready to roll.
Filled feedback surfaces work as hero strips — the header carries its own palette while the body stays in the card's neutral context.
284 events processed
The footer is panel-backed too — a stepped strip is a quiet way to mark the action zone or summary footer without a hard divider line.
Order #4,128
A feedback-tinted footer doubles as a confirmation strip — success here, but warning and danger work the same way for nudges and alerts.
---
import Card from "../Card.astro";
import Avatar from "@pindoba/astro-avatar";
import Button from "@pindoba/astro-button";
import Stamp from "@pindoba/astro-stamp";
import { Icon } from "astro-icon/components";
import { css } from "@pindoba/styled-system/css";
import { flex } from "@pindoba/styled-system/patterns";
---
<div
class={css({
display: "grid",
gridTemplateColumns: "repeat(2, minmax(0, 1fr))",
gap: "md",
width: "100%",
})}
>
<Card
border="default"
shadow="sm"
header={{
heading: "Helena Rocha",
subheading: "Pinned this morning",
background: "surface.step.2",
}}
>
<Avatar
slot="header-leading"
name="Helena Rocha"
src="https://i.pravatar.cc/96?img=32"
size="md"
/>
<Button slot="header-trailing" emphasis="ghost" shape="circle" size="sm">
<Icon name="lucide:ellipsis" />
</Button>
<p class={css({ margin: "0", color: "panel.text" })}>
A subtly stepped header sets the meta block apart from the body without
shouting — useful for activity feeds and threaded conversations.
</p>
</Card>
<Card
border="default"
shadow="sm"
header={{
heading: "Welcome aboard",
subheading: "Your workspace is set up and ready to roll.",
feedback: "primary",
emphasis: "primary",
background: "surface.soft",
}}
>
<Stamp
slot="header-leading"
size="md"
shape="square"
feedback="primary"
emphasis="primary"
background="surface.deep"
>
<Icon name="lucide:rocket" />
</Stamp>
<p class={css({ margin: "0", color: "panel.text" })}>
Filled feedback surfaces work as hero strips — the header carries its own
palette while the body stays in the card's neutral context.
</p>
<Button
slot="footer-trailing"
feedback="primary"
emphasis="primary"
size="sm"
>
Get started
<Icon name="lucide:arrow-right" />
</Button>
</Card>
<Card
border="default"
shadow="sm"
header={{
heading: "Daily digest",
subheading: "284 events processed",
}}
footer={{
background: "surface.step.2",
}}
>
<p class={css({ margin: "0", color: "panel.text" })}>
The footer is panel-backed too — a stepped strip is a quiet way to mark
the action zone or summary footer without a hard divider line.
</p>
<div slot="footer-trailing" class={flex({ gap: "xs", align: "center" })}>
<Button emphasis="ghost" size="sm">Skip</Button>
<Button emphasis="primary" feedback="primary" size="sm">
Open report
</Button>
</div>
</Card>
<Card
border="default"
shadow="sm"
header={{
heading: "Payment received",
subheading: "Order #4,128",
}}
footer={{
feedback: "success",
background: "surface.soft",
}}
>
<Stamp slot="header-leading" size="md" shape="circle" feedback="success">
<Icon name="lucide:check" />
</Stamp>
<p class={css({ margin: "0", color: "panel.text" })}>
A feedback-tinted footer doubles as a confirmation strip — success here,
but warning and danger work the same way for nudges and alerts.
</p>
<Button
slot="footer-trailing"
emphasis="ghost"
feedback="success"
size="sm"
>
View receipt
<Icon name="lucide:arrow-right" />
</Button>
</Card>
</div>The card header supports an eyebrow — a small kicker line above the heading. It is delegated to the underlying Banner component, so it inherits panel-aware text color and auto-flips to contrast under emphasis="primary". Pass it as a string or as { content, leading, trailing } to add an icon.
<Card header={{
eyebrow: "Wednesday",
heading: "Dec 14",
}} />
| prop | type | default | req | description |
|---|---|---|---|---|
| size | "sm""md""lg" | "md" | Controls padding for header, content, and footer sections, and the heading font size. sm: compact. md: default. lg: generous. | |
| background | "surface.soft""surface.step.1""surface.step.2""surface.step.3""surface.deep""transparent" | "surface.soft" | Surface background style forwarded to Panel. surface.soft is the lightest, surface.deep is the darkest. transparent removes the background entirely. | |
| feedback | "neutral""primary""success""warning""danger" | "neutral" | Semantic color palette forwarded to Panel. | |
| border | "none""default""bold""muted" | "none" | Box-shadow ring border forwarded to Panel. | |
| radius | "none""5xs""4xs""3xs""2xs""xs""sm""md""lg""xl""2xl""3xl""4xl""5xl""6xl""7xl""8xl""9xl""10xl""11xl""full" | "md" | Border radius of the card, forwarded to Panel. | |
| padding | "none""5xs""4xs""3xs""2xs""xs""sm""md""lg""xl""2xl" | "none" | Outer padding of the card, forwarded to Panel. Note: header, content, and footer have their own internal padding controlled by size. | |
| interactive | boolean | false | Apply pointer cursor and hover/active states. | |
| emphasis | "primary""secondary""tertiary" | "secondary" | Visual weight inherited from Panel. "primary" fills with the feedback 500 shade; "secondary" (default) uses surface tints; "tertiary" uses a neutral surface with feedback border and text. | |
| translucent | boolean | false | Apply a frosted glass effect with backdrop blur. | |
| header | PrimitiveCardHeaderProps | undefined | Configuration object for the card header section. | |
| footer | PrimitiveCardFooterProps | undefined | Configuration object for the card footer section. | |
| passThrough | { root?: { style?: SystemStyleObject; props?: HTMLAttributes<HTMLDivElement> }; header?: { style?: SystemStyleObject }; content?: { style?: SystemStyleObject }; footer?: { style?: SystemStyleObject }; heading?: { style?: SystemStyleObject }; subheading?: { style?: SystemStyleObject }; ... } | undefined | Custom styling and props for card slots. Each slot accepts style (SystemStyleObject) and props (HTML attributes). | |
| ...rest | HTMLAttributes<HTMLDivElement> | - | Standard HTML div attributes |
PrimitiveCardHeaderProps)| prop | type | default | req | description |
|---|---|---|---|---|
| eyebrow | stringTitleWithLeadingTrailing | undefined | Small kicker line above the heading. Inherits panel-aware text color and auto-flips under emphasis="primary". | |
| heading | stringTitleWithLeadingTrailing | undefined | Main heading content. Can be a string, or an object with content, leading, and trailing. | |
| subheading | stringTitleWithLeadingTrailing | undefined | Subheading content below the main heading. | |
| leading | stringSnippet | undefined | Content displayed at the start of the header (e.g., an icon). | |
| trailing | stringSnippet | undefined | Content displayed at the end of the header. | |
| passThrough | object | undefined | Custom styling and props for header slots. |
PrimitiveCardFooterProps)The footer is Panel-backed — it accepts the full panel surface API so you can give it its own background strip, divider, or interactive treatment independent of the card body. By default the footer is transparent and inherits the card’s feedback / emphasis via context.
| prop | type | default | req | description |
|---|---|---|---|---|
| leading | stringSnippet | undefined | Content displayed at the start of the footer. | |
| trailing | stringSnippet | undefined | Content displayed at the end of the footer. | |
| children | Snippet | undefined | Main footer content. | |
| background | "surface.soft""surface.step.1""surface.step.2""surface.step.3""surface.deep""transparent" | "transparent" | Footer surface background. Use to set a distinct footer strip color. | |
| feedback | "inherit""neutral""primary""success""warning""danger" | card's feedback | Footer color palette. Inherits the card's feedback via context if unset. | |
| emphasis | "primary""secondary""tertiary" | card's emphasis | Footer panel emphasis. Inherits the card's emphasis via context if unset. | |
| border | "none""default""bold""muted""accent" | "none" | Footer box-shadow border. | |
| interactive | boolean | false | Apply pointer cursor and hover/active states on the footer. | |
| passThrough | object | undefined | Custom styling and props for footer slots. |
| prop | type | default | req | description |
|---|---|---|---|---|
| content | stringSnippet | - | The main content of the title. | |
| leading | stringSnippet | undefined | Content before the title. | |
| trailing | stringSnippet | undefined | Content after the title. |