Saltar al contenido principal

Card

Agrupar contenido relacionado. Construir layouts estructurados.

Production deploy

Live

web-app, commit 8f2c1ad on main

Build time
42s
Triggered by
lucia@acmestudio.dev
Finished
12 minutes ago
1import { Badge } from '@/components/ui/badge';
2import { Button } from '@/components/ui/button';
3import { Card } from '@/components/ui/card';
4
5export function Default() {
6 return (
7 <Card className="w-full max-w-sm">
8 <Card.Header>
9 <div className="flex items-center justify-between gap-3">
10 <Card.Title>Production deploy</Card.Title>
11 <Badge variant="success">Live</Badge>
12 </div>
13 <Card.Description>web-app, commit 8f2c1ad on main</Card.Description>
14 </Card.Header>
15 <Card.Content className="text-sm">
16 <dl className="grid grid-cols-2 gap-y-2">
17 <dt className="text-muted-foreground">Build time</dt>
18 <dd className="text-right">42s</dd>
19 <dt className="text-muted-foreground">Triggered by</dt>
20 <dd className="text-right">lucia@acmestudio.dev</dd>
21 <dt className="text-muted-foreground">Finished</dt>
22 <dd className="text-right">12 minutes ago</dd>
23 </dl>
24 </Card.Content>
25 <Card.Footer align="between">
26 <Button variant="ghost" size="sm">
27 Roll back
28 </Button>
29 <Button variant="secondary" size="sm">
30 View logs
31 </Button>
32 </Card.Footer>
33 </Card>
34 );
35}

Instalación

pnpm dlx nachui add card

Anatomía

1import { Card } from '@/components/ui/card';
1<Card>
2 <Card.Header>
3 <Card.Title>Título de la tarjeta</Card.Title>
4 <Card.Description>Descripción de la tarjeta</Card.Description>
5 </Card.Header>
6 <Card.Content>
7 <p>Contenido de la tarjeta</p>
8 </Card.Content>
9 <Card.Footer>
10 <p>Pie de la tarjeta</p>
11 </Card.Footer>
12</Card>

Composición

Usa la siguiente composición para construir un Card:
Card
├── Card.Header
│ ├── Card.Title
│ └── Card.Description
├── Card.Content
└── Card.Footer

Variantes

Outline

Tarjetas con un borde prominente y sin sombra.

ci-deploy-key

Read and write

Created Jan 9, last used 3 hours ago

sk_live_4f8a...c210
1import { Badge } from '@/components/ui/badge';
2import { Button } from '@/components/ui/button';
3import { Card } from '@/components/ui/card';
4
5export function Outline() {
6 return (
7 <Card variant="outline" className="w-full max-w-sm">
8 <Card.Header>
9 <div className="flex items-center justify-between gap-3">
10 <Card.Title>ci-deploy-key</Card.Title>
11 <Badge variant="outline">Read and write</Badge>
12 </div>
13 <Card.Description>Created Jan 9, last used 3 hours ago</Card.Description>
14 </Card.Header>
15 <Card.Content className="text-sm">
16 <code className="bg-muted text-muted-foreground block truncate rounded px-2 py-1.5 font-mono text-xs">
17 sk_live_4f8a...c210
18 </code>
19 </Card.Content>
20 <Card.Footer align="between">
21 <Button variant="ghost" size="sm">
22 Copy
23 </Button>
24 <Button variant="ghost" size="sm" className="text-destructive-text">
25 Revoke
26 </Button>
27 </Card.Footer>
28 </Card>
29 );
30}

Ghost

Tarjetas transparentes sin borde ni sombra.

Notifications

How this workspace reaches you.

  • Deploy failuresEmail and Slack
  • New commentsSlack only
  • Weekly usage reportEmail, every Monday
