Components Data display
Card
StableA contained surface for related content, with header, media, content and footer parts.
Use Card to group information about one subject, such as a template, contract or integration. Cards can be static, contain actions, or be fully clickable through CardLink. Avoid nesting cards inside cards.
Overview
Exchange relay
Deploys signatures to Microsoft 365 mailboxes.
import { Badge, Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@bindshq/stance-react';
export function Basic() {
return (
<Card style={{ maxWidth: 380 }}>
<CardHeader
actions={
<Badge tone="success" dot>
Live
</Badge>
}
>
<CardTitle>Exchange relay</CardTitle>
<CardDescription>Deploys signatures to Microsoft 365 mailboxes.</CardDescription>
</CardHeader>
<CardContent>Last sync 4 minutes ago · 312 mailboxes</CardContent>
<CardFooter>
<Button variant="ghost" size="sm">
View logs
</Button>
<Button size="sm">Sync now</Button>
</CardFooter>
</Card>
);
}Light, dark and high contrast
Every Stance component is designed and tested in all three appearance modes.
Exchange relay
Deploys signatures to Microsoft 365 mailboxes.
Exchange relay
Deploys signatures to Microsoft 365 mailboxes.
Exchange relay
Deploys signatures to Microsoft 365 mailboxes.
Import
import { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter, CardMedia, CardLink } from '@bindshq/stance-react';Platforms
Card has native counterparts. They share Stance tokens and intent, and use each platform’s own controls and conventions. The live previews on this page are the web implementation.
import { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter, CardMedia, CardLink } from '@bindshq/stance-react';Playground
Sales 2026
Default signature for the sales team
<Card />Examples
Outline
3 contracts awaiting review
Elevated
3 contracts awaiting review
Filled
3 contracts awaiting review
import { Card, CardDescription, CardTitle } from '@bindshq/stance-react';
export function Variants() {
return (
<div
style={{
display: 'grid',
gap: 16,
gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))',
width: '100%',
}}
>
{(['outline', 'elevated', 'filled'] as const).map((v) => (
<Card key={v} variant={v}>
<CardTitle>{v[0]!.toUpperCase() + v.slice(1)}</CardTitle>
<CardDescription>3 contracts awaiting review</CardDescription>
</Card>
))}
</div>
);
}Clickable card
CardLink stretches its hit area across the card. Header actions stay clickable above it.
Executive
Used by 6 people · edited last week
import { Button, Card, CardDescription, CardHeader, CardLink, CardTitle, Icon } from '@bindshq/stance-react';
export function Interactive() {
return (
<Card interactive style={{ maxWidth: 380 }}>
<CardHeader
actions={
<Button size="xs" variant="ghost" aria-label="Duplicate Executive template">
<Icon name="copy" />
</Button>
}
>
<CardTitle>
<CardLink href="#executive">Executive</CardLink>
</CardTitle>
<CardDescription>Used by 6 people · edited last week</CardDescription>
</CardHeader>
</Card>
);
}Minimal
A clean, single-column signature layout.
import { Badge, Button, Card, CardDescription, CardFooter, CardHeader, CardMedia, CardTitle } from '@bindshq/stance-react';
export function WithMedia() {
return (
<Card style={{ maxWidth: 340 }}>
<CardMedia ratio="16 / 7" aria-hidden="true">
<svg viewBox="0 0 320 140" preserveAspectRatio="xMidYMid slice">
<rect width="320" height="140" fill="currentColor" opacity="0.06" />
<rect x="24" y="36" width="120" height="10" rx="5" fill="currentColor" opacity="0.5" />
<rect x="24" y="56" width="180" height="8" rx="4" fill="currentColor" opacity="0.25" />
<rect x="24" y="72" width="150" height="8" rx="4" fill="currentColor" opacity="0.25" />
</svg>
</CardMedia>
<CardHeader>
<CardTitle>Minimal</CardTitle>
<CardDescription>A clean, single-column signature layout.</CardDescription>
</CardHeader>
<CardFooter align="between">
<Badge>Gallery</Badge>
<Button size="sm" variant="outline">
Use template
</Button>
</CardFooter>
</Card>
);
}API reference
Card
| Prop | Type | Default | Description |
|---|---|---|---|
variant | 'outline' | 'elevated' | 'filled' | 'outline' | Surface treatment. |
padding | 'none' | 'sm' | 'md' | 'lg' | 'md' | Inner padding. |
interactive | boolean | false | Make the card a click target through its CardLink. |
asChild | boolean | false | Render as the child element, e.g. <article>. |
CardHeader
| Prop | Type | Default | Description |
|---|---|---|---|
actions | ReactNode | None | Trailing header actions. |
CardTitle
| Prop | Type | Default | Description |
|---|---|---|---|
level | 2 | 3 | 4 | 5 | 6 | 3 | Heading level. |
CardFooter
| Prop | Type | Default | Description |
|---|---|---|---|
align | 'start' | 'end' | 'between' | 'end' | Footer alignment. |
CardMedia
| Prop | Type | Default | Description |
|---|---|---|---|
ratio | number | string | '16 / 9' | Aspect ratio of the media area. |
CardLink
| Prop | Type | Default | Description |
|---|---|---|---|
asChild | boolean | false | Render your router link as the card link. |
Accessibility
- CardTitle renders a real heading; choose a level that fits the page outline.
- Clickable cards use one real link (CardLink) rather than onClick on a div. Its accessible name is the title, so screen-reader link lists stay concise.
- Buttons and links in an interactive card are lifted above the stretched link, so they stay independently operable.
- The focus ring is drawn around the whole card while its link has keyboard focus.
Keyboard
| Keys | Action |
|---|---|
| Tab | Moves to the card link, then to any actions in the card. |
Usage guidelines
Do
- Keep one primary action per card.
- Use asChild with <article> for self-contained content.
Don’t
- Wrap a whole card in <a> when it contains buttons.
- Nest cards.