Card
Deploy to production
Ship the latest build of the main branch.
12 commits since the last release, all checks passing.
Installation
npm install @radix-ui/react-slot@^1.2.4 clsx@^2.1.1 tailwind-merge@^3.4.0lib/utils.ts
components/card/card.tsx
components/card/index.tsThe code below also uses:
npm install @tabler/icons-react@^3.36.1 class-variance-authority@^0.7.1components/button-group/button-group-context.ts
components/spinner/index.ts
components/spinner/spinner.tsx
lib/icons.ts
components/button/button.tsx
components/button/index.tsCode
'use client';
import { Button } from '@/components/button/button';
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from '@/components/card/card';
export default function CardDemo() {
return (
<Card className="nx:w-full nx:max-w-sm">
<CardHeader>
<CardTitle asChild>
<h2>Deploy to production</h2>
</CardTitle>
<CardDescription>
Ship the latest build of the main branch.
</CardDescription>
</CardHeader>
<CardContent>
<p className="nx:typography-body-default">
12 commits since the last release, all checks passing.
</p>
</CardContent>
<CardFooter>
<Button variant="outline">Review changes</Button>
<Button>Deploy</Button>
</CardFooter>
</Card>
);
}
Props
Card
Card adds no props of its own; it accepts the props of the element or primitive it wraps.
CardAction
CardAction adds no props of its own; it accepts the props of the element or primitive it wraps.
CardContent
CardContent adds no props of its own; it accepts the props of the element or primitive it wraps.
CardDescription
CardDescription adds no props of its own; it accepts the props of the element or primitive it wraps.
CardFooter
CardFooter adds no props of its own; it accepts the props of the element or primitive it wraps.
CardHeader
CardHeader adds no props of its own; it accepts the props of the element or primitive it wraps.
CardTitle
| Prop | Type | Default | Description |
|---|---|---|---|
asChild | boolean | false | Render the title styles on a child element. Use this when the card title needs a different heading level in the page outline. |
Examples
Header with action
Team members
Invite people to collaborate.
4 of 5 seats in use on the Team plan.
'use client';
import { Button } from '@/components/button/button';
import {
Card,
CardAction,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from '@/components/card/card';
export default function CardHeaderWithAction() {
return (
<Card className="nx:w-full nx:max-w-sm">
<CardHeader>
<CardTitle asChild>
<h4>Team members</h4>
</CardTitle>
<CardDescription>Invite people to collaborate.</CardDescription>
<CardAction>
<Button size="sm" variant="outline">
Invite
</Button>
</CardAction>
</CardHeader>
<CardContent>
<p className="nx:typography-body-default">
4 of 5 seats in use on the Team plan.
</p>
</CardContent>
</Card>
);
}
Content only
A card with only content works as a plain surface for a note, a quote, or a single metric.
'use client';
import { Card, CardContent } from '@/components/card/card';
export default function CardContentOnly() {
return (
<Card className="nx:w-full nx:max-w-sm">
<CardContent className="nx:pt-6">
<p className="nx:typography-body-default">
A card with only content works as a plain surface for a note, a quote,
or a single metric.
</p>
</CardContent>
</Card>
);
}
Footer actions
Email notifications
Choose what lands in your inbox.
You will get a daily digest of mentions and assigned issues.
'use client';
import { Button } from '@/components/button/button';
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from '@/components/card/card';
export default function CardFooterActions() {
return (
<Card className="nx:w-full nx:max-w-sm">
<CardHeader>
<CardTitle asChild>
<h4>Email notifications</h4>
</CardTitle>
<CardDescription>Choose what lands in your inbox.</CardDescription>
</CardHeader>
<CardContent>
<p className="nx:typography-body-default">
You will get a daily digest of mentions and assigned issues.
</p>
</CardContent>
<CardFooter className="nx:justify-end">
<Button variant="outline">Cancel</Button>
<Button>Save preferences</Button>
</CardFooter>
</Card>
);
}
Sign in form
This example also needs:
npm install @radix-ui/react-label@^2.1.7lib/field-size.ts
components/input/index.ts
components/input/input.tsx
components/label/index.ts
components/label/label.tsx'use client';
import { Button } from '@/components/button/button';
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from '@/components/card/card';
import { Input } from '@/components/input/input';
import { Label } from '@/components/label/label';
export default function CardSignInForm() {
return (
<form
className="nx:w-full nx:max-w-sm"
onSubmit={(event) => event.preventDefault()}
>
<Card>
<CardHeader>
<CardTitle asChild>
<h4>Sign in</h4>
</CardTitle>
<CardDescription>
Enter your email and password to continue.
</CardDescription>
</CardHeader>
<CardContent className="nx:grid nx:gap-4">
<div className="nx:grid nx:gap-1.5">
<Label htmlFor="card-sign-in-email">Email</Label>
<Input
id="card-sign-in-email"
type="email"
autoComplete="email"
placeholder="you@example.com"
required
/>
</div>
<div className="nx:grid nx:gap-1.5">
<Label htmlFor="card-sign-in-password">Password</Label>
<Input
id="card-sign-in-password"
type="password"
autoComplete="current-password"
required
/>
</div>
</CardContent>
<CardFooter>
<Button type="submit" className="nx:w-full">
Sign in
</Button>
</CardFooter>
</Card>
</form>
);
}