1import { Card } from '@/components/ui/card';
2
3const channels = [
4 { name: 'Deploy failures', detail: 'Email and Slack' },
5 { name: 'New comments', detail: 'Slack only' },
6 { name: 'Weekly usage report', detail: 'Email, every Monday' },
7];
8
9export function Ghost() {
10 return (
11 <div className="border-border bg-card w-full max-w-sm rounded-xl border p-2">
12 <Card variant="ghost">
13 <Card.Header>
14 <Card.Title>Notifications</Card.Title>
15 <Card.Description>How this workspace reaches you.</Card.Description>
16 </Card.Header>
17 <Card.Content className="text-sm">
18 <ul className="space-y-2">
19 {channels.map((channel) => (
20 <li key={channel.name} className="flex items-baseline justify-between gap-3">
21 <span>{channel.name}</span>
22 <span className="text-muted-foreground text-xs">{channel.detail}</span>
23 </li>
24 ))}
25 </ul>
26 </Card.Content>
27 </Card>
28 </div>
29 );
30}

Compacta

Tarjetas con padding reducido para diseños densos.

Default density, billing page

Team plan

$49 per month, renews on Mar 14

12 of 20 seats used. Invoices go to billing@acmestudio.dev.

Compact density, sidebar summary

Team plan

$49 per month, renews on Mar 14

12 of 20 seats used. Invoices go to billing@acmestudio.dev.

1import { Button } from '@/components/ui/button';
2import { Card } from '@/components/ui/card';
3
4const densities = [
5 {
6 label: 'Default density, billing page',
7 compact: false,
8 },
9 {
10 label: 'Compact density, sidebar summary',
11 compact: true,
12 },
13] as const;
14
15export function Compact() {
16 return (
17 <div className="grid w-full max-w-sm gap-6">
18 {densities.map((density) => (
19 <div key={density.label}>
20 <p className="text-muted-foreground mb-2 text-xs">{density.label}</p>
21 <Card>
22 <Card.Header compact={density.compact}>
23 <Card.Title>Team plan</Card.Title>
24 <Card.Description>$49 per month, renews on Mar 14</Card.Description>
25 </Card.Header>
26 <Card.Content compact={density.compact} className="text-sm">
27 <p className="text-muted-foreground">
28 12 of 20 seats used. Invoices go to billing@acmestudio.dev.
29 </p>
30 </Card.Content>
31 <Card.Footer compact={density.compact}>
32 <Button variant="secondary" size="sm">
33 Manage billing
34 </Button>
35 </Card.Footer>
36 </Card>
37 </div>
38 ))}
39 </div>
40 );
41}

Referencia de API

Card

PropTipoDefaultDescripción
variant"default" | "outline" | "ghost""default"Variante visual del card.
asReact.ElementType'div'Cambia el elemento raíz del card.
classNamestringClases adicionales.
childrenReact.ReactNodeContenido del card.

Card.Header

PropTipoDefaultDescripción
compactbooleanfalseReduce el padding superior e inferior del header.
classNamestringClases adicionales.
childrenReact.ReactNodeContenido del header.

Card.Title

PropTipoDefaultDescripción
as'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6''h3'Tag HTML para el título del card.
classNamestringClases adicionales.
childrenReact.ReactNodeContenido del título.

Card.Description

PropTipoDefaultDescripción
classNamestringClases adicionales.
childrenReact.ReactNodeTexto descriptivo.

Card.Content

PropTipoDefaultDescripción
compactbooleanfalseReduce el padding del contenido.
classNamestringClases adicionales.
childrenReact.ReactNodeContenido principal del card.

Card.Footer

PropTipoDefaultDescripción
align'start' | 'center' | 'end' | 'between''start'Controla la alineación horizontal del pie.
compactbooleanfalseReduce el padding del footer.
classNamestringClases adicionales.
childrenReact.ReactNodeContenido del footer.
¿Encontraste algo que mejorar?

¿Notaste un error, tipografía o detalle faltante en esta página? Ayúdanos a mejorar la documentación abriendo un issue en GitHub.

Crear un Issue
Ctrl+I