@adamosuiteservices/ui 1.7.13 → 1.8.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/accordion-rounded.cjs +24 -2
- package/dist/accordion-rounded.js +46 -8
- package/dist/accordion.cjs +20 -1
- package/dist/accordion.js +29 -5
- package/dist/alert.cjs +26 -1
- package/dist/alert.js +33 -8
- package/dist/avatar.cjs +7 -1
- package/dist/avatar.js +8 -2
- package/dist/badge.cjs +83 -1
- package/dist/badge.js +106 -24
- package/dist/breadcrumb.cjs +8 -1
- package/dist/breadcrumb.js +11 -4
- package/dist/button-B7ZP4LZN.js +127 -0
- package/dist/button-D-qFRXiM.cjs +70 -0
- package/dist/button-group.cjs +25 -1
- package/dist/button-group.js +33 -9
- package/dist/button.cjs +1 -1
- package/dist/button.js +1 -1
- package/dist/calendar.cjs +74 -1
- package/dist/calendar.js +114 -35
- package/dist/card.cjs +35 -1
- package/dist/card.js +45 -11
- package/dist/{checkbox-YWAnswaW.cjs → checkbox-CdnZ8VFJ.cjs} +21 -1
- package/dist/{checkbox-Dr487kAg.js → checkbox-DhBcmKze.js} +34 -4
- package/dist/checkbox.cjs +1 -1
- package/dist/checkbox.js +1 -1
- package/dist/combobox.cjs +36 -2
- package/dist/combobox.js +62 -22
- package/dist/components/icons/account-balance-icon.d.ts +3 -0
- package/dist/components/icons/account-icon.d.ts +3 -0
- package/dist/components/icons/add-circle-icon.d.ts +3 -0
- package/dist/components/icons/alarm-icon.d.ts +3 -0
- package/dist/components/icons/archive-icon.d.ts +3 -0
- package/dist/components/icons/arrow-back-icon.d.ts +3 -0
- package/dist/components/icons/arrow-circle-up-icon.d.ts +3 -0
- package/dist/components/icons/arrow-forward-icon.d.ts +3 -0
- package/dist/components/icons/arrow-outward-icon.d.ts +3 -0
- package/dist/components/icons/article-icon.d.ts +3 -0
- package/dist/components/icons/attach-file-icon.d.ts +3 -0
- package/dist/components/icons/autorenew-icon.d.ts +3 -0
- package/dist/components/icons/bookmark-icon.d.ts +3 -0
- package/dist/components/icons/calculate-icon.d.ts +3 -0
- package/dist/components/icons/calendar-today-icon.d.ts +3 -0
- package/dist/components/icons/call-split-icon.d.ts +3 -0
- package/dist/components/icons/cancel-filled-icon.d.ts +3 -0
- package/dist/components/icons/cancel-icon.d.ts +3 -0
- package/dist/components/icons/check-circle-icon.d.ts +3 -0
- package/dist/components/icons/check-icon.d.ts +3 -0
- package/dist/components/icons/chevron-back-icon.d.ts +3 -0
- package/dist/components/icons/chevron-down-icon.d.ts +3 -0
- package/dist/components/icons/chevron-forward-icon.d.ts +3 -0
- package/dist/components/icons/chevron-up-icon.d.ts +3 -0
- package/dist/components/icons/clarify-icon.d.ts +3 -0
- package/dist/components/icons/clock-icon.d.ts +3 -0
- package/dist/components/icons/close-icon.d.ts +3 -0
- package/dist/components/icons/confirmation-number-icon.d.ts +3 -0
- package/dist/components/icons/contacts-icon.d.ts +3 -0
- package/dist/components/icons/contract-delete-icon.d.ts +3 -0
- package/dist/components/icons/copy-icon.d.ts +3 -0
- package/dist/components/icons/do-not-touch-icon.d.ts +3 -0
- package/dist/components/icons/download-icon.d.ts +3 -0
- package/dist/components/icons/dragger-icon.d.ts +3 -0
- package/dist/components/icons/edit-icon.d.ts +3 -0
- package/dist/components/icons/edit-square-icon.d.ts +3 -0
- package/dist/components/icons/exclamation-icon.d.ts +3 -0
- package/dist/components/icons/expand-circle-right-icon.d.ts +3 -0
- package/dist/components/icons/feature-search-icon.d.ts +3 -0
- package/dist/components/icons/filter-icon.d.ts +3 -0
- package/dist/components/icons/folder-icon.d.ts +3 -0
- package/dist/components/icons/folder-open-icon.d.ts +3 -0
- package/dist/components/icons/format-list-bulleted-icon.d.ts +3 -0
- package/dist/components/icons/hamburger-menu-icon.d.ts +3 -0
- package/dist/components/icons/help-icon.d.ts +3 -0
- package/dist/components/icons/hide-pass-icon.d.ts +3 -0
- package/dist/components/icons/home-icon.d.ts +3 -0
- package/dist/components/icons/id-card-icon.d.ts +3 -0
- package/dist/components/icons/index.d.ts +88 -0
- package/dist/components/icons/info-icon.d.ts +3 -0
- package/dist/components/icons/kid-star-icon.d.ts +3 -0
- package/dist/components/icons/language-icon.d.ts +3 -0
- package/dist/components/icons/last-page-icon.d.ts +3 -0
- package/dist/components/icons/layers-icon.d.ts +3 -0
- package/dist/components/icons/location-icon.d.ts +3 -0
- package/dist/components/icons/mail-icon.d.ts +3 -0
- package/dist/components/icons/manage-search-icon.d.ts +3 -0
- package/dist/components/icons/menu-icon.d.ts +3 -0
- package/dist/components/icons/message-icon.d.ts +3 -0
- package/dist/components/icons/metrics-icon.d.ts +3 -0
- package/dist/components/icons/mic-icon.d.ts +3 -0
- package/dist/components/icons/minus-icon.d.ts +3 -0
- package/dist/components/icons/mode-comment-icon.d.ts +3 -0
- package/dist/components/icons/money-icon.d.ts +3 -0
- package/dist/components/icons/monitoring-icon.d.ts +3 -0
- package/dist/components/icons/more-icon.d.ts +3 -0
- package/dist/components/icons/notifications-icon.d.ts +3 -0
- package/dist/components/icons/open-in-new-icon.d.ts +3 -0
- package/dist/components/icons/palette-icon.d.ts +3 -0
- package/dist/components/icons/password-icon.d.ts +3 -0
- package/dist/components/icons/pending-icon.d.ts +3 -0
- package/dist/components/icons/person-add-icon.d.ts +3 -0
- package/dist/components/icons/person-search-icon.d.ts +3 -0
- package/dist/components/icons/photo-icon.d.ts +3 -0
- package/dist/components/icons/plus-icon.d.ts +3 -0
- package/dist/components/icons/policy-icon.d.ts +3 -0
- package/dist/components/icons/publish-icon.d.ts +3 -0
- package/dist/components/icons/ready-icon.d.ts +3 -0
- package/dist/components/icons/receipt-icon.d.ts +3 -0
- package/dist/components/icons/receive-icon.d.ts +3 -0
- package/dist/components/icons/refresh-icon.d.ts +3 -0
- package/dist/components/icons/search-icon.d.ts +3 -0
- package/dist/components/icons/see-icon.d.ts +3 -0
- package/dist/components/icons/send-icon.d.ts +3 -0
- package/dist/components/icons/settings-icon.d.ts +3 -0
- package/dist/components/icons/shield-icon.d.ts +3 -0
- package/dist/components/icons/swap-horiz-icon.d.ts +3 -0
- package/dist/components/icons/tag-icon.d.ts +3 -0
- package/dist/components/icons/trash-icon.d.ts +3 -0
- package/dist/components/layout/toaster/toaster.d.ts +1 -1
- package/dist/components/layout/toaster/toaster.stories.d.ts +1 -1
- package/dist/components/ui/accordion/accordion.d.ts +1 -1
- package/dist/components/ui/accordion/accordion.stories.d.ts +1 -1
- package/dist/components/ui/accordion-rounded/accordion-rounded.d.ts +1 -1
- package/dist/components/ui/accordion-rounded/accordion-rounded.stories.d.ts +1 -1
- package/dist/components/ui/alert/alert.stories.d.ts +1 -1
- package/dist/components/ui/avatar/avatar.d.ts +1 -1
- package/dist/components/ui/avatar/avatar.stories.d.ts +1 -1
- package/dist/components/ui/badge/badge.stories.d.ts +1 -1
- package/dist/components/ui/breadcrumb/breadcrumb.stories.d.ts +1 -1
- package/dist/components/ui/button/button.stories.d.ts +1 -1
- package/dist/components/ui/button-group/button-group.d.ts +1 -1
- package/dist/components/ui/button-group/button-group.stories.d.ts +1 -1
- package/dist/components/ui/calendar/calendar.d.ts +1 -1
- package/dist/components/ui/calendar/calendar.stories.d.ts +1 -1
- package/dist/components/ui/card/card.stories.d.ts +1 -1
- package/dist/components/ui/checkbox/checkbox.d.ts +1 -1
- package/dist/components/ui/checkbox/checkbox.stories.d.ts +1 -1
- package/dist/components/ui/collapsible/collapsible.stories.d.ts +1 -1
- package/dist/components/ui/combobox/combobox.stories.d.ts +1 -1
- package/dist/components/ui/command/command.d.ts +1 -1
- package/dist/components/ui/context-menu/context-menu.d.ts +1 -1
- package/dist/components/ui/context-menu/context-menu.stories.d.ts +1 -1
- package/dist/components/ui/dialog/dialog.d.ts +1 -1
- package/dist/components/ui/dialog/dialog.stories.d.ts +1 -1
- package/dist/components/ui/dropdown-menu/dropdown-menu.d.ts +1 -1
- package/dist/components/ui/dropdown-menu/dropdown-menu.stories.d.ts +1 -1
- package/dist/components/ui/field/field.d.ts +1 -1
- package/dist/components/ui/field/field.stories.d.ts +1 -1
- package/dist/components/ui/hover-card/hover-card.d.ts +1 -1
- package/dist/components/ui/hover-card/hover-card.stories.d.ts +1 -1
- package/dist/components/ui/input/input.stories.d.ts +1 -1
- package/dist/components/ui/input-group/Input-group.stories.d.ts +1 -1
- package/dist/components/ui/input-group/input-group.d.ts +1 -1
- package/dist/components/ui/kbd/kbd.stories.d.ts +1 -1
- package/dist/components/ui/label/label.d.ts +1 -1
- package/dist/components/ui/label/label.stories.d.ts +1 -1
- package/dist/components/ui/pagination/pagination.stories.d.ts +1 -1
- package/dist/components/ui/popover/popover.d.ts +1 -1
- package/dist/components/ui/popover/popover.stories.d.ts +1 -1
- package/dist/components/ui/progress/progress.d.ts +1 -1
- package/dist/components/ui/progress/progress.stories.d.ts +1 -1
- package/dist/components/ui/radio-group/radio-group.d.ts +1 -1
- package/dist/components/ui/radio-group/radio-group.stories.d.ts +1 -1
- package/dist/components/ui/scroll-area/scroll-area.d.ts +1 -1
- package/dist/components/ui/scroll-area/scroll-area.stories.d.ts +1 -1
- package/dist/components/ui/select/select.d.ts +1 -1
- package/dist/components/ui/select/select.stories.d.ts +1 -1
- package/dist/components/ui/separator/separator.d.ts +1 -1
- package/dist/components/ui/separator/separator.stories.d.ts +1 -1
- package/dist/components/ui/sheet/sheet.d.ts +1 -1
- package/dist/components/ui/sheet/sheet.stories.d.ts +1 -1
- package/dist/components/ui/skeleton/skeleton.stories.d.ts +1 -1
- package/dist/components/ui/slider/slider.d.ts +1 -1
- package/dist/components/ui/slider/slider.stories.d.ts +1 -1
- package/dist/components/ui/spinner/spinner.stories.d.ts +1 -1
- package/dist/components/ui/switch/switch.d.ts +1 -1
- package/dist/components/ui/switch/switch.stories.d.ts +1 -1
- package/dist/components/ui/tabs/tabs.d.ts +1 -1
- package/dist/components/ui/tabs/tabs.stories.d.ts +1 -1
- package/dist/components/ui/tabs-underline/tabs-underline.d.ts +1 -1
- package/dist/components/ui/tabs-underline/tabs-underline.stories.d.ts +1 -1
- package/dist/components/ui/textarea/textarea.stories.d.ts +1 -1
- package/dist/components/ui/toggle/toggle.d.ts +1 -1
- package/dist/components/ui/toggle/toggle.stories.d.ts +1 -1
- package/dist/components/ui/tooltip/tooltip.d.ts +1 -1
- package/dist/components/ui/tooltip/tooltip.stories.d.ts +1 -1
- package/dist/context-menu.cjs +79 -1
- package/dist/context-menu.js +101 -11
- package/dist/custom-layered-styles.css +1 -1
- package/dist/dialog.cjs +30 -1
- package/dist/dialog.js +35 -6
- package/dist/dropdown-menu.cjs +79 -1
- package/dist/dropdown-menu.js +101 -11
- package/dist/field.cjs +66 -1
- package/dist/field.js +91 -26
- package/dist/hover-card.cjs +15 -1
- package/dist/hover-card.js +15 -1
- package/dist/icons.cjs +1 -0
- package/dist/icons.js +1507 -0
- package/dist/input-BQZUpTEY.js +42 -0
- package/dist/input-DSmxdfq5.cjs +21 -0
- package/dist/input-group.cjs +76 -1
- package/dist/input-group.js +99 -24
- package/dist/input.cjs +1 -1
- package/dist/input.js +1 -1
- package/dist/kbd.cjs +10 -1
- package/dist/kbd.js +11 -2
- package/dist/{label-CmwGvhy1.js → label-BJ8Yf6Ft.js} +7 -1
- package/dist/{label-BjXORCBM.cjs → label-CNGQhi5L.cjs} +7 -1
- package/dist/label.cjs +1 -1
- package/dist/label.js +1 -1
- package/dist/pagination.cjs +13 -1
- package/dist/pagination.js +30 -6
- package/dist/{popover-FCKBtFo-.cjs → popover-CYbik-H4.cjs} +15 -1
- package/dist/{popover-3rIoNCXs.js → popover-DAwH8jUh.js} +15 -1
- package/dist/popover.cjs +1 -1
- package/dist/popover.js +1 -1
- package/dist/radio-group.cjs +14 -1
- package/dist/radio-group.js +20 -2
- package/dist/select.cjs +68 -1
- package/dist/select.js +83 -10
- package/dist/{separator-BaZqZZ9R.cjs → separator-Brpax0EI.cjs} +7 -1
- package/dist/{separator-DR7lQjv9.js → separator-DVypR3Qf.js} +7 -1
- package/dist/separator.cjs +1 -1
- package/dist/separator.js +1 -1
- package/dist/sheet-CGahUP7F.cjs +41 -0
- package/dist/sheet-Q3dBOQG-.js +174 -0
- package/dist/sheet.cjs +1 -1
- package/dist/sheet.js +1 -1
- package/dist/sidebar.cjs +20 -2
- package/dist/sidebar.js +58 -26
- package/dist/skeleton.cjs +1 -1
- package/dist/skeleton.js +1 -1
- package/dist/slider.cjs +27 -1
- package/dist/slider.js +30 -4
- package/dist/space.css +1 -1
- package/dist/styles.css +1 -1
- package/dist/switch.cjs +18 -1
- package/dist/switch.js +19 -2
- package/dist/table.cjs +20 -1
- package/dist/table.js +26 -7
- package/dist/tabs-underline.cjs +21 -1
- package/dist/tabs-underline.js +23 -3
- package/dist/tabs.cjs +22 -1
- package/dist/tabs.js +24 -3
- package/dist/textarea-CG7iQcb3.cjs +14 -0
- package/dist/textarea-CUPWKl-S.js +32 -0
- package/dist/textarea.cjs +1 -1
- package/dist/textarea.js +1 -1
- package/dist/toaster.cjs +4 -1
- package/dist/toaster.js +9 -6
- package/dist/toggle.cjs +17 -1
- package/dist/toggle.js +25 -9
- package/dist/tooltip.cjs +16 -1
- package/dist/tooltip.js +22 -2
- package/dist/typography.cjs +1 -1
- package/dist/typography.js +6 -6
- package/docs/AI-GUIDE.md +321 -321
- package/docs/components/layout/sidebar.md +404 -404
- package/docs/components/layout/toaster.md +436 -436
- package/docs/components/ui/accordion-rounded.md +583 -583
- package/docs/components/ui/accordion.md +267 -267
- package/docs/components/ui/alert.md +671 -671
- package/docs/components/ui/avatar.md +588 -588
- package/docs/components/ui/badge.md +1024 -1024
- package/docs/components/ui/button-group.md +1002 -1002
- package/docs/components/ui/button.md +1078 -1078
- package/docs/components/ui/calendar.md +1159 -1159
- package/docs/components/ui/card.md +1265 -1265
- package/docs/components/ui/checkbox.md +292 -292
- package/docs/components/ui/collapsible.md +320 -320
- package/docs/components/ui/command.md +454 -454
- package/docs/components/ui/context-menu.md +540 -540
- package/docs/components/ui/dialog.md +628 -628
- package/docs/components/ui/dropdown-menu.md +731 -731
- package/docs/components/ui/field.md +706 -706
- package/docs/components/ui/hover-card.md +446 -446
- package/docs/components/ui/input-group.md +509 -509
- package/docs/components/ui/input.md +362 -362
- package/docs/components/ui/kbd.md +434 -434
- package/docs/components/ui/label.md +359 -359
- package/docs/components/ui/pagination.md +650 -650
- package/docs/components/ui/popover.md +536 -536
- package/docs/components/ui/progress.md +182 -182
- package/docs/components/ui/radio-group.md +311 -311
- package/docs/components/ui/select.md +352 -352
- package/docs/components/ui/separator.md +214 -214
- package/docs/components/ui/sheet.md +142 -142
- package/docs/components/ui/skeleton.md +140 -140
- package/docs/components/ui/slider.md +341 -341
- package/docs/components/ui/spinner.md +170 -170
- package/docs/components/ui/switch.md +402 -402
- package/docs/components/ui/table.md +183 -183
- package/docs/components/ui/tabs-underline.md +106 -106
- package/docs/components/ui/tabs.md +122 -122
- package/docs/components/ui/textarea.md +243 -243
- package/docs/components/ui/toggle.md +243 -243
- package/docs/components/ui/tooltip.md +320 -320
- package/docs/components/ui/typography.md +191 -191
- package/package.json +7 -1
- package/dist/button-2GdKenQI.js +0 -58
- package/dist/button-DEQVHMrX.cjs +0 -1
- package/dist/input-BF73maXg.cjs +0 -1
- package/dist/input-C04hsVXE.js +0 -22
- package/dist/sheet-B-9YHdR5.js +0 -128
- package/dist/sheet-CU-sFSaJ.cjs +0 -1
- package/dist/textarea-3ZdbFRDN.cjs +0 -1
- package/dist/textarea-BZbcAAAu.js +0 -19
|
@@ -1,1265 +1,1265 @@
|
|
|
1
|
-
# Card
|
|
2
|
-
|
|
3
|
-
Contenedor versátil con bordes redondeados, padding y sombra para agrupar contenido relacionado. Incluye 6 variantes de color y un sistema de layout con grid automático para headers con acciones.
|
|
4
|
-
|
|
5
|
-
## Características Principales
|
|
6
|
-
|
|
7
|
-
- **6 variantes de color**: Default, Primary, Muted, Success, Warning, Destructive
|
|
8
|
-
- **Composición modular**: 6 subcomponentes (Card, CardHeader, CardTitle, CardDescription, CardAction, CardContent, CardFooter)
|
|
9
|
-
- **Grid automático en header**: Detecta `CardAction` y ajusta layout automáticamente con `has-data-[slot=card-action]:grid-cols-[1fr_auto]`
|
|
10
|
-
- **Container queries**: CardHeader usa `@container/card-header` para layouts responsive
|
|
11
|
-
- **Spacing flexible**: `gap-6` entre secciones principales, spacing auto en header/footer con bordes
|
|
12
|
-
- **Bordes opcionales**: Clases `.border-b` y `.border-t` añaden separadores con padding automático
|
|
13
|
-
- **Data slots**: Cada subcomponente tiene `data-slot` para targeting CSS específico
|
|
14
|
-
- **Integración con otros componentes**: Background transparente para Calendar/otros componentes anidados
|
|
15
|
-
|
|
16
|
-
## Importación
|
|
17
|
-
|
|
18
|
-
```tsx
|
|
19
|
-
import {
|
|
20
|
-
Card,
|
|
21
|
-
CardHeader,
|
|
22
|
-
CardTitle,
|
|
23
|
-
CardDescription,
|
|
24
|
-
CardAction,
|
|
25
|
-
CardContent,
|
|
26
|
-
CardFooter,
|
|
27
|
-
} from "@adamosuiteservices/ui/card";
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
## Uso Básico
|
|
31
|
-
|
|
32
|
-
### Card Completa
|
|
33
|
-
|
|
34
|
-
Estructura típica con todos los componentes.
|
|
35
|
-
|
|
36
|
-
```tsx
|
|
37
|
-
import {
|
|
38
|
-
Card,
|
|
39
|
-
CardHeader,
|
|
40
|
-
CardTitle,
|
|
41
|
-
CardDescription,
|
|
42
|
-
CardContent,
|
|
43
|
-
CardFooter,
|
|
44
|
-
} from "@adamosuiteservices/ui/card";
|
|
45
|
-
import { Button } from "@adamosuiteservices/ui/button";
|
|
46
|
-
|
|
47
|
-
<Card className="w-[350px]">
|
|
48
|
-
<CardHeader>
|
|
49
|
-
<CardTitle>Card Title</CardTitle>
|
|
50
|
-
<CardDescription>Card Description</CardDescription>
|
|
51
|
-
</CardHeader>
|
|
52
|
-
<CardContent>
|
|
53
|
-
<p>Card Content goes here.</p>
|
|
54
|
-
</CardContent>
|
|
55
|
-
<CardFooter>
|
|
56
|
-
<Button>Action</Button>
|
|
57
|
-
</CardFooter>
|
|
58
|
-
</Card>;
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
### Card Simple (Solo Contenido)
|
|
62
|
-
|
|
63
|
-
Para contenedores minimalistas sin header/footer.
|
|
64
|
-
|
|
65
|
-
```tsx
|
|
66
|
-
<Card className="w-[350px]">
|
|
67
|
-
<CardContent>
|
|
68
|
-
<h3 className="text-lg font-semibold">Simple Card</h3>
|
|
69
|
-
<p className="text-sm text-muted-foreground">
|
|
70
|
-
This is a simple card with just content.
|
|
71
|
-
</p>
|
|
72
|
-
</CardContent>
|
|
73
|
-
</Card>
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
### Con Acción en Header
|
|
77
|
-
|
|
78
|
-
Botón de acción que se alinea automáticamente a la derecha.
|
|
79
|
-
|
|
80
|
-
```tsx
|
|
81
|
-
import { MoreHorizontalIcon } from "lucide-react";
|
|
82
|
-
|
|
83
|
-
<Card className="w-[400px]">
|
|
84
|
-
<CardHeader>
|
|
85
|
-
<CardTitle>Notifications</CardTitle>
|
|
86
|
-
<CardDescription>You have 3 unread messages.</CardDescription>
|
|
87
|
-
<CardAction>
|
|
88
|
-
<Button variant="outline" size="sm">
|
|
89
|
-
<MoreHorizontalIcon />
|
|
90
|
-
</Button>
|
|
91
|
-
</CardAction>
|
|
92
|
-
</CardHeader>
|
|
93
|
-
<CardContent>{/* Notification items */}</CardContent>
|
|
94
|
-
</Card>;
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
**Nota**: El grid se ajusta automáticamente cuando hay `CardAction`.
|
|
98
|
-
|
|
99
|
-
## Componentes
|
|
100
|
-
|
|
101
|
-
### Card
|
|
102
|
-
|
|
103
|
-
Contenedor principal de la card.
|
|
104
|
-
|
|
105
|
-
#### Props
|
|
106
|
-
|
|
107
|
-
| Prop | Tipo | Default | Descripción |
|
|
108
|
-
| ----------- | ------------------------------------------------------------------------------ | ----------- | -------------------------- |
|
|
109
|
-
| `variant` | `"default" \| "primary" \| "muted" \| "success" \| "warning" \| "destructive"` | `"default"` | Variante de color de fondo |
|
|
110
|
-
| `className` | `string` | - | Clases CSS adicionales |
|
|
111
|
-
| `children` | `ReactNode` | - | Contenido de la card |
|
|
112
|
-
|
|
113
|
-
### CardHeader
|
|
114
|
-
|
|
115
|
-
Sección de encabezado con grid automático para título, descripción y acción.
|
|
116
|
-
|
|
117
|
-
#### Props
|
|
118
|
-
|
|
119
|
-
| Prop | Tipo | Descripción |
|
|
120
|
-
| ----------- | ----------- | ---------------------------------------------------------- |
|
|
121
|
-
| `className` | `string` | Clases CSS adicionales |
|
|
122
|
-
| `children` | `ReactNode` | Usualmente contiene CardTitle, CardDescription, CardAction |
|
|
123
|
-
|
|
124
|
-
**Características**:
|
|
125
|
-
|
|
126
|
-
- Grid automático: 2 filas (`grid-rows-[auto_auto]`)
|
|
127
|
-
- Columnas adaptativas: 1 columna por defecto, 2 cuando hay `CardAction` (`has-data-[slot=card-action]:grid-cols-[1fr_auto]`)
|
|
128
|
-
- Container query: `@container/card-header` para responsive interno
|
|
129
|
-
- Padding inferior automático: `[.border-b]:pb-6` cuando se agrega clase `.border-b`
|
|
130
|
-
|
|
131
|
-
### CardTitle
|
|
132
|
-
|
|
133
|
-
Título principal de la card.
|
|
134
|
-
|
|
135
|
-
#### Props
|
|
136
|
-
|
|
137
|
-
| Prop | Tipo | Descripción |
|
|
138
|
-
| ----------- | ----------- | ---------------------- |
|
|
139
|
-
| `className` | `string` | Clases CSS adicionales |
|
|
140
|
-
| `children` | `ReactNode` | Texto del título |
|
|
141
|
-
|
|
142
|
-
**Estilos default**: `leading-none font-semibold`
|
|
143
|
-
|
|
144
|
-
### CardDescription
|
|
145
|
-
|
|
146
|
-
Descripción o subtítulo de la card.
|
|
147
|
-
|
|
148
|
-
#### Props
|
|
149
|
-
|
|
150
|
-
| Prop | Tipo | Descripción |
|
|
151
|
-
| ----------- | ----------- | ---------------------- |
|
|
152
|
-
| `className` | `string` | Clases CSS adicionales |
|
|
153
|
-
| `children` | `ReactNode` | Texto de descripción |
|
|
154
|
-
|
|
155
|
-
**Estilos default**: `text-muted-foreground text-sm`
|
|
156
|
-
|
|
157
|
-
### CardAction
|
|
158
|
-
|
|
159
|
-
Botón o acción alineada a la derecha del header.
|
|
160
|
-
|
|
161
|
-
#### Props
|
|
162
|
-
|
|
163
|
-
| Prop | Tipo | Descripción |
|
|
164
|
-
| ----------- | ----------- | ---------------------- |
|
|
165
|
-
| `className` | `string` | Clases CSS adicionales |
|
|
166
|
-
| `children` | `ReactNode` | Usualmente un Button |
|
|
167
|
-
|
|
168
|
-
**Posicionamiento**:
|
|
169
|
-
|
|
170
|
-
- `col-start-2 row-span-2 row-start-1`: Ocupa columna 2, ambas filas
|
|
171
|
-
- `self-start justify-self-end`: Alineado superior-derecha
|
|
172
|
-
|
|
173
|
-
### CardContent
|
|
174
|
-
|
|
175
|
-
Contenido principal de la card.
|
|
176
|
-
|
|
177
|
-
#### Props
|
|
178
|
-
|
|
179
|
-
| Prop | Tipo | Descripción |
|
|
180
|
-
| ----------- | ----------- | ---------------------- |
|
|
181
|
-
| `className` | `string` | Clases CSS adicionales |
|
|
182
|
-
| `children` | `ReactNode` | Contenido principal |
|
|
183
|
-
|
|
184
|
-
**Estilos default**: `px-6` (padding horizontal matching header/footer)
|
|
185
|
-
|
|
186
|
-
### CardFooter
|
|
187
|
-
|
|
188
|
-
Pie de la card para acciones o información adicional.
|
|
189
|
-
|
|
190
|
-
#### Props
|
|
191
|
-
|
|
192
|
-
| Prop | Tipo | Descripción |
|
|
193
|
-
| ----------- | ----------- | ---------------------- |
|
|
194
|
-
| `className` | `string` | Clases CSS adicionales |
|
|
195
|
-
| `children` | `ReactNode` | Usualmente botones |
|
|
196
|
-
|
|
197
|
-
**Estilos default**:
|
|
198
|
-
|
|
199
|
-
- `flex items-center px-6`: Layout flex horizontal centrado
|
|
200
|
-
- `[.border-t]:pt-6`: Padding superior automático con clase `.border-t`
|
|
201
|
-
|
|
202
|
-
## Variantes
|
|
203
|
-
|
|
204
|
-
### Default
|
|
205
|
-
|
|
206
|
-
Card estándar con fondo blanco/oscuro según tema.
|
|
207
|
-
|
|
208
|
-
```tsx
|
|
209
|
-
<Card variant="default" className="w-[350px]">
|
|
210
|
-
<CardHeader>
|
|
211
|
-
<CardTitle>Default Card</CardTitle>
|
|
212
|
-
<CardDescription>Standard card appearance</CardDescription>
|
|
213
|
-
</CardHeader>
|
|
214
|
-
<CardContent>
|
|
215
|
-
<p className="text-sm">Standard styling with default colors.</p>
|
|
216
|
-
</CardContent>
|
|
217
|
-
</Card>
|
|
218
|
-
```
|
|
219
|
-
|
|
220
|
-
**Colores**: `bg-card text-card-foreground`
|
|
221
|
-
|
|
222
|
-
### Primary
|
|
223
|
-
|
|
224
|
-
Fondo azul claro para información importante.
|
|
225
|
-
|
|
226
|
-
```tsx
|
|
227
|
-
<Card variant="primary" className="w-[350px]">
|
|
228
|
-
<CardHeader>
|
|
229
|
-
<CardTitle>Important Information</CardTitle>
|
|
230
|
-
<CardDescription>Please read carefully</CardDescription>
|
|
231
|
-
</CardHeader>
|
|
232
|
-
<CardContent>
|
|
233
|
-
<p className="text-sm">
|
|
234
|
-
This is important information that requires attention.
|
|
235
|
-
</p>
|
|
236
|
-
</CardContent>
|
|
237
|
-
<CardFooter>
|
|
238
|
-
<Button>Acknowledge</Button>
|
|
239
|
-
</CardFooter>
|
|
240
|
-
</Card>
|
|
241
|
-
```
|
|
242
|
-
|
|
243
|
-
**Colores**: `bg-primary-50` con iconos y texto ajustados
|
|
244
|
-
|
|
245
|
-
### Success
|
|
246
|
-
|
|
247
|
-
Fondo verde claro para confirmaciones exitosas.
|
|
248
|
-
|
|
249
|
-
```tsx
|
|
250
|
-
<Card variant="success" className="w-[350px]">
|
|
251
|
-
<CardHeader>
|
|
252
|
-
<CardTitle>Payment Successful</CardTitle>
|
|
253
|
-
<CardDescription>Your transaction completed</CardDescription>
|
|
254
|
-
</CardHeader>
|
|
255
|
-
<CardContent>
|
|
256
|
-
<p className="text-sm">Your payment has been processed successfully.</p>
|
|
257
|
-
</CardContent>
|
|
258
|
-
<CardFooter>
|
|
259
|
-
<Button variant="outline">View Receipt</Button>
|
|
260
|
-
</CardFooter>
|
|
261
|
-
</Card>
|
|
262
|
-
```
|
|
263
|
-
|
|
264
|
-
**Colores**: `bg-success-50` con texto `text-success/90`
|
|
265
|
-
|
|
266
|
-
### Warning
|
|
267
|
-
|
|
268
|
-
Fondo naranja/amarillo para advertencias.
|
|
269
|
-
|
|
270
|
-
```tsx
|
|
271
|
-
<Card variant="warning" className="w-[350px]">
|
|
272
|
-
<CardHeader>
|
|
273
|
-
<CardTitle>Storage Almost Full</CardTitle>
|
|
274
|
-
<CardDescription>You're running out of space</CardDescription>
|
|
275
|
-
</CardHeader>
|
|
276
|
-
<CardContent>
|
|
277
|
-
<p className="text-sm">You've used 95% of storage. Consider upgrading.</p>
|
|
278
|
-
</CardContent>
|
|
279
|
-
<CardFooter className="gap-2">
|
|
280
|
-
<Button variant="outline" size="sm">
|
|
281
|
-
Manage
|
|
282
|
-
</Button>
|
|
283
|
-
<Button size="sm">Upgrade</Button>
|
|
284
|
-
</CardFooter>
|
|
285
|
-
</Card>
|
|
286
|
-
```
|
|
287
|
-
|
|
288
|
-
**Colores**: `bg-warning-50` con texto `text-warning/90`
|
|
289
|
-
|
|
290
|
-
### Destructive
|
|
291
|
-
|
|
292
|
-
Fondo rojo claro para acciones destructivas o errores.
|
|
293
|
-
|
|
294
|
-
```tsx
|
|
295
|
-
<Card variant="destructive" className="w-[350px]">
|
|
296
|
-
<CardHeader>
|
|
297
|
-
<CardTitle>Delete Account</CardTitle>
|
|
298
|
-
<CardDescription>This action cannot be undone</CardDescription>
|
|
299
|
-
</CardHeader>
|
|
300
|
-
<CardContent>
|
|
301
|
-
<p className="text-sm">
|
|
302
|
-
Permanently delete your account? All data will be lost.
|
|
303
|
-
</p>
|
|
304
|
-
</CardContent>
|
|
305
|
-
<CardFooter className="gap-2">
|
|
306
|
-
<Button variant="outline" size="sm">
|
|
307
|
-
Cancel
|
|
308
|
-
</Button>
|
|
309
|
-
<Button variant="destructive" size="sm">
|
|
310
|
-
Delete
|
|
311
|
-
</Button>
|
|
312
|
-
</CardFooter>
|
|
313
|
-
</Card>
|
|
314
|
-
```
|
|
315
|
-
|
|
316
|
-
**Colores**: `bg-destructive-50` con texto `text-destructive/90`
|
|
317
|
-
|
|
318
|
-
### Muted
|
|
319
|
-
|
|
320
|
-
Fondo gris claro para información secundaria.
|
|
321
|
-
|
|
322
|
-
```tsx
|
|
323
|
-
<Card variant="muted" className="w-full">
|
|
324
|
-
<CardHeader>
|
|
325
|
-
<CardTitle>Muted Card</CardTitle>
|
|
326
|
-
<CardDescription>Less prominent information</CardDescription>
|
|
327
|
-
</CardHeader>
|
|
328
|
-
<CardContent>
|
|
329
|
-
<p className="text-sm">
|
|
330
|
-
Information that doesn't require immediate attention.
|
|
331
|
-
</p>
|
|
332
|
-
</CardContent>
|
|
333
|
-
</Card>
|
|
334
|
-
```
|
|
335
|
-
|
|
336
|
-
**Colores**: `bg-muted` con texto `text-muted/90`
|
|
337
|
-
|
|
338
|
-
**Colores**: `bg-muted` con texto `text-muted/90`
|
|
339
|
-
|
|
340
|
-
## Patrones Avanzados
|
|
341
|
-
|
|
342
|
-
### Formulario de Login
|
|
343
|
-
|
|
344
|
-
Card completa con form, inputs y múltiples acciones.
|
|
345
|
-
|
|
346
|
-
```tsx
|
|
347
|
-
import { Input } from "@adamosuiteservices/ui/input";
|
|
348
|
-
import { Label } from "@adamosuiteservices/ui/label";
|
|
349
|
-
|
|
350
|
-
<Card className="w-full max-w-sm">
|
|
351
|
-
<CardHeader>
|
|
352
|
-
<CardTitle>Login to your account</CardTitle>
|
|
353
|
-
<CardDescription>Enter your email below to login</CardDescription>
|
|
354
|
-
<CardAction>
|
|
355
|
-
<Button variant="link">Sign Up</Button>
|
|
356
|
-
</CardAction>
|
|
357
|
-
</CardHeader>
|
|
358
|
-
<CardContent>
|
|
359
|
-
<form>
|
|
360
|
-
<div className="flex flex-col gap-6">
|
|
361
|
-
<div className="grid gap-2">
|
|
362
|
-
<Label htmlFor="email">Email</Label>
|
|
363
|
-
<Input id="email" type="email" placeholder="m@example.com" required />
|
|
364
|
-
</div>
|
|
365
|
-
<div className="grid gap-2">
|
|
366
|
-
<div className="flex items-center">
|
|
367
|
-
<Label htmlFor="password">Password</Label>
|
|
368
|
-
<a
|
|
369
|
-
href="#"
|
|
370
|
-
className="ml-auto text-sm underline-offset-4 hover:underline"
|
|
371
|
-
>
|
|
372
|
-
Forgot password?
|
|
373
|
-
</a>
|
|
374
|
-
</div>
|
|
375
|
-
<Input id="password" type="password" required />
|
|
376
|
-
</div>
|
|
377
|
-
</div>
|
|
378
|
-
</form>
|
|
379
|
-
</CardContent>
|
|
380
|
-
<CardFooter className="flex-col gap-2">
|
|
381
|
-
<Button type="submit" className="w-full">
|
|
382
|
-
Login
|
|
383
|
-
</Button>
|
|
384
|
-
<Button variant="outline" className="w-full">
|
|
385
|
-
Login with Google
|
|
386
|
-
</Button>
|
|
387
|
-
</CardFooter>
|
|
388
|
-
</Card>;
|
|
389
|
-
```
|
|
390
|
-
|
|
391
|
-
### Perfil de Usuario
|
|
392
|
-
|
|
393
|
-
Card con avatar, stats y acciones múltiples.
|
|
394
|
-
|
|
395
|
-
```tsx
|
|
396
|
-
import { Avatar } from "@adamosuiteservices/ui/avatar";
|
|
397
|
-
import {
|
|
398
|
-
HeartIcon,
|
|
399
|
-
StarIcon,
|
|
400
|
-
ShareIcon,
|
|
401
|
-
ExternalLinkIcon,
|
|
402
|
-
UserIcon,
|
|
403
|
-
} from "lucide-react";
|
|
404
|
-
|
|
405
|
-
<Card className="w-[380px]">
|
|
406
|
-
<CardHeader>
|
|
407
|
-
<div className="flex items-center space-x-4">
|
|
408
|
-
<Avatar className="h-12 w-12">
|
|
409
|
-
<UserIcon />
|
|
410
|
-
</Avatar>
|
|
411
|
-
<div>
|
|
412
|
-
<CardTitle>Sofia Davis</CardTitle>
|
|
413
|
-
<CardDescription>Product Designer</CardDescription>
|
|
414
|
-
</div>
|
|
415
|
-
</div>
|
|
416
|
-
<CardAction>
|
|
417
|
-
<Button variant="outline" size="sm">
|
|
418
|
-
Follow
|
|
419
|
-
</Button>
|
|
420
|
-
</CardAction>
|
|
421
|
-
</CardHeader>
|
|
422
|
-
<CardContent>
|
|
423
|
-
<div className="text-sm text-muted-foreground">
|
|
424
|
-
Passionate about creating beautiful user experiences.
|
|
425
|
-
</div>
|
|
426
|
-
</CardContent>
|
|
427
|
-
<CardFooter className="flex justify-between">
|
|
428
|
-
<div className="flex space-x-4 text-sm text-muted-foreground">
|
|
429
|
-
<div className="flex items-center">
|
|
430
|
-
<HeartIcon className="mr-1 h-3 w-3" />
|
|
431
|
-
256
|
|
432
|
-
</div>
|
|
433
|
-
<div className="flex items-center">
|
|
434
|
-
<StarIcon className="mr-1 h-3 w-3" />
|
|
435
|
-
98
|
|
436
|
-
</div>
|
|
437
|
-
</div>
|
|
438
|
-
<div className="flex space-x-1">
|
|
439
|
-
<Button variant="ghost" size="sm">
|
|
440
|
-
<ShareIcon />
|
|
441
|
-
</Button>
|
|
442
|
-
<Button variant="ghost" size="sm">
|
|
443
|
-
<ExternalLinkIcon />
|
|
444
|
-
</Button>
|
|
445
|
-
</div>
|
|
446
|
-
</CardFooter>
|
|
447
|
-
</Card>;
|
|
448
|
-
```
|
|
449
|
-
|
|
450
|
-
### Card de Producto
|
|
451
|
-
|
|
452
|
-
E-commerce card con imagen, badge, precio y acciones.
|
|
453
|
-
|
|
454
|
-
```tsx
|
|
455
|
-
import { Badge } from "@adamosuiteservices/ui/badge";
|
|
456
|
-
import { StarIcon, CreditCardIcon, HeartIcon } from "lucide-react";
|
|
457
|
-
|
|
458
|
-
<Card className="w-[350px]">
|
|
459
|
-
<CardHeader>
|
|
460
|
-
<div className="aspect-square rounded-md bg-muted"></div>
|
|
461
|
-
</CardHeader>
|
|
462
|
-
<CardContent>
|
|
463
|
-
<div className="space-y-2">
|
|
464
|
-
<Badge variant="secondary">Electronics</Badge>
|
|
465
|
-
<CardTitle>Wireless Headphones</CardTitle>
|
|
466
|
-
<CardDescription>
|
|
467
|
-
Premium wireless headphones with noise cancellation.
|
|
468
|
-
</CardDescription>
|
|
469
|
-
<div className="flex items-center justify-between">
|
|
470
|
-
<div className="text-2xl font-bold">$299.99</div>
|
|
471
|
-
<div className="flex items-center text-sm text-muted-foreground">
|
|
472
|
-
<StarIcon className="mr-1 h-4 w-4 fill-current" />
|
|
473
|
-
4.5 (128)
|
|
474
|
-
</div>
|
|
475
|
-
</div>
|
|
476
|
-
</div>
|
|
477
|
-
</CardContent>
|
|
478
|
-
<CardFooter className="flex gap-2">
|
|
479
|
-
<Button className="flex-1">
|
|
480
|
-
<CreditCardIcon />
|
|
481
|
-
Add to Cart
|
|
482
|
-
</Button>
|
|
483
|
-
<Button variant="outline" size="sm">
|
|
484
|
-
<HeartIcon />
|
|
485
|
-
</Button>
|
|
486
|
-
</CardFooter>
|
|
487
|
-
</Card>;
|
|
488
|
-
```
|
|
489
|
-
|
|
490
|
-
### Stats Cards (Dashboard)
|
|
491
|
-
|
|
492
|
-
Grid de cards para métricas con iconos y tendencias.
|
|
493
|
-
|
|
494
|
-
```tsx
|
|
495
|
-
import { DollarSignIcon, UserIcon, CreditCardIcon } from "lucide-react";
|
|
496
|
-
|
|
497
|
-
<div className="grid gap-4 grid-cols-1 md:grid-cols-2 lg:grid-cols-4">
|
|
498
|
-
<Card>
|
|
499
|
-
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
|
500
|
-
<CardTitle className="text-sm font-medium">Total Revenue</CardTitle>
|
|
501
|
-
<DollarSignIcon className="h-4 w-4 text-muted-foreground" />
|
|
502
|
-
</CardHeader>
|
|
503
|
-
<CardContent>
|
|
504
|
-
<div className="text-2xl font-bold">$45,231.89</div>
|
|
505
|
-
<p className="text-xs text-muted-foreground">+20.1% from last month</p>
|
|
506
|
-
</CardContent>
|
|
507
|
-
</Card>
|
|
508
|
-
|
|
509
|
-
<Card>
|
|
510
|
-
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
|
511
|
-
<CardTitle className="text-sm font-medium">Subscriptions</CardTitle>
|
|
512
|
-
<UserIcon className="h-4 w-4 text-muted-foreground" />
|
|
513
|
-
</CardHeader>
|
|
514
|
-
<CardContent>
|
|
515
|
-
<div className="text-2xl font-bold">+2350</div>
|
|
516
|
-
<p className="text-xs text-muted-foreground">+180.1% from last month</p>
|
|
517
|
-
</CardContent>
|
|
518
|
-
</Card>
|
|
519
|
-
|
|
520
|
-
<Card>
|
|
521
|
-
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
|
522
|
-
<CardTitle className="text-sm font-medium">Sales</CardTitle>
|
|
523
|
-
<CreditCardIcon className="h-4 w-4 text-muted-foreground" />
|
|
524
|
-
</CardHeader>
|
|
525
|
-
<CardContent>
|
|
526
|
-
<div className="text-2xl font-bold">+12,234</div>
|
|
527
|
-
<p className="text-xs text-muted-foreground">+19% from last month</p>
|
|
528
|
-
</CardContent>
|
|
529
|
-
</Card>
|
|
530
|
-
|
|
531
|
-
<Card>
|
|
532
|
-
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
|
533
|
-
<CardTitle className="text-sm font-medium">Active Now</CardTitle>
|
|
534
|
-
<UserIcon className="h-4 w-4 text-muted-foreground" />
|
|
535
|
-
</CardHeader>
|
|
536
|
-
<CardContent>
|
|
537
|
-
<div className="text-2xl font-bold">+573</div>
|
|
538
|
-
<p className="text-xs text-muted-foreground">+201 since last hour</p>
|
|
539
|
-
</CardContent>
|
|
540
|
-
</Card>
|
|
541
|
-
</div>;
|
|
542
|
-
```
|
|
543
|
-
|
|
544
|
-
### Card de Notificaciones
|
|
545
|
-
|
|
546
|
-
Lista de notificaciones con items y acción de marcar leído.
|
|
547
|
-
|
|
548
|
-
```tsx
|
|
549
|
-
import { BellIcon, MailIcon, CheckIcon } from "lucide-react";
|
|
550
|
-
|
|
551
|
-
<Card className="w-[380px]">
|
|
552
|
-
<CardHeader>
|
|
553
|
-
<CardTitle>Notifications</CardTitle>
|
|
554
|
-
<CardDescription>You have 3 unread messages.</CardDescription>
|
|
555
|
-
</CardHeader>
|
|
556
|
-
<CardContent className="grid gap-4">
|
|
557
|
-
<div className="flex items-center space-x-4 rounded-md border p-4">
|
|
558
|
-
<BellIcon className="h-4 w-4" />
|
|
559
|
-
<div className="flex-1 space-y-1">
|
|
560
|
-
<p className="text-sm font-medium leading-none">Push Notifications</p>
|
|
561
|
-
<p className="text-sm text-muted-foreground">
|
|
562
|
-
Send notifications to device.
|
|
563
|
-
</p>
|
|
564
|
-
</div>
|
|
565
|
-
</div>
|
|
566
|
-
<div className="flex items-center space-x-4 rounded-md border p-4">
|
|
567
|
-
<MailIcon className="h-4 w-4" />
|
|
568
|
-
<div className="flex-1 space-y-1">
|
|
569
|
-
<p className="text-sm font-medium leading-none">Email Notifications</p>
|
|
570
|
-
<p className="text-sm text-muted-foreground">
|
|
571
|
-
Send notifications to email.
|
|
572
|
-
</p>
|
|
573
|
-
</div>
|
|
574
|
-
</div>
|
|
575
|
-
</CardContent>
|
|
576
|
-
<CardFooter>
|
|
577
|
-
<Button className="w-full">
|
|
578
|
-
<CheckIcon />
|
|
579
|
-
Mark all as read
|
|
580
|
-
</Button>
|
|
581
|
-
</CardFooter>
|
|
582
|
-
</Card>;
|
|
583
|
-
```
|
|
584
|
-
|
|
585
|
-
### Con Separadores (Border)
|
|
586
|
-
|
|
587
|
-
Usa `.border-b` y `.border-t` para separadores visuales.
|
|
588
|
-
|
|
589
|
-
```tsx
|
|
590
|
-
<Card className="w-[350px]">
|
|
591
|
-
<CardHeader className="border-b">
|
|
592
|
-
<CardTitle>Settings</CardTitle>
|
|
593
|
-
<CardDescription>Manage your preferences</CardDescription>
|
|
594
|
-
</CardHeader>
|
|
595
|
-
<CardContent>
|
|
596
|
-
<div className="space-y-4">{/* Settings content */}</div>
|
|
597
|
-
</CardContent>
|
|
598
|
-
<CardFooter className="border-t">
|
|
599
|
-
<Button className="w-full">Save Changes</Button>
|
|
600
|
-
</CardFooter>
|
|
601
|
-
</Card>
|
|
602
|
-
```
|
|
603
|
-
|
|
604
|
-
**Nota**: El padding se ajusta automáticamente (`pb-6` en header, `pt-6` en footer).
|
|
605
|
-
|
|
606
|
-
### Grid de Variantes
|
|
607
|
-
|
|
608
|
-
Mostrar todas las variantes en una vista comparativa.
|
|
609
|
-
|
|
610
|
-
```tsx
|
|
611
|
-
<div className="grid gap-6 grid-cols-1 md:grid-cols-2 lg:grid-cols-3">
|
|
612
|
-
<Card variant="default">
|
|
613
|
-
<CardHeader>
|
|
614
|
-
<CardTitle>Default</CardTitle>
|
|
615
|
-
<CardDescription>Standard card</CardDescription>
|
|
616
|
-
</CardHeader>
|
|
617
|
-
<CardContent>
|
|
618
|
-
<p className="text-sm">Standard styling.</p>
|
|
619
|
-
</CardContent>
|
|
620
|
-
</Card>
|
|
621
|
-
|
|
622
|
-
<Card variant="primary">
|
|
623
|
-
<CardHeader>
|
|
624
|
-
<CardTitle>Primary</CardTitle>
|
|
625
|
-
<CardDescription>Important info</CardDescription>
|
|
626
|
-
</CardHeader>
|
|
627
|
-
<CardContent>
|
|
628
|
-
<p className="text-sm">Highlight important content.</p>
|
|
629
|
-
</CardContent>
|
|
630
|
-
</Card>
|
|
631
|
-
|
|
632
|
-
<Card variant="success">
|
|
633
|
-
<CardHeader>
|
|
634
|
-
<CardTitle>Success</CardTitle>
|
|
635
|
-
<CardDescription>Success message</CardDescription>
|
|
636
|
-
</CardHeader>
|
|
637
|
-
<CardContent>
|
|
638
|
-
<p className="text-sm">Successful operations.</p>
|
|
639
|
-
</CardContent>
|
|
640
|
-
</Card>
|
|
641
|
-
|
|
642
|
-
<Card variant="warning">
|
|
643
|
-
<CardHeader>
|
|
644
|
-
<CardTitle>Warning</CardTitle>
|
|
645
|
-
<CardDescription>Caution message</CardDescription>
|
|
646
|
-
</CardHeader>
|
|
647
|
-
<CardContent>
|
|
648
|
-
<p className="text-sm">Important warnings.</p>
|
|
649
|
-
</CardContent>
|
|
650
|
-
</Card>
|
|
651
|
-
|
|
652
|
-
<Card variant="destructive">
|
|
653
|
-
<CardHeader>
|
|
654
|
-
<CardTitle>Destructive</CardTitle>
|
|
655
|
-
<CardDescription>Error or danger</CardDescription>
|
|
656
|
-
</CardHeader>
|
|
657
|
-
<CardContent>
|
|
658
|
-
<p className="text-sm">Errors or destructive actions.</p>
|
|
659
|
-
</CardContent>
|
|
660
|
-
</Card>
|
|
661
|
-
|
|
662
|
-
<Card variant="muted">
|
|
663
|
-
<CardHeader>
|
|
664
|
-
<CardTitle>Muted</CardTitle>
|
|
665
|
-
<CardDescription>Secondary info</CardDescription>
|
|
666
|
-
</CardHeader>
|
|
667
|
-
<CardContent>
|
|
668
|
-
<p className="text-sm">Less important information.</p>
|
|
669
|
-
</CardContent>
|
|
670
|
-
</Card>
|
|
671
|
-
</div>
|
|
672
|
-
```
|
|
673
|
-
|
|
674
|
-
### Header con Layout Custom
|
|
675
|
-
|
|
676
|
-
Override del grid para layouts específicos.
|
|
677
|
-
|
|
678
|
-
```tsx
|
|
679
|
-
{
|
|
680
|
-
/* Horizontal layout con custom spacing */
|
|
681
|
-
}
|
|
682
|
-
<Card className="w-[400px]">
|
|
683
|
-
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
|
684
|
-
<CardTitle className="text-sm font-medium">Custom Layout</CardTitle>
|
|
685
|
-
<Badge>New</Badge>
|
|
686
|
-
</CardHeader>
|
|
687
|
-
<CardContent>
|
|
688
|
-
<div className="text-2xl font-bold">Content</div>
|
|
689
|
-
</CardContent>
|
|
690
|
-
</Card>;
|
|
691
|
-
```
|
|
692
|
-
|
|
693
|
-
### Footer con Múltiples Acciones
|
|
694
|
-
|
|
695
|
-
Diferentes arreglos de botones.
|
|
696
|
-
|
|
697
|
-
```tsx
|
|
698
|
-
{
|
|
699
|
-
/* Botones horizontales con gap */
|
|
700
|
-
}
|
|
701
|
-
<Card>
|
|
702
|
-
<CardHeader>
|
|
703
|
-
<CardTitle>Confirm Action</CardTitle>
|
|
704
|
-
</CardHeader>
|
|
705
|
-
<CardContent>
|
|
706
|
-
<p>Are you sure?</p>
|
|
707
|
-
</CardContent>
|
|
708
|
-
<CardFooter className="gap-2">
|
|
709
|
-
<Button variant="outline" size="sm">
|
|
710
|
-
Cancel
|
|
711
|
-
</Button>
|
|
712
|
-
<Button size="sm">Confirm</Button>
|
|
713
|
-
</CardFooter>
|
|
714
|
-
</Card>;
|
|
715
|
-
|
|
716
|
-
{
|
|
717
|
-
/* Botones apilados verticalmente */
|
|
718
|
-
}
|
|
719
|
-
<Card>
|
|
720
|
-
<CardHeader>
|
|
721
|
-
<CardTitle>Choose Option</CardTitle>
|
|
722
|
-
</CardHeader>
|
|
723
|
-
<CardContent>
|
|
724
|
-
<p>Select an action:</p>
|
|
725
|
-
</CardContent>
|
|
726
|
-
<CardFooter className="flex-col gap-2">
|
|
727
|
-
<Button className="w-full">Primary Action</Button>
|
|
728
|
-
<Button variant="outline" className="w-full">
|
|
729
|
-
Secondary
|
|
730
|
-
</Button>
|
|
731
|
-
</CardFooter>
|
|
732
|
-
</Card>;
|
|
733
|
-
|
|
734
|
-
{
|
|
735
|
-
/* Acciones distribuidas */
|
|
736
|
-
}
|
|
737
|
-
<Card>
|
|
738
|
-
<CardHeader>
|
|
739
|
-
<CardTitle>Actions</CardTitle>
|
|
740
|
-
</CardHeader>
|
|
741
|
-
<CardContent>
|
|
742
|
-
<p>Multiple actions available.</p>
|
|
743
|
-
</CardContent>
|
|
744
|
-
<CardFooter className="justify-between">
|
|
745
|
-
<Button variant="outline" size="sm">
|
|
746
|
-
Cancel
|
|
747
|
-
</Button>
|
|
748
|
-
<div className="flex gap-2">
|
|
749
|
-
<Button variant="outline" size="sm">
|
|
750
|
-
Save Draft
|
|
751
|
-
</Button>
|
|
752
|
-
<Button size="sm">Publish</Button>
|
|
753
|
-
</div>
|
|
754
|
-
</CardFooter>
|
|
755
|
-
</Card>;
|
|
756
|
-
```
|
|
757
|
-
|
|
758
|
-
## Casos de Uso Comunes
|
|
759
|
-
|
|
760
|
-
### Authentication Forms
|
|
761
|
-
|
|
762
|
-
```tsx
|
|
763
|
-
<Card className="w-full max-w-md">
|
|
764
|
-
<CardHeader>
|
|
765
|
-
<CardTitle>Create Account</CardTitle>
|
|
766
|
-
<CardDescription>Sign up to get started</CardDescription>
|
|
767
|
-
</CardHeader>
|
|
768
|
-
<CardContent className="space-y-4">
|
|
769
|
-
<Input type="text" placeholder="Full Name" />
|
|
770
|
-
<Input type="email" placeholder="Email" />
|
|
771
|
-
<Input type="password" placeholder="Password" />
|
|
772
|
-
</CardContent>
|
|
773
|
-
<CardFooter>
|
|
774
|
-
<Button className="w-full">Create Account</Button>
|
|
775
|
-
</CardFooter>
|
|
776
|
-
</Card>
|
|
777
|
-
```
|
|
778
|
-
|
|
779
|
-
### Dashboard Widgets
|
|
780
|
-
|
|
781
|
-
```tsx
|
|
782
|
-
<Card>
|
|
783
|
-
<CardHeader>
|
|
784
|
-
<CardTitle>Recent Activity</CardTitle>
|
|
785
|
-
<CardDescription>Your latest actions</CardDescription>
|
|
786
|
-
<CardAction>
|
|
787
|
-
<Button variant="ghost" size="sm">
|
|
788
|
-
View All
|
|
789
|
-
</Button>
|
|
790
|
-
</CardAction>
|
|
791
|
-
</CardHeader>
|
|
792
|
-
<CardContent>{/* Activity list */}</CardContent>
|
|
793
|
-
</Card>
|
|
794
|
-
```
|
|
795
|
-
|
|
796
|
-
### Settings Panels
|
|
797
|
-
|
|
798
|
-
```tsx
|
|
799
|
-
<Card className="border-b">
|
|
800
|
-
<CardHeader>
|
|
801
|
-
<CardTitle>Account Settings</CardTitle>
|
|
802
|
-
<CardDescription>Manage your account preferences</CardDescription>
|
|
803
|
-
</CardHeader>
|
|
804
|
-
<CardContent className="space-y-4">{/* Settings options */}</CardContent>
|
|
805
|
-
<CardFooter className="border-t">
|
|
806
|
-
<Button>Save Changes</Button>
|
|
807
|
-
</CardFooter>
|
|
808
|
-
</Card>
|
|
809
|
-
```
|
|
810
|
-
|
|
811
|
-
### Pricing Cards
|
|
812
|
-
|
|
813
|
-
```tsx
|
|
814
|
-
<div className="grid gap-4 md:grid-cols-3">
|
|
815
|
-
<Card>
|
|
816
|
-
<CardHeader>
|
|
817
|
-
<CardTitle>Basic</CardTitle>
|
|
818
|
-
<CardDescription>For individuals</CardDescription>
|
|
819
|
-
</CardHeader>
|
|
820
|
-
<CardContent>
|
|
821
|
-
<div className="text-3xl font-bold">$9/mo</div>
|
|
822
|
-
<ul className="mt-4 space-y-2 text-sm">
|
|
823
|
-
<li>✓ Feature 1</li>
|
|
824
|
-
<li>✓ Feature 2</li>
|
|
825
|
-
</ul>
|
|
826
|
-
</CardContent>
|
|
827
|
-
<CardFooter>
|
|
828
|
-
<Button variant="outline" className="w-full">
|
|
829
|
-
Choose Plan
|
|
830
|
-
</Button>
|
|
831
|
-
</CardFooter>
|
|
832
|
-
</Card>
|
|
833
|
-
{/* More pricing tiers */}
|
|
834
|
-
</div>
|
|
835
|
-
```
|
|
836
|
-
|
|
837
|
-
### Status/Alert Cards
|
|
838
|
-
|
|
839
|
-
```tsx
|
|
840
|
-
<Card variant="warning">
|
|
841
|
-
<CardHeader>
|
|
842
|
-
<CardTitle>Action Required</CardTitle>
|
|
843
|
-
<CardDescription>Your subscription expires soon</CardDescription>
|
|
844
|
-
</CardHeader>
|
|
845
|
-
<CardContent>
|
|
846
|
-
<p className="text-sm">
|
|
847
|
-
Renew your subscription to continue accessing premium features.
|
|
848
|
-
</p>
|
|
849
|
-
</CardContent>
|
|
850
|
-
<CardFooter>
|
|
851
|
-
<Button>Renew Now</Button>
|
|
852
|
-
</CardFooter>
|
|
853
|
-
</Card>
|
|
854
|
-
```
|
|
855
|
-
|
|
856
|
-
## Mejores Prácticas
|
|
857
|
-
|
|
858
|
-
### Usa Anchos Fijos para Consistencia
|
|
859
|
-
|
|
860
|
-
```tsx
|
|
861
|
-
{
|
|
862
|
-
/* ✅ Correcto - Ancho consistente */
|
|
863
|
-
}
|
|
864
|
-
<Card className="w-[350px]">
|
|
865
|
-
<CardContent>Consistent width</CardContent>
|
|
866
|
-
</Card>;
|
|
867
|
-
|
|
868
|
-
{
|
|
869
|
-
/* ✅ También correcto - max-w para responsive */
|
|
870
|
-
}
|
|
871
|
-
<Card className="w-full max-w-md">
|
|
872
|
-
<CardContent>Responsive width</CardContent>
|
|
873
|
-
</Card>;
|
|
874
|
-
|
|
875
|
-
{
|
|
876
|
-
/* ❌ Evitar - Sin ancho puede expandirse inesperadamente */
|
|
877
|
-
}
|
|
878
|
-
<Card>
|
|
879
|
-
<CardContent>No width constraint</CardContent>
|
|
880
|
-
</Card>;
|
|
881
|
-
```
|
|
882
|
-
|
|
883
|
-
### Variantes Semánticas
|
|
884
|
-
|
|
885
|
-
```tsx
|
|
886
|
-
{/* ✅ Correcto - Variante según significado */}
|
|
887
|
-
<Card variant="success">
|
|
888
|
-
<CardContent>Payment processed!</CardContent>
|
|
889
|
-
</Card>
|
|
890
|
-
|
|
891
|
-
<Card variant="destructive">
|
|
892
|
-
<CardContent>Error occurred</CardContent>
|
|
893
|
-
</Card>
|
|
894
|
-
|
|
895
|
-
{/* ❌ Incorrecto - Variante no semántica */}
|
|
896
|
-
<Card variant="success">
|
|
897
|
-
<CardContent>Error occurred</CardContent> {/* Confuso */}
|
|
898
|
-
</Card>
|
|
899
|
-
```
|
|
900
|
-
|
|
901
|
-
### Estructura de Header Completa
|
|
902
|
-
|
|
903
|
-
```tsx
|
|
904
|
-
{
|
|
905
|
-
/* ✅ Correcto - Título + Descripción */
|
|
906
|
-
}
|
|
907
|
-
<CardHeader>
|
|
908
|
-
<CardTitle>Title</CardTitle>
|
|
909
|
-
<CardDescription>Description</CardDescription>
|
|
910
|
-
</CardHeader>;
|
|
911
|
-
|
|
912
|
-
{
|
|
913
|
-
/* ⚠️ Aceptable - Solo título */
|
|
914
|
-
}
|
|
915
|
-
<CardHeader>
|
|
916
|
-
<CardTitle>Title Only</CardTitle>
|
|
917
|
-
</CardHeader>;
|
|
918
|
-
|
|
919
|
-
{
|
|
920
|
-
/* ❌ Evitar - Solo descripción sin título */
|
|
921
|
-
}
|
|
922
|
-
<CardHeader>
|
|
923
|
-
<CardDescription>No title</CardDescription>
|
|
924
|
-
</CardHeader>;
|
|
925
|
-
```
|
|
926
|
-
|
|
927
|
-
### CardAction Solo en CardHeader
|
|
928
|
-
|
|
929
|
-
```tsx
|
|
930
|
-
{
|
|
931
|
-
/* ✅ Correcto - CardAction dentro de CardHeader */
|
|
932
|
-
}
|
|
933
|
-
<CardHeader>
|
|
934
|
-
<CardTitle>Title</CardTitle>
|
|
935
|
-
<CardDescription>Description</CardDescription>
|
|
936
|
-
<CardAction>
|
|
937
|
-
<Button size="sm">Action</Button>
|
|
938
|
-
</CardAction>
|
|
939
|
-
</CardHeader>;
|
|
940
|
-
|
|
941
|
-
{
|
|
942
|
-
/* ❌ Incorrecto - CardAction fuera de CardHeader */
|
|
943
|
-
}
|
|
944
|
-
<Card>
|
|
945
|
-
<CardTitle>Title</CardTitle>
|
|
946
|
-
<CardAction>
|
|
947
|
-
<Button>Won't position correctly</Button>
|
|
948
|
-
</CardAction>
|
|
949
|
-
</Card>;
|
|
950
|
-
```
|
|
951
|
-
|
|
952
|
-
### Footer Flex para Múltiples Botones
|
|
953
|
-
|
|
954
|
-
```tsx
|
|
955
|
-
{
|
|
956
|
-
/* ✅ Correcto - Gap entre botones */
|
|
957
|
-
}
|
|
958
|
-
<CardFooter className="gap-2">
|
|
959
|
-
<Button variant="outline">Cancel</Button>
|
|
960
|
-
<Button>Confirm</Button>
|
|
961
|
-
</CardFooter>;
|
|
962
|
-
|
|
963
|
-
{
|
|
964
|
-
/* ✅ Correcto - Full width individual */
|
|
965
|
-
}
|
|
966
|
-
<CardFooter className="flex-col gap-2">
|
|
967
|
-
<Button className="w-full">Primary</Button>
|
|
968
|
-
<Button variant="outline" className="w-full">
|
|
969
|
-
Secondary
|
|
970
|
-
</Button>
|
|
971
|
-
</CardFooter>;
|
|
972
|
-
|
|
973
|
-
{
|
|
974
|
-
/* ❌ Evitar - Sin gap entre botones */
|
|
975
|
-
}
|
|
976
|
-
<CardFooter>
|
|
977
|
-
<Button>Button1</Button>
|
|
978
|
-
<Button>Button2</Button> {/* Se pegan */}
|
|
979
|
-
</CardFooter>;
|
|
980
|
-
```
|
|
981
|
-
|
|
982
|
-
### Bordes Opcionales
|
|
983
|
-
|
|
984
|
-
```tsx
|
|
985
|
-
{
|
|
986
|
-
/* ✅ Correcto - Border con padding automático */
|
|
987
|
-
}
|
|
988
|
-
<Card>
|
|
989
|
-
<CardHeader className="border-b">
|
|
990
|
-
<CardTitle>Title</CardTitle>
|
|
991
|
-
</CardHeader>
|
|
992
|
-
<CardContent>Content</CardContent>
|
|
993
|
-
<CardFooter className="border-t">
|
|
994
|
-
<Button>Action</Button>
|
|
995
|
-
</CardFooter>
|
|
996
|
-
</Card>;
|
|
997
|
-
|
|
998
|
-
{
|
|
999
|
-
/* ❌ Evitar - Border sin la clase en header/footer */
|
|
1000
|
-
}
|
|
1001
|
-
<Card className="border-b">
|
|
1002
|
-
{" "}
|
|
1003
|
-
{/* No aplica padding correcto */}
|
|
1004
|
-
<CardHeader>
|
|
1005
|
-
<CardTitle>Title</CardTitle>
|
|
1006
|
-
</CardHeader>
|
|
1007
|
-
</Card>;
|
|
1008
|
-
```
|
|
1009
|
-
|
|
1010
|
-
### Grid en Stats Cards
|
|
1011
|
-
|
|
1012
|
-
```tsx
|
|
1013
|
-
{
|
|
1014
|
-
/* ✅ Correcto - Override spacing cuando es necesario */
|
|
1015
|
-
}
|
|
1016
|
-
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
|
1017
|
-
<CardTitle className="text-sm font-medium">Stat</CardTitle>
|
|
1018
|
-
<Icon className="h-4 w-4 text-muted-foreground" />
|
|
1019
|
-
</CardHeader>;
|
|
1020
|
-
|
|
1021
|
-
{
|
|
1022
|
-
/* ❌ Incorrecto - Usar grid default con layout horizontal */
|
|
1023
|
-
}
|
|
1024
|
-
<CardHeader className="flex-row">
|
|
1025
|
-
{" "}
|
|
1026
|
-
{/* Grid sigue activo */}
|
|
1027
|
-
<CardTitle>Stat</CardTitle>
|
|
1028
|
-
<Icon />
|
|
1029
|
-
</CardHeader>;
|
|
1030
|
-
```
|
|
1031
|
-
|
|
1032
|
-
## Notas de Implementación
|
|
1033
|
-
|
|
1034
|
-
- **Basado en CVA**: Usa `class-variance-authority` para variantes de color
|
|
1035
|
-
- **Data Slots**: Cada componente tiene `data-slot` para CSS targeting específico (`data-slot="card"`, `data-slot="card-header"`, etc.)
|
|
1036
|
-
- **Grid Automático**: CardHeader usa `has-data-[slot=card-action]:grid-cols-[1fr_auto]` para detectar CardAction y ajustar layout
|
|
1037
|
-
- **Container Queries**: CardHeader tiene `@container/card-header` para responsive interno (requiere Tailwind CSS container queries)
|
|
1038
|
-
- **Spacing Consistente**: `gap-6` entre secciones (header, content, footer), `px-6` horizontal en todas las secciones
|
|
1039
|
-
- **Padding Condicional**: `.border-b` y `.border-t` triggers automáticos para `pb-6` y `pt-6` respectivamente
|
|
1040
|
-
- **Variantes de Color**: Cada variante ajusta `bg-*-50` y `text-*-foreground`, con ajustes para iconos SVG (`[&>svg]:text-current`)
|
|
1041
|
-
- **Rounded Corners**: `rounded-xl` por defecto (12px)
|
|
1042
|
-
- **Shadow**: `shadow-sm` para elevación sutil
|
|
1043
|
-
- **Flex Column**: Card root usa `flex flex-col gap-6` para layout vertical automático
|
|
1044
|
-
|
|
1045
|
-
## Accesibilidad
|
|
1046
|
-
|
|
1047
|
-
### Estructura Semántica
|
|
1048
|
-
|
|
1049
|
-
Cards usan `<div>` por defecto, pero considera añadir roles ARIA cuando sea apropiado.
|
|
1050
|
-
|
|
1051
|
-
```tsx
|
|
1052
|
-
{
|
|
1053
|
-
/* Para cards interactivas */
|
|
1054
|
-
}
|
|
1055
|
-
<Card role="article" aria-labelledby="card-title">
|
|
1056
|
-
<CardHeader>
|
|
1057
|
-
<CardTitle id="card-title">Article Title</CardTitle>
|
|
1058
|
-
</CardHeader>
|
|
1059
|
-
<CardContent>Content</CardContent>
|
|
1060
|
-
</Card>;
|
|
1061
|
-
|
|
1062
|
-
{
|
|
1063
|
-
/* Para cards clickeables */
|
|
1064
|
-
}
|
|
1065
|
-
<Card
|
|
1066
|
-
role="button"
|
|
1067
|
-
tabIndex={0}
|
|
1068
|
-
onClick={handleClick}
|
|
1069
|
-
onKeyDown={(e) => e.key === "Enter" && handleClick()}
|
|
1070
|
-
>
|
|
1071
|
-
<CardContent>Clickable card</CardContent>
|
|
1072
|
-
</Card>;
|
|
1073
|
-
```
|
|
1074
|
-
|
|
1075
|
-
### Labels para CardAction
|
|
1076
|
-
|
|
1077
|
-
```tsx
|
|
1078
|
-
{
|
|
1079
|
-
/* ✅ Correcto - aria-label descriptiva */
|
|
1080
|
-
}
|
|
1081
|
-
<CardAction>
|
|
1082
|
-
<Button variant="outline" size="sm" aria-label="More options">
|
|
1083
|
-
<MoreHorizontalIcon />
|
|
1084
|
-
</Button>
|
|
1085
|
-
</CardAction>;
|
|
1086
|
-
|
|
1087
|
-
{
|
|
1088
|
-
/* ❌ Incorrecto - Sin label para icono solo */
|
|
1089
|
-
}
|
|
1090
|
-
<CardAction>
|
|
1091
|
-
<Button variant="outline" size="sm">
|
|
1092
|
-
<MoreHorizontalIcon />
|
|
1093
|
-
</Button>
|
|
1094
|
-
</CardAction>;
|
|
1095
|
-
```
|
|
1096
|
-
|
|
1097
|
-
### Formularios Accesibles
|
|
1098
|
-
|
|
1099
|
-
```tsx
|
|
1100
|
-
{
|
|
1101
|
-
/* ✅ Correcto - Labels asociadas */
|
|
1102
|
-
}
|
|
1103
|
-
<CardContent>
|
|
1104
|
-
<div className="space-y-4">
|
|
1105
|
-
<div className="grid gap-2">
|
|
1106
|
-
<Label htmlFor="email">Email</Label>
|
|
1107
|
-
<Input id="email" type="email" />
|
|
1108
|
-
</div>
|
|
1109
|
-
</div>
|
|
1110
|
-
</CardContent>;
|
|
1111
|
-
```
|
|
1112
|
-
|
|
1113
|
-
### Focus Management
|
|
1114
|
-
|
|
1115
|
-
Cards no son focuseables por defecto. Si necesitas interactividad:
|
|
1116
|
-
|
|
1117
|
-
```tsx
|
|
1118
|
-
{
|
|
1119
|
-
/* Para cards clickeables */
|
|
1120
|
-
}
|
|
1121
|
-
<Card
|
|
1122
|
-
tabIndex={0}
|
|
1123
|
-
role="button"
|
|
1124
|
-
className="cursor-pointer hover:shadow-md transition-shadow focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
|
|
1125
|
-
onClick={handleClick}
|
|
1126
|
-
>
|
|
1127
|
-
<CardContent>Interactive card</CardContent>
|
|
1128
|
-
</Card>;
|
|
1129
|
-
```
|
|
1130
|
-
|
|
1131
|
-
## Troubleshooting
|
|
1132
|
-
|
|
1133
|
-
### CardAction No Se Alinea a la Derecha
|
|
1134
|
-
|
|
1135
|
-
**Problema**: CardAction no aparece en la posición correcta.
|
|
1136
|
-
|
|
1137
|
-
**Solución**:
|
|
1138
|
-
|
|
1139
|
-
```tsx
|
|
1140
|
-
// ❌ Problema - CardAction fuera de CardHeader
|
|
1141
|
-
<Card>
|
|
1142
|
-
<CardTitle>Title</CardTitle>
|
|
1143
|
-
<CardAction>
|
|
1144
|
-
<Button>Action</Button>
|
|
1145
|
-
</CardAction>
|
|
1146
|
-
</Card>
|
|
1147
|
-
|
|
1148
|
-
// ✅ Solución - CardAction dentro de CardHeader
|
|
1149
|
-
<Card>
|
|
1150
|
-
<CardHeader>
|
|
1151
|
-
<CardTitle>Title</CardTitle>
|
|
1152
|
-
<CardDescription>Description</CardDescription>
|
|
1153
|
-
<CardAction>
|
|
1154
|
-
<Button>Action</Button>
|
|
1155
|
-
</CardAction>
|
|
1156
|
-
</CardHeader>
|
|
1157
|
-
</Card>
|
|
1158
|
-
```
|
|
1159
|
-
|
|
1160
|
-
### Gap Excesivo entre Secciones
|
|
1161
|
-
|
|
1162
|
-
**Problema**: Mucho espacio entre header/content/footer.
|
|
1163
|
-
|
|
1164
|
-
**Solución**:
|
|
1165
|
-
|
|
1166
|
-
```tsx
|
|
1167
|
-
// ✅ El gap-6 es intencional, pero puedes reducirlo
|
|
1168
|
-
<Card className="gap-4"> {/* Override gap-6 */}
|
|
1169
|
-
<CardHeader>...</CardHeader>
|
|
1170
|
-
<CardContent>...</CardContent>
|
|
1171
|
-
</Card>
|
|
1172
|
-
|
|
1173
|
-
// O eliminar gap completamente
|
|
1174
|
-
<Card className="gap-0">
|
|
1175
|
-
<CardHeader>...</CardHeader>
|
|
1176
|
-
<CardContent>...</CardContent>
|
|
1177
|
-
</Card>
|
|
1178
|
-
```
|
|
1179
|
-
|
|
1180
|
-
### Bordes No Muestran Padding
|
|
1181
|
-
|
|
1182
|
-
**Problema**: `.border-b` o `.border-t` no agregan padding.
|
|
1183
|
-
|
|
1184
|
-
**Solución**:
|
|
1185
|
-
|
|
1186
|
-
```tsx
|
|
1187
|
-
// ❌ Problema - Border en elemento incorrecto
|
|
1188
|
-
<Card className="border-b">
|
|
1189
|
-
<CardHeader>...</CardHeader>
|
|
1190
|
-
</Card>
|
|
1191
|
-
|
|
1192
|
-
// ✅ Solución - Border en CardHeader o CardFooter
|
|
1193
|
-
<Card>
|
|
1194
|
-
<CardHeader className="border-b">...</CardHeader>
|
|
1195
|
-
<CardContent>...</CardContent>
|
|
1196
|
-
<CardFooter className="border-t">...</CardFooter>
|
|
1197
|
-
</Card>
|
|
1198
|
-
```
|
|
1199
|
-
|
|
1200
|
-
### Variante No Cambia Color
|
|
1201
|
-
|
|
1202
|
-
**Problema**: Variante primary/success/etc no aplica colores.
|
|
1203
|
-
|
|
1204
|
-
**Solución**:
|
|
1205
|
-
|
|
1206
|
-
```tsx
|
|
1207
|
-
// ✅ Verifica que la prop sea en Card root
|
|
1208
|
-
<Card variant="primary"> {/* Correcto */}
|
|
1209
|
-
<CardHeader>...</CardHeader>
|
|
1210
|
-
</Card>
|
|
1211
|
-
|
|
1212
|
-
// ❌ No funciona en subcomponentes
|
|
1213
|
-
<Card>
|
|
1214
|
-
<CardHeader variant="primary"> {/* No existe esta prop */}
|
|
1215
|
-
...
|
|
1216
|
-
</CardHeader>
|
|
1217
|
-
</Card>
|
|
1218
|
-
```
|
|
1219
|
-
|
|
1220
|
-
### Stats Cards con Layout Incorrecto
|
|
1221
|
-
|
|
1222
|
-
**Problema**: Íconos y títulos no se alinean horizontalmente.
|
|
1223
|
-
|
|
1224
|
-
**Solución**:
|
|
1225
|
-
|
|
1226
|
-
```tsx
|
|
1227
|
-
// ✅ Override grid con flex
|
|
1228
|
-
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
|
1229
|
-
<CardTitle className="text-sm font-medium">Revenue</CardTitle>
|
|
1230
|
-
<DollarSignIcon className="h-4 w-4" />
|
|
1231
|
-
</CardHeader>
|
|
1232
|
-
```
|
|
1233
|
-
|
|
1234
|
-
### Footer Buttons No Se Distribuyen
|
|
1235
|
-
|
|
1236
|
-
**Problema**: Botones en footer se pegan sin espacio.
|
|
1237
|
-
|
|
1238
|
-
**Solución**:
|
|
1239
|
-
|
|
1240
|
-
```tsx
|
|
1241
|
-
// ❌ Problema - Sin gap
|
|
1242
|
-
<CardFooter>
|
|
1243
|
-
<Button>Cancel</Button>
|
|
1244
|
-
<Button>Confirm</Button>
|
|
1245
|
-
</CardFooter>
|
|
1246
|
-
|
|
1247
|
-
// ✅ Solución - Añade gap
|
|
1248
|
-
<CardFooter className="gap-2">
|
|
1249
|
-
<Button>Cancel</Button>
|
|
1250
|
-
<Button>Confirm</Button>
|
|
1251
|
-
</CardFooter>
|
|
1252
|
-
|
|
1253
|
-
// ✅ O usa justify-between
|
|
1254
|
-
<CardFooter className="justify-between">
|
|
1255
|
-
<Button>Cancel</Button>
|
|
1256
|
-
<Button>Confirm</Button>
|
|
1257
|
-
</CardFooter>
|
|
1258
|
-
```
|
|
1259
|
-
|
|
1260
|
-
## Referencias
|
|
1261
|
-
|
|
1262
|
-
- **CVA (Class Variance Authority)**: https://cva.style/docs
|
|
1263
|
-
- **shadcn/ui Card**: https://ui.shadcn.com/docs/components/card
|
|
1264
|
-
- **Tailwind Container Queries**: https://tailwindcss.com/docs/hover-focus-and-other-states#container-queries
|
|
1265
|
-
- **ARIA Article Role**: https://www.w3.org/TR/wai-aria-1.2/#article
|
|
1
|
+
# Card
|
|
2
|
+
|
|
3
|
+
Contenedor versátil con bordes redondeados, padding y sombra para agrupar contenido relacionado. Incluye 6 variantes de color y un sistema de layout con grid automático para headers con acciones.
|
|
4
|
+
|
|
5
|
+
## Características Principales
|
|
6
|
+
|
|
7
|
+
- **6 variantes de color**: Default, Primary, Muted, Success, Warning, Destructive
|
|
8
|
+
- **Composición modular**: 6 subcomponentes (Card, CardHeader, CardTitle, CardDescription, CardAction, CardContent, CardFooter)
|
|
9
|
+
- **Grid automático en header**: Detecta `CardAction` y ajusta layout automáticamente con `has-data-[slot=card-action]:grid-cols-[1fr_auto]`
|
|
10
|
+
- **Container queries**: CardHeader usa `@container/card-header` para layouts responsive
|
|
11
|
+
- **Spacing flexible**: `gap-6` entre secciones principales, spacing auto en header/footer con bordes
|
|
12
|
+
- **Bordes opcionales**: Clases `.border-b` y `.border-t` añaden separadores con padding automático
|
|
13
|
+
- **Data slots**: Cada subcomponente tiene `data-slot` para targeting CSS específico
|
|
14
|
+
- **Integración con otros componentes**: Background transparente para Calendar/otros componentes anidados
|
|
15
|
+
|
|
16
|
+
## Importación
|
|
17
|
+
|
|
18
|
+
```tsx
|
|
19
|
+
import {
|
|
20
|
+
Card,
|
|
21
|
+
CardHeader,
|
|
22
|
+
CardTitle,
|
|
23
|
+
CardDescription,
|
|
24
|
+
CardAction,
|
|
25
|
+
CardContent,
|
|
26
|
+
CardFooter,
|
|
27
|
+
} from "@adamosuiteservices/ui/card";
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Uso Básico
|
|
31
|
+
|
|
32
|
+
### Card Completa
|
|
33
|
+
|
|
34
|
+
Estructura típica con todos los componentes.
|
|
35
|
+
|
|
36
|
+
```tsx
|
|
37
|
+
import {
|
|
38
|
+
Card,
|
|
39
|
+
CardHeader,
|
|
40
|
+
CardTitle,
|
|
41
|
+
CardDescription,
|
|
42
|
+
CardContent,
|
|
43
|
+
CardFooter,
|
|
44
|
+
} from "@adamosuiteservices/ui/card";
|
|
45
|
+
import { Button } from "@adamosuiteservices/ui/button";
|
|
46
|
+
|
|
47
|
+
<Card className="w-[350px]">
|
|
48
|
+
<CardHeader>
|
|
49
|
+
<CardTitle>Card Title</CardTitle>
|
|
50
|
+
<CardDescription>Card Description</CardDescription>
|
|
51
|
+
</CardHeader>
|
|
52
|
+
<CardContent>
|
|
53
|
+
<p>Card Content goes here.</p>
|
|
54
|
+
</CardContent>
|
|
55
|
+
<CardFooter>
|
|
56
|
+
<Button>Action</Button>
|
|
57
|
+
</CardFooter>
|
|
58
|
+
</Card>;
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Card Simple (Solo Contenido)
|
|
62
|
+
|
|
63
|
+
Para contenedores minimalistas sin header/footer.
|
|
64
|
+
|
|
65
|
+
```tsx
|
|
66
|
+
<Card className="w-[350px]">
|
|
67
|
+
<CardContent>
|
|
68
|
+
<h3 className="text-lg font-semibold">Simple Card</h3>
|
|
69
|
+
<p className="text-sm text-muted-foreground">
|
|
70
|
+
This is a simple card with just content.
|
|
71
|
+
</p>
|
|
72
|
+
</CardContent>
|
|
73
|
+
</Card>
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Con Acción en Header
|
|
77
|
+
|
|
78
|
+
Botón de acción que se alinea automáticamente a la derecha.
|
|
79
|
+
|
|
80
|
+
```tsx
|
|
81
|
+
import { MoreHorizontalIcon } from "lucide-react";
|
|
82
|
+
|
|
83
|
+
<Card className="w-[400px]">
|
|
84
|
+
<CardHeader>
|
|
85
|
+
<CardTitle>Notifications</CardTitle>
|
|
86
|
+
<CardDescription>You have 3 unread messages.</CardDescription>
|
|
87
|
+
<CardAction>
|
|
88
|
+
<Button variant="outline" size="sm">
|
|
89
|
+
<MoreHorizontalIcon />
|
|
90
|
+
</Button>
|
|
91
|
+
</CardAction>
|
|
92
|
+
</CardHeader>
|
|
93
|
+
<CardContent>{/* Notification items */}</CardContent>
|
|
94
|
+
</Card>;
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
**Nota**: El grid se ajusta automáticamente cuando hay `CardAction`.
|
|
98
|
+
|
|
99
|
+
## Componentes
|
|
100
|
+
|
|
101
|
+
### Card
|
|
102
|
+
|
|
103
|
+
Contenedor principal de la card.
|
|
104
|
+
|
|
105
|
+
#### Props
|
|
106
|
+
|
|
107
|
+
| Prop | Tipo | Default | Descripción |
|
|
108
|
+
| ----------- | ------------------------------------------------------------------------------ | ----------- | -------------------------- |
|
|
109
|
+
| `variant` | `"default" \| "primary" \| "muted" \| "success" \| "warning" \| "destructive"` | `"default"` | Variante de color de fondo |
|
|
110
|
+
| `className` | `string` | - | Clases CSS adicionales |
|
|
111
|
+
| `children` | `ReactNode` | - | Contenido de la card |
|
|
112
|
+
|
|
113
|
+
### CardHeader
|
|
114
|
+
|
|
115
|
+
Sección de encabezado con grid automático para título, descripción y acción.
|
|
116
|
+
|
|
117
|
+
#### Props
|
|
118
|
+
|
|
119
|
+
| Prop | Tipo | Descripción |
|
|
120
|
+
| ----------- | ----------- | ---------------------------------------------------------- |
|
|
121
|
+
| `className` | `string` | Clases CSS adicionales |
|
|
122
|
+
| `children` | `ReactNode` | Usualmente contiene CardTitle, CardDescription, CardAction |
|
|
123
|
+
|
|
124
|
+
**Características**:
|
|
125
|
+
|
|
126
|
+
- Grid automático: 2 filas (`grid-rows-[auto_auto]`)
|
|
127
|
+
- Columnas adaptativas: 1 columna por defecto, 2 cuando hay `CardAction` (`has-data-[slot=card-action]:grid-cols-[1fr_auto]`)
|
|
128
|
+
- Container query: `@container/card-header` para responsive interno
|
|
129
|
+
- Padding inferior automático: `[.border-b]:pb-6` cuando se agrega clase `.border-b`
|
|
130
|
+
|
|
131
|
+
### CardTitle
|
|
132
|
+
|
|
133
|
+
Título principal de la card.
|
|
134
|
+
|
|
135
|
+
#### Props
|
|
136
|
+
|
|
137
|
+
| Prop | Tipo | Descripción |
|
|
138
|
+
| ----------- | ----------- | ---------------------- |
|
|
139
|
+
| `className` | `string` | Clases CSS adicionales |
|
|
140
|
+
| `children` | `ReactNode` | Texto del título |
|
|
141
|
+
|
|
142
|
+
**Estilos default**: `leading-none font-semibold`
|
|
143
|
+
|
|
144
|
+
### CardDescription
|
|
145
|
+
|
|
146
|
+
Descripción o subtítulo de la card.
|
|
147
|
+
|
|
148
|
+
#### Props
|
|
149
|
+
|
|
150
|
+
| Prop | Tipo | Descripción |
|
|
151
|
+
| ----------- | ----------- | ---------------------- |
|
|
152
|
+
| `className` | `string` | Clases CSS adicionales |
|
|
153
|
+
| `children` | `ReactNode` | Texto de descripción |
|
|
154
|
+
|
|
155
|
+
**Estilos default**: `text-muted-foreground text-sm`
|
|
156
|
+
|
|
157
|
+
### CardAction
|
|
158
|
+
|
|
159
|
+
Botón o acción alineada a la derecha del header.
|
|
160
|
+
|
|
161
|
+
#### Props
|
|
162
|
+
|
|
163
|
+
| Prop | Tipo | Descripción |
|
|
164
|
+
| ----------- | ----------- | ---------------------- |
|
|
165
|
+
| `className` | `string` | Clases CSS adicionales |
|
|
166
|
+
| `children` | `ReactNode` | Usualmente un Button |
|
|
167
|
+
|
|
168
|
+
**Posicionamiento**:
|
|
169
|
+
|
|
170
|
+
- `col-start-2 row-span-2 row-start-1`: Ocupa columna 2, ambas filas
|
|
171
|
+
- `self-start justify-self-end`: Alineado superior-derecha
|
|
172
|
+
|
|
173
|
+
### CardContent
|
|
174
|
+
|
|
175
|
+
Contenido principal de la card.
|
|
176
|
+
|
|
177
|
+
#### Props
|
|
178
|
+
|
|
179
|
+
| Prop | Tipo | Descripción |
|
|
180
|
+
| ----------- | ----------- | ---------------------- |
|
|
181
|
+
| `className` | `string` | Clases CSS adicionales |
|
|
182
|
+
| `children` | `ReactNode` | Contenido principal |
|
|
183
|
+
|
|
184
|
+
**Estilos default**: `px-6` (padding horizontal matching header/footer)
|
|
185
|
+
|
|
186
|
+
### CardFooter
|
|
187
|
+
|
|
188
|
+
Pie de la card para acciones o información adicional.
|
|
189
|
+
|
|
190
|
+
#### Props
|
|
191
|
+
|
|
192
|
+
| Prop | Tipo | Descripción |
|
|
193
|
+
| ----------- | ----------- | ---------------------- |
|
|
194
|
+
| `className` | `string` | Clases CSS adicionales |
|
|
195
|
+
| `children` | `ReactNode` | Usualmente botones |
|
|
196
|
+
|
|
197
|
+
**Estilos default**:
|
|
198
|
+
|
|
199
|
+
- `flex items-center px-6`: Layout flex horizontal centrado
|
|
200
|
+
- `[.border-t]:pt-6`: Padding superior automático con clase `.border-t`
|
|
201
|
+
|
|
202
|
+
## Variantes
|
|
203
|
+
|
|
204
|
+
### Default
|
|
205
|
+
|
|
206
|
+
Card estándar con fondo blanco/oscuro según tema.
|
|
207
|
+
|
|
208
|
+
```tsx
|
|
209
|
+
<Card variant="default" className="w-[350px]">
|
|
210
|
+
<CardHeader>
|
|
211
|
+
<CardTitle>Default Card</CardTitle>
|
|
212
|
+
<CardDescription>Standard card appearance</CardDescription>
|
|
213
|
+
</CardHeader>
|
|
214
|
+
<CardContent>
|
|
215
|
+
<p className="text-sm">Standard styling with default colors.</p>
|
|
216
|
+
</CardContent>
|
|
217
|
+
</Card>
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
**Colores**: `bg-card text-card-foreground`
|
|
221
|
+
|
|
222
|
+
### Primary
|
|
223
|
+
|
|
224
|
+
Fondo azul claro para información importante.
|
|
225
|
+
|
|
226
|
+
```tsx
|
|
227
|
+
<Card variant="primary" className="w-[350px]">
|
|
228
|
+
<CardHeader>
|
|
229
|
+
<CardTitle>Important Information</CardTitle>
|
|
230
|
+
<CardDescription>Please read carefully</CardDescription>
|
|
231
|
+
</CardHeader>
|
|
232
|
+
<CardContent>
|
|
233
|
+
<p className="text-sm">
|
|
234
|
+
This is important information that requires attention.
|
|
235
|
+
</p>
|
|
236
|
+
</CardContent>
|
|
237
|
+
<CardFooter>
|
|
238
|
+
<Button>Acknowledge</Button>
|
|
239
|
+
</CardFooter>
|
|
240
|
+
</Card>
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
**Colores**: `bg-primary-50` con iconos y texto ajustados
|
|
244
|
+
|
|
245
|
+
### Success
|
|
246
|
+
|
|
247
|
+
Fondo verde claro para confirmaciones exitosas.
|
|
248
|
+
|
|
249
|
+
```tsx
|
|
250
|
+
<Card variant="success" className="w-[350px]">
|
|
251
|
+
<CardHeader>
|
|
252
|
+
<CardTitle>Payment Successful</CardTitle>
|
|
253
|
+
<CardDescription>Your transaction completed</CardDescription>
|
|
254
|
+
</CardHeader>
|
|
255
|
+
<CardContent>
|
|
256
|
+
<p className="text-sm">Your payment has been processed successfully.</p>
|
|
257
|
+
</CardContent>
|
|
258
|
+
<CardFooter>
|
|
259
|
+
<Button variant="outline">View Receipt</Button>
|
|
260
|
+
</CardFooter>
|
|
261
|
+
</Card>
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
**Colores**: `bg-success-50` con texto `text-success/90`
|
|
265
|
+
|
|
266
|
+
### Warning
|
|
267
|
+
|
|
268
|
+
Fondo naranja/amarillo para advertencias.
|
|
269
|
+
|
|
270
|
+
```tsx
|
|
271
|
+
<Card variant="warning" className="w-[350px]">
|
|
272
|
+
<CardHeader>
|
|
273
|
+
<CardTitle>Storage Almost Full</CardTitle>
|
|
274
|
+
<CardDescription>You're running out of space</CardDescription>
|
|
275
|
+
</CardHeader>
|
|
276
|
+
<CardContent>
|
|
277
|
+
<p className="text-sm">You've used 95% of storage. Consider upgrading.</p>
|
|
278
|
+
</CardContent>
|
|
279
|
+
<CardFooter className="gap-2">
|
|
280
|
+
<Button variant="outline" size="sm">
|
|
281
|
+
Manage
|
|
282
|
+
</Button>
|
|
283
|
+
<Button size="sm">Upgrade</Button>
|
|
284
|
+
</CardFooter>
|
|
285
|
+
</Card>
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
**Colores**: `bg-warning-50` con texto `text-warning/90`
|
|
289
|
+
|
|
290
|
+
### Destructive
|
|
291
|
+
|
|
292
|
+
Fondo rojo claro para acciones destructivas o errores.
|
|
293
|
+
|
|
294
|
+
```tsx
|
|
295
|
+
<Card variant="destructive" className="w-[350px]">
|
|
296
|
+
<CardHeader>
|
|
297
|
+
<CardTitle>Delete Account</CardTitle>
|
|
298
|
+
<CardDescription>This action cannot be undone</CardDescription>
|
|
299
|
+
</CardHeader>
|
|
300
|
+
<CardContent>
|
|
301
|
+
<p className="text-sm">
|
|
302
|
+
Permanently delete your account? All data will be lost.
|
|
303
|
+
</p>
|
|
304
|
+
</CardContent>
|
|
305
|
+
<CardFooter className="gap-2">
|
|
306
|
+
<Button variant="outline" size="sm">
|
|
307
|
+
Cancel
|
|
308
|
+
</Button>
|
|
309
|
+
<Button variant="destructive" size="sm">
|
|
310
|
+
Delete
|
|
311
|
+
</Button>
|
|
312
|
+
</CardFooter>
|
|
313
|
+
</Card>
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
**Colores**: `bg-destructive-50` con texto `text-destructive/90`
|
|
317
|
+
|
|
318
|
+
### Muted
|
|
319
|
+
|
|
320
|
+
Fondo gris claro para información secundaria.
|
|
321
|
+
|
|
322
|
+
```tsx
|
|
323
|
+
<Card variant="muted" className="w-full">
|
|
324
|
+
<CardHeader>
|
|
325
|
+
<CardTitle>Muted Card</CardTitle>
|
|
326
|
+
<CardDescription>Less prominent information</CardDescription>
|
|
327
|
+
</CardHeader>
|
|
328
|
+
<CardContent>
|
|
329
|
+
<p className="text-sm">
|
|
330
|
+
Information that doesn't require immediate attention.
|
|
331
|
+
</p>
|
|
332
|
+
</CardContent>
|
|
333
|
+
</Card>
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
**Colores**: `bg-muted` con texto `text-muted/90`
|
|
337
|
+
|
|
338
|
+
**Colores**: `bg-muted` con texto `text-muted/90`
|
|
339
|
+
|
|
340
|
+
## Patrones Avanzados
|
|
341
|
+
|
|
342
|
+
### Formulario de Login
|
|
343
|
+
|
|
344
|
+
Card completa con form, inputs y múltiples acciones.
|
|
345
|
+
|
|
346
|
+
```tsx
|
|
347
|
+
import { Input } from "@adamosuiteservices/ui/input";
|
|
348
|
+
import { Label } from "@adamosuiteservices/ui/label";
|
|
349
|
+
|
|
350
|
+
<Card className="w-full max-w-sm">
|
|
351
|
+
<CardHeader>
|
|
352
|
+
<CardTitle>Login to your account</CardTitle>
|
|
353
|
+
<CardDescription>Enter your email below to login</CardDescription>
|
|
354
|
+
<CardAction>
|
|
355
|
+
<Button variant="link">Sign Up</Button>
|
|
356
|
+
</CardAction>
|
|
357
|
+
</CardHeader>
|
|
358
|
+
<CardContent>
|
|
359
|
+
<form>
|
|
360
|
+
<div className="flex flex-col gap-6">
|
|
361
|
+
<div className="grid gap-2">
|
|
362
|
+
<Label htmlFor="email">Email</Label>
|
|
363
|
+
<Input id="email" type="email" placeholder="m@example.com" required />
|
|
364
|
+
</div>
|
|
365
|
+
<div className="grid gap-2">
|
|
366
|
+
<div className="flex items-center">
|
|
367
|
+
<Label htmlFor="password">Password</Label>
|
|
368
|
+
<a
|
|
369
|
+
href="#"
|
|
370
|
+
className="ml-auto text-sm underline-offset-4 hover:underline"
|
|
371
|
+
>
|
|
372
|
+
Forgot password?
|
|
373
|
+
</a>
|
|
374
|
+
</div>
|
|
375
|
+
<Input id="password" type="password" required />
|
|
376
|
+
</div>
|
|
377
|
+
</div>
|
|
378
|
+
</form>
|
|
379
|
+
</CardContent>
|
|
380
|
+
<CardFooter className="flex-col gap-2">
|
|
381
|
+
<Button type="submit" className="w-full">
|
|
382
|
+
Login
|
|
383
|
+
</Button>
|
|
384
|
+
<Button variant="outline" className="w-full">
|
|
385
|
+
Login with Google
|
|
386
|
+
</Button>
|
|
387
|
+
</CardFooter>
|
|
388
|
+
</Card>;
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
### Perfil de Usuario
|
|
392
|
+
|
|
393
|
+
Card con avatar, stats y acciones múltiples.
|
|
394
|
+
|
|
395
|
+
```tsx
|
|
396
|
+
import { Avatar } from "@adamosuiteservices/ui/avatar";
|
|
397
|
+
import {
|
|
398
|
+
HeartIcon,
|
|
399
|
+
StarIcon,
|
|
400
|
+
ShareIcon,
|
|
401
|
+
ExternalLinkIcon,
|
|
402
|
+
UserIcon,
|
|
403
|
+
} from "lucide-react";
|
|
404
|
+
|
|
405
|
+
<Card className="w-[380px]">
|
|
406
|
+
<CardHeader>
|
|
407
|
+
<div className="flex items-center space-x-4">
|
|
408
|
+
<Avatar className="h-12 w-12">
|
|
409
|
+
<UserIcon />
|
|
410
|
+
</Avatar>
|
|
411
|
+
<div>
|
|
412
|
+
<CardTitle>Sofia Davis</CardTitle>
|
|
413
|
+
<CardDescription>Product Designer</CardDescription>
|
|
414
|
+
</div>
|
|
415
|
+
</div>
|
|
416
|
+
<CardAction>
|
|
417
|
+
<Button variant="outline" size="sm">
|
|
418
|
+
Follow
|
|
419
|
+
</Button>
|
|
420
|
+
</CardAction>
|
|
421
|
+
</CardHeader>
|
|
422
|
+
<CardContent>
|
|
423
|
+
<div className="text-sm text-muted-foreground">
|
|
424
|
+
Passionate about creating beautiful user experiences.
|
|
425
|
+
</div>
|
|
426
|
+
</CardContent>
|
|
427
|
+
<CardFooter className="flex justify-between">
|
|
428
|
+
<div className="flex space-x-4 text-sm text-muted-foreground">
|
|
429
|
+
<div className="flex items-center">
|
|
430
|
+
<HeartIcon className="mr-1 h-3 w-3" />
|
|
431
|
+
256
|
|
432
|
+
</div>
|
|
433
|
+
<div className="flex items-center">
|
|
434
|
+
<StarIcon className="mr-1 h-3 w-3" />
|
|
435
|
+
98
|
|
436
|
+
</div>
|
|
437
|
+
</div>
|
|
438
|
+
<div className="flex space-x-1">
|
|
439
|
+
<Button variant="ghost" size="sm">
|
|
440
|
+
<ShareIcon />
|
|
441
|
+
</Button>
|
|
442
|
+
<Button variant="ghost" size="sm">
|
|
443
|
+
<ExternalLinkIcon />
|
|
444
|
+
</Button>
|
|
445
|
+
</div>
|
|
446
|
+
</CardFooter>
|
|
447
|
+
</Card>;
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
### Card de Producto
|
|
451
|
+
|
|
452
|
+
E-commerce card con imagen, badge, precio y acciones.
|
|
453
|
+
|
|
454
|
+
```tsx
|
|
455
|
+
import { Badge } from "@adamosuiteservices/ui/badge";
|
|
456
|
+
import { StarIcon, CreditCardIcon, HeartIcon } from "lucide-react";
|
|
457
|
+
|
|
458
|
+
<Card className="w-[350px]">
|
|
459
|
+
<CardHeader>
|
|
460
|
+
<div className="aspect-square rounded-md bg-muted"></div>
|
|
461
|
+
</CardHeader>
|
|
462
|
+
<CardContent>
|
|
463
|
+
<div className="space-y-2">
|
|
464
|
+
<Badge variant="secondary">Electronics</Badge>
|
|
465
|
+
<CardTitle>Wireless Headphones</CardTitle>
|
|
466
|
+
<CardDescription>
|
|
467
|
+
Premium wireless headphones with noise cancellation.
|
|
468
|
+
</CardDescription>
|
|
469
|
+
<div className="flex items-center justify-between">
|
|
470
|
+
<div className="text-2xl font-bold">$299.99</div>
|
|
471
|
+
<div className="flex items-center text-sm text-muted-foreground">
|
|
472
|
+
<StarIcon className="mr-1 h-4 w-4 fill-current" />
|
|
473
|
+
4.5 (128)
|
|
474
|
+
</div>
|
|
475
|
+
</div>
|
|
476
|
+
</div>
|
|
477
|
+
</CardContent>
|
|
478
|
+
<CardFooter className="flex gap-2">
|
|
479
|
+
<Button className="flex-1">
|
|
480
|
+
<CreditCardIcon />
|
|
481
|
+
Add to Cart
|
|
482
|
+
</Button>
|
|
483
|
+
<Button variant="outline" size="sm">
|
|
484
|
+
<HeartIcon />
|
|
485
|
+
</Button>
|
|
486
|
+
</CardFooter>
|
|
487
|
+
</Card>;
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
### Stats Cards (Dashboard)
|
|
491
|
+
|
|
492
|
+
Grid de cards para métricas con iconos y tendencias.
|
|
493
|
+
|
|
494
|
+
```tsx
|
|
495
|
+
import { DollarSignIcon, UserIcon, CreditCardIcon } from "lucide-react";
|
|
496
|
+
|
|
497
|
+
<div className="grid gap-4 grid-cols-1 md:grid-cols-2 lg:grid-cols-4">
|
|
498
|
+
<Card>
|
|
499
|
+
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
|
500
|
+
<CardTitle className="text-sm font-medium">Total Revenue</CardTitle>
|
|
501
|
+
<DollarSignIcon className="h-4 w-4 text-muted-foreground" />
|
|
502
|
+
</CardHeader>
|
|
503
|
+
<CardContent>
|
|
504
|
+
<div className="text-2xl font-bold">$45,231.89</div>
|
|
505
|
+
<p className="text-xs text-muted-foreground">+20.1% from last month</p>
|
|
506
|
+
</CardContent>
|
|
507
|
+
</Card>
|
|
508
|
+
|
|
509
|
+
<Card>
|
|
510
|
+
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
|
511
|
+
<CardTitle className="text-sm font-medium">Subscriptions</CardTitle>
|
|
512
|
+
<UserIcon className="h-4 w-4 text-muted-foreground" />
|
|
513
|
+
</CardHeader>
|
|
514
|
+
<CardContent>
|
|
515
|
+
<div className="text-2xl font-bold">+2350</div>
|
|
516
|
+
<p className="text-xs text-muted-foreground">+180.1% from last month</p>
|
|
517
|
+
</CardContent>
|
|
518
|
+
</Card>
|
|
519
|
+
|
|
520
|
+
<Card>
|
|
521
|
+
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
|
522
|
+
<CardTitle className="text-sm font-medium">Sales</CardTitle>
|
|
523
|
+
<CreditCardIcon className="h-4 w-4 text-muted-foreground" />
|
|
524
|
+
</CardHeader>
|
|
525
|
+
<CardContent>
|
|
526
|
+
<div className="text-2xl font-bold">+12,234</div>
|
|
527
|
+
<p className="text-xs text-muted-foreground">+19% from last month</p>
|
|
528
|
+
</CardContent>
|
|
529
|
+
</Card>
|
|
530
|
+
|
|
531
|
+
<Card>
|
|
532
|
+
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
|
533
|
+
<CardTitle className="text-sm font-medium">Active Now</CardTitle>
|
|
534
|
+
<UserIcon className="h-4 w-4 text-muted-foreground" />
|
|
535
|
+
</CardHeader>
|
|
536
|
+
<CardContent>
|
|
537
|
+
<div className="text-2xl font-bold">+573</div>
|
|
538
|
+
<p className="text-xs text-muted-foreground">+201 since last hour</p>
|
|
539
|
+
</CardContent>
|
|
540
|
+
</Card>
|
|
541
|
+
</div>;
|
|
542
|
+
```
|
|
543
|
+
|
|
544
|
+
### Card de Notificaciones
|
|
545
|
+
|
|
546
|
+
Lista de notificaciones con items y acción de marcar leído.
|
|
547
|
+
|
|
548
|
+
```tsx
|
|
549
|
+
import { BellIcon, MailIcon, CheckIcon } from "lucide-react";
|
|
550
|
+
|
|
551
|
+
<Card className="w-[380px]">
|
|
552
|
+
<CardHeader>
|
|
553
|
+
<CardTitle>Notifications</CardTitle>
|
|
554
|
+
<CardDescription>You have 3 unread messages.</CardDescription>
|
|
555
|
+
</CardHeader>
|
|
556
|
+
<CardContent className="grid gap-4">
|
|
557
|
+
<div className="flex items-center space-x-4 rounded-md border p-4">
|
|
558
|
+
<BellIcon className="h-4 w-4" />
|
|
559
|
+
<div className="flex-1 space-y-1">
|
|
560
|
+
<p className="text-sm font-medium leading-none">Push Notifications</p>
|
|
561
|
+
<p className="text-sm text-muted-foreground">
|
|
562
|
+
Send notifications to device.
|
|
563
|
+
</p>
|
|
564
|
+
</div>
|
|
565
|
+
</div>
|
|
566
|
+
<div className="flex items-center space-x-4 rounded-md border p-4">
|
|
567
|
+
<MailIcon className="h-4 w-4" />
|
|
568
|
+
<div className="flex-1 space-y-1">
|
|
569
|
+
<p className="text-sm font-medium leading-none">Email Notifications</p>
|
|
570
|
+
<p className="text-sm text-muted-foreground">
|
|
571
|
+
Send notifications to email.
|
|
572
|
+
</p>
|
|
573
|
+
</div>
|
|
574
|
+
</div>
|
|
575
|
+
</CardContent>
|
|
576
|
+
<CardFooter>
|
|
577
|
+
<Button className="w-full">
|
|
578
|
+
<CheckIcon />
|
|
579
|
+
Mark all as read
|
|
580
|
+
</Button>
|
|
581
|
+
</CardFooter>
|
|
582
|
+
</Card>;
|
|
583
|
+
```
|
|
584
|
+
|
|
585
|
+
### Con Separadores (Border)
|
|
586
|
+
|
|
587
|
+
Usa `.border-b` y `.border-t` para separadores visuales.
|
|
588
|
+
|
|
589
|
+
```tsx
|
|
590
|
+
<Card className="w-[350px]">
|
|
591
|
+
<CardHeader className="border-b">
|
|
592
|
+
<CardTitle>Settings</CardTitle>
|
|
593
|
+
<CardDescription>Manage your preferences</CardDescription>
|
|
594
|
+
</CardHeader>
|
|
595
|
+
<CardContent>
|
|
596
|
+
<div className="space-y-4">{/* Settings content */}</div>
|
|
597
|
+
</CardContent>
|
|
598
|
+
<CardFooter className="border-t">
|
|
599
|
+
<Button className="w-full">Save Changes</Button>
|
|
600
|
+
</CardFooter>
|
|
601
|
+
</Card>
|
|
602
|
+
```
|
|
603
|
+
|
|
604
|
+
**Nota**: El padding se ajusta automáticamente (`pb-6` en header, `pt-6` en footer).
|
|
605
|
+
|
|
606
|
+
### Grid de Variantes
|
|
607
|
+
|
|
608
|
+
Mostrar todas las variantes en una vista comparativa.
|
|
609
|
+
|
|
610
|
+
```tsx
|
|
611
|
+
<div className="grid gap-6 grid-cols-1 md:grid-cols-2 lg:grid-cols-3">
|
|
612
|
+
<Card variant="default">
|
|
613
|
+
<CardHeader>
|
|
614
|
+
<CardTitle>Default</CardTitle>
|
|
615
|
+
<CardDescription>Standard card</CardDescription>
|
|
616
|
+
</CardHeader>
|
|
617
|
+
<CardContent>
|
|
618
|
+
<p className="text-sm">Standard styling.</p>
|
|
619
|
+
</CardContent>
|
|
620
|
+
</Card>
|
|
621
|
+
|
|
622
|
+
<Card variant="primary">
|
|
623
|
+
<CardHeader>
|
|
624
|
+
<CardTitle>Primary</CardTitle>
|
|
625
|
+
<CardDescription>Important info</CardDescription>
|
|
626
|
+
</CardHeader>
|
|
627
|
+
<CardContent>
|
|
628
|
+
<p className="text-sm">Highlight important content.</p>
|
|
629
|
+
</CardContent>
|
|
630
|
+
</Card>
|
|
631
|
+
|
|
632
|
+
<Card variant="success">
|
|
633
|
+
<CardHeader>
|
|
634
|
+
<CardTitle>Success</CardTitle>
|
|
635
|
+
<CardDescription>Success message</CardDescription>
|
|
636
|
+
</CardHeader>
|
|
637
|
+
<CardContent>
|
|
638
|
+
<p className="text-sm">Successful operations.</p>
|
|
639
|
+
</CardContent>
|
|
640
|
+
</Card>
|
|
641
|
+
|
|
642
|
+
<Card variant="warning">
|
|
643
|
+
<CardHeader>
|
|
644
|
+
<CardTitle>Warning</CardTitle>
|
|
645
|
+
<CardDescription>Caution message</CardDescription>
|
|
646
|
+
</CardHeader>
|
|
647
|
+
<CardContent>
|
|
648
|
+
<p className="text-sm">Important warnings.</p>
|
|
649
|
+
</CardContent>
|
|
650
|
+
</Card>
|
|
651
|
+
|
|
652
|
+
<Card variant="destructive">
|
|
653
|
+
<CardHeader>
|
|
654
|
+
<CardTitle>Destructive</CardTitle>
|
|
655
|
+
<CardDescription>Error or danger</CardDescription>
|
|
656
|
+
</CardHeader>
|
|
657
|
+
<CardContent>
|
|
658
|
+
<p className="text-sm">Errors or destructive actions.</p>
|
|
659
|
+
</CardContent>
|
|
660
|
+
</Card>
|
|
661
|
+
|
|
662
|
+
<Card variant="muted">
|
|
663
|
+
<CardHeader>
|
|
664
|
+
<CardTitle>Muted</CardTitle>
|
|
665
|
+
<CardDescription>Secondary info</CardDescription>
|
|
666
|
+
</CardHeader>
|
|
667
|
+
<CardContent>
|
|
668
|
+
<p className="text-sm">Less important information.</p>
|
|
669
|
+
</CardContent>
|
|
670
|
+
</Card>
|
|
671
|
+
</div>
|
|
672
|
+
```
|
|
673
|
+
|
|
674
|
+
### Header con Layout Custom
|
|
675
|
+
|
|
676
|
+
Override del grid para layouts específicos.
|
|
677
|
+
|
|
678
|
+
```tsx
|
|
679
|
+
{
|
|
680
|
+
/* Horizontal layout con custom spacing */
|
|
681
|
+
}
|
|
682
|
+
<Card className="w-[400px]">
|
|
683
|
+
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
|
684
|
+
<CardTitle className="text-sm font-medium">Custom Layout</CardTitle>
|
|
685
|
+
<Badge>New</Badge>
|
|
686
|
+
</CardHeader>
|
|
687
|
+
<CardContent>
|
|
688
|
+
<div className="text-2xl font-bold">Content</div>
|
|
689
|
+
</CardContent>
|
|
690
|
+
</Card>;
|
|
691
|
+
```
|
|
692
|
+
|
|
693
|
+
### Footer con Múltiples Acciones
|
|
694
|
+
|
|
695
|
+
Diferentes arreglos de botones.
|
|
696
|
+
|
|
697
|
+
```tsx
|
|
698
|
+
{
|
|
699
|
+
/* Botones horizontales con gap */
|
|
700
|
+
}
|
|
701
|
+
<Card>
|
|
702
|
+
<CardHeader>
|
|
703
|
+
<CardTitle>Confirm Action</CardTitle>
|
|
704
|
+
</CardHeader>
|
|
705
|
+
<CardContent>
|
|
706
|
+
<p>Are you sure?</p>
|
|
707
|
+
</CardContent>
|
|
708
|
+
<CardFooter className="gap-2">
|
|
709
|
+
<Button variant="outline" size="sm">
|
|
710
|
+
Cancel
|
|
711
|
+
</Button>
|
|
712
|
+
<Button size="sm">Confirm</Button>
|
|
713
|
+
</CardFooter>
|
|
714
|
+
</Card>;
|
|
715
|
+
|
|
716
|
+
{
|
|
717
|
+
/* Botones apilados verticalmente */
|
|
718
|
+
}
|
|
719
|
+
<Card>
|
|
720
|
+
<CardHeader>
|
|
721
|
+
<CardTitle>Choose Option</CardTitle>
|
|
722
|
+
</CardHeader>
|
|
723
|
+
<CardContent>
|
|
724
|
+
<p>Select an action:</p>
|
|
725
|
+
</CardContent>
|
|
726
|
+
<CardFooter className="flex-col gap-2">
|
|
727
|
+
<Button className="w-full">Primary Action</Button>
|
|
728
|
+
<Button variant="outline" className="w-full">
|
|
729
|
+
Secondary
|
|
730
|
+
</Button>
|
|
731
|
+
</CardFooter>
|
|
732
|
+
</Card>;
|
|
733
|
+
|
|
734
|
+
{
|
|
735
|
+
/* Acciones distribuidas */
|
|
736
|
+
}
|
|
737
|
+
<Card>
|
|
738
|
+
<CardHeader>
|
|
739
|
+
<CardTitle>Actions</CardTitle>
|
|
740
|
+
</CardHeader>
|
|
741
|
+
<CardContent>
|
|
742
|
+
<p>Multiple actions available.</p>
|
|
743
|
+
</CardContent>
|
|
744
|
+
<CardFooter className="justify-between">
|
|
745
|
+
<Button variant="outline" size="sm">
|
|
746
|
+
Cancel
|
|
747
|
+
</Button>
|
|
748
|
+
<div className="flex gap-2">
|
|
749
|
+
<Button variant="outline" size="sm">
|
|
750
|
+
Save Draft
|
|
751
|
+
</Button>
|
|
752
|
+
<Button size="sm">Publish</Button>
|
|
753
|
+
</div>
|
|
754
|
+
</CardFooter>
|
|
755
|
+
</Card>;
|
|
756
|
+
```
|
|
757
|
+
|
|
758
|
+
## Casos de Uso Comunes
|
|
759
|
+
|
|
760
|
+
### Authentication Forms
|
|
761
|
+
|
|
762
|
+
```tsx
|
|
763
|
+
<Card className="w-full max-w-md">
|
|
764
|
+
<CardHeader>
|
|
765
|
+
<CardTitle>Create Account</CardTitle>
|
|
766
|
+
<CardDescription>Sign up to get started</CardDescription>
|
|
767
|
+
</CardHeader>
|
|
768
|
+
<CardContent className="space-y-4">
|
|
769
|
+
<Input type="text" placeholder="Full Name" />
|
|
770
|
+
<Input type="email" placeholder="Email" />
|
|
771
|
+
<Input type="password" placeholder="Password" />
|
|
772
|
+
</CardContent>
|
|
773
|
+
<CardFooter>
|
|
774
|
+
<Button className="w-full">Create Account</Button>
|
|
775
|
+
</CardFooter>
|
|
776
|
+
</Card>
|
|
777
|
+
```
|
|
778
|
+
|
|
779
|
+
### Dashboard Widgets
|
|
780
|
+
|
|
781
|
+
```tsx
|
|
782
|
+
<Card>
|
|
783
|
+
<CardHeader>
|
|
784
|
+
<CardTitle>Recent Activity</CardTitle>
|
|
785
|
+
<CardDescription>Your latest actions</CardDescription>
|
|
786
|
+
<CardAction>
|
|
787
|
+
<Button variant="ghost" size="sm">
|
|
788
|
+
View All
|
|
789
|
+
</Button>
|
|
790
|
+
</CardAction>
|
|
791
|
+
</CardHeader>
|
|
792
|
+
<CardContent>{/* Activity list */}</CardContent>
|
|
793
|
+
</Card>
|
|
794
|
+
```
|
|
795
|
+
|
|
796
|
+
### Settings Panels
|
|
797
|
+
|
|
798
|
+
```tsx
|
|
799
|
+
<Card className="border-b">
|
|
800
|
+
<CardHeader>
|
|
801
|
+
<CardTitle>Account Settings</CardTitle>
|
|
802
|
+
<CardDescription>Manage your account preferences</CardDescription>
|
|
803
|
+
</CardHeader>
|
|
804
|
+
<CardContent className="space-y-4">{/* Settings options */}</CardContent>
|
|
805
|
+
<CardFooter className="border-t">
|
|
806
|
+
<Button>Save Changes</Button>
|
|
807
|
+
</CardFooter>
|
|
808
|
+
</Card>
|
|
809
|
+
```
|
|
810
|
+
|
|
811
|
+
### Pricing Cards
|
|
812
|
+
|
|
813
|
+
```tsx
|
|
814
|
+
<div className="grid gap-4 md:grid-cols-3">
|
|
815
|
+
<Card>
|
|
816
|
+
<CardHeader>
|
|
817
|
+
<CardTitle>Basic</CardTitle>
|
|
818
|
+
<CardDescription>For individuals</CardDescription>
|
|
819
|
+
</CardHeader>
|
|
820
|
+
<CardContent>
|
|
821
|
+
<div className="text-3xl font-bold">$9/mo</div>
|
|
822
|
+
<ul className="mt-4 space-y-2 text-sm">
|
|
823
|
+
<li>✓ Feature 1</li>
|
|
824
|
+
<li>✓ Feature 2</li>
|
|
825
|
+
</ul>
|
|
826
|
+
</CardContent>
|
|
827
|
+
<CardFooter>
|
|
828
|
+
<Button variant="outline" className="w-full">
|
|
829
|
+
Choose Plan
|
|
830
|
+
</Button>
|
|
831
|
+
</CardFooter>
|
|
832
|
+
</Card>
|
|
833
|
+
{/* More pricing tiers */}
|
|
834
|
+
</div>
|
|
835
|
+
```
|
|
836
|
+
|
|
837
|
+
### Status/Alert Cards
|
|
838
|
+
|
|
839
|
+
```tsx
|
|
840
|
+
<Card variant="warning">
|
|
841
|
+
<CardHeader>
|
|
842
|
+
<CardTitle>Action Required</CardTitle>
|
|
843
|
+
<CardDescription>Your subscription expires soon</CardDescription>
|
|
844
|
+
</CardHeader>
|
|
845
|
+
<CardContent>
|
|
846
|
+
<p className="text-sm">
|
|
847
|
+
Renew your subscription to continue accessing premium features.
|
|
848
|
+
</p>
|
|
849
|
+
</CardContent>
|
|
850
|
+
<CardFooter>
|
|
851
|
+
<Button>Renew Now</Button>
|
|
852
|
+
</CardFooter>
|
|
853
|
+
</Card>
|
|
854
|
+
```
|
|
855
|
+
|
|
856
|
+
## Mejores Prácticas
|
|
857
|
+
|
|
858
|
+
### Usa Anchos Fijos para Consistencia
|
|
859
|
+
|
|
860
|
+
```tsx
|
|
861
|
+
{
|
|
862
|
+
/* ✅ Correcto - Ancho consistente */
|
|
863
|
+
}
|
|
864
|
+
<Card className="w-[350px]">
|
|
865
|
+
<CardContent>Consistent width</CardContent>
|
|
866
|
+
</Card>;
|
|
867
|
+
|
|
868
|
+
{
|
|
869
|
+
/* ✅ También correcto - max-w para responsive */
|
|
870
|
+
}
|
|
871
|
+
<Card className="w-full max-w-md">
|
|
872
|
+
<CardContent>Responsive width</CardContent>
|
|
873
|
+
</Card>;
|
|
874
|
+
|
|
875
|
+
{
|
|
876
|
+
/* ❌ Evitar - Sin ancho puede expandirse inesperadamente */
|
|
877
|
+
}
|
|
878
|
+
<Card>
|
|
879
|
+
<CardContent>No width constraint</CardContent>
|
|
880
|
+
</Card>;
|
|
881
|
+
```
|
|
882
|
+
|
|
883
|
+
### Variantes Semánticas
|
|
884
|
+
|
|
885
|
+
```tsx
|
|
886
|
+
{/* ✅ Correcto - Variante según significado */}
|
|
887
|
+
<Card variant="success">
|
|
888
|
+
<CardContent>Payment processed!</CardContent>
|
|
889
|
+
</Card>
|
|
890
|
+
|
|
891
|
+
<Card variant="destructive">
|
|
892
|
+
<CardContent>Error occurred</CardContent>
|
|
893
|
+
</Card>
|
|
894
|
+
|
|
895
|
+
{/* ❌ Incorrecto - Variante no semántica */}
|
|
896
|
+
<Card variant="success">
|
|
897
|
+
<CardContent>Error occurred</CardContent> {/* Confuso */}
|
|
898
|
+
</Card>
|
|
899
|
+
```
|
|
900
|
+
|
|
901
|
+
### Estructura de Header Completa
|
|
902
|
+
|
|
903
|
+
```tsx
|
|
904
|
+
{
|
|
905
|
+
/* ✅ Correcto - Título + Descripción */
|
|
906
|
+
}
|
|
907
|
+
<CardHeader>
|
|
908
|
+
<CardTitle>Title</CardTitle>
|
|
909
|
+
<CardDescription>Description</CardDescription>
|
|
910
|
+
</CardHeader>;
|
|
911
|
+
|
|
912
|
+
{
|
|
913
|
+
/* ⚠️ Aceptable - Solo título */
|
|
914
|
+
}
|
|
915
|
+
<CardHeader>
|
|
916
|
+
<CardTitle>Title Only</CardTitle>
|
|
917
|
+
</CardHeader>;
|
|
918
|
+
|
|
919
|
+
{
|
|
920
|
+
/* ❌ Evitar - Solo descripción sin título */
|
|
921
|
+
}
|
|
922
|
+
<CardHeader>
|
|
923
|
+
<CardDescription>No title</CardDescription>
|
|
924
|
+
</CardHeader>;
|
|
925
|
+
```
|
|
926
|
+
|
|
927
|
+
### CardAction Solo en CardHeader
|
|
928
|
+
|
|
929
|
+
```tsx
|
|
930
|
+
{
|
|
931
|
+
/* ✅ Correcto - CardAction dentro de CardHeader */
|
|
932
|
+
}
|
|
933
|
+
<CardHeader>
|
|
934
|
+
<CardTitle>Title</CardTitle>
|
|
935
|
+
<CardDescription>Description</CardDescription>
|
|
936
|
+
<CardAction>
|
|
937
|
+
<Button size="sm">Action</Button>
|
|
938
|
+
</CardAction>
|
|
939
|
+
</CardHeader>;
|
|
940
|
+
|
|
941
|
+
{
|
|
942
|
+
/* ❌ Incorrecto - CardAction fuera de CardHeader */
|
|
943
|
+
}
|
|
944
|
+
<Card>
|
|
945
|
+
<CardTitle>Title</CardTitle>
|
|
946
|
+
<CardAction>
|
|
947
|
+
<Button>Won't position correctly</Button>
|
|
948
|
+
</CardAction>
|
|
949
|
+
</Card>;
|
|
950
|
+
```
|
|
951
|
+
|
|
952
|
+
### Footer Flex para Múltiples Botones
|
|
953
|
+
|
|
954
|
+
```tsx
|
|
955
|
+
{
|
|
956
|
+
/* ✅ Correcto - Gap entre botones */
|
|
957
|
+
}
|
|
958
|
+
<CardFooter className="gap-2">
|
|
959
|
+
<Button variant="outline">Cancel</Button>
|
|
960
|
+
<Button>Confirm</Button>
|
|
961
|
+
</CardFooter>;
|
|
962
|
+
|
|
963
|
+
{
|
|
964
|
+
/* ✅ Correcto - Full width individual */
|
|
965
|
+
}
|
|
966
|
+
<CardFooter className="flex-col gap-2">
|
|
967
|
+
<Button className="w-full">Primary</Button>
|
|
968
|
+
<Button variant="outline" className="w-full">
|
|
969
|
+
Secondary
|
|
970
|
+
</Button>
|
|
971
|
+
</CardFooter>;
|
|
972
|
+
|
|
973
|
+
{
|
|
974
|
+
/* ❌ Evitar - Sin gap entre botones */
|
|
975
|
+
}
|
|
976
|
+
<CardFooter>
|
|
977
|
+
<Button>Button1</Button>
|
|
978
|
+
<Button>Button2</Button> {/* Se pegan */}
|
|
979
|
+
</CardFooter>;
|
|
980
|
+
```
|
|
981
|
+
|
|
982
|
+
### Bordes Opcionales
|
|
983
|
+
|
|
984
|
+
```tsx
|
|
985
|
+
{
|
|
986
|
+
/* ✅ Correcto - Border con padding automático */
|
|
987
|
+
}
|
|
988
|
+
<Card>
|
|
989
|
+
<CardHeader className="border-b">
|
|
990
|
+
<CardTitle>Title</CardTitle>
|
|
991
|
+
</CardHeader>
|
|
992
|
+
<CardContent>Content</CardContent>
|
|
993
|
+
<CardFooter className="border-t">
|
|
994
|
+
<Button>Action</Button>
|
|
995
|
+
</CardFooter>
|
|
996
|
+
</Card>;
|
|
997
|
+
|
|
998
|
+
{
|
|
999
|
+
/* ❌ Evitar - Border sin la clase en header/footer */
|
|
1000
|
+
}
|
|
1001
|
+
<Card className="border-b">
|
|
1002
|
+
{" "}
|
|
1003
|
+
{/* No aplica padding correcto */}
|
|
1004
|
+
<CardHeader>
|
|
1005
|
+
<CardTitle>Title</CardTitle>
|
|
1006
|
+
</CardHeader>
|
|
1007
|
+
</Card>;
|
|
1008
|
+
```
|
|
1009
|
+
|
|
1010
|
+
### Grid en Stats Cards
|
|
1011
|
+
|
|
1012
|
+
```tsx
|
|
1013
|
+
{
|
|
1014
|
+
/* ✅ Correcto - Override spacing cuando es necesario */
|
|
1015
|
+
}
|
|
1016
|
+
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
|
1017
|
+
<CardTitle className="text-sm font-medium">Stat</CardTitle>
|
|
1018
|
+
<Icon className="h-4 w-4 text-muted-foreground" />
|
|
1019
|
+
</CardHeader>;
|
|
1020
|
+
|
|
1021
|
+
{
|
|
1022
|
+
/* ❌ Incorrecto - Usar grid default con layout horizontal */
|
|
1023
|
+
}
|
|
1024
|
+
<CardHeader className="flex-row">
|
|
1025
|
+
{" "}
|
|
1026
|
+
{/* Grid sigue activo */}
|
|
1027
|
+
<CardTitle>Stat</CardTitle>
|
|
1028
|
+
<Icon />
|
|
1029
|
+
</CardHeader>;
|
|
1030
|
+
```
|
|
1031
|
+
|
|
1032
|
+
## Notas de Implementación
|
|
1033
|
+
|
|
1034
|
+
- **Basado en CVA**: Usa `class-variance-authority` para variantes de color
|
|
1035
|
+
- **Data Slots**: Cada componente tiene `data-slot` para CSS targeting específico (`data-slot="card"`, `data-slot="card-header"`, etc.)
|
|
1036
|
+
- **Grid Automático**: CardHeader usa `has-data-[slot=card-action]:grid-cols-[1fr_auto]` para detectar CardAction y ajustar layout
|
|
1037
|
+
- **Container Queries**: CardHeader tiene `@container/card-header` para responsive interno (requiere Tailwind CSS container queries)
|
|
1038
|
+
- **Spacing Consistente**: `gap-6` entre secciones (header, content, footer), `px-6` horizontal en todas las secciones
|
|
1039
|
+
- **Padding Condicional**: `.border-b` y `.border-t` triggers automáticos para `pb-6` y `pt-6` respectivamente
|
|
1040
|
+
- **Variantes de Color**: Cada variante ajusta `bg-*-50` y `text-*-foreground`, con ajustes para iconos SVG (`[&>svg]:text-current`)
|
|
1041
|
+
- **Rounded Corners**: `rounded-xl` por defecto (12px)
|
|
1042
|
+
- **Shadow**: `shadow-sm` para elevación sutil
|
|
1043
|
+
- **Flex Column**: Card root usa `flex flex-col gap-6` para layout vertical automático
|
|
1044
|
+
|
|
1045
|
+
## Accesibilidad
|
|
1046
|
+
|
|
1047
|
+
### Estructura Semántica
|
|
1048
|
+
|
|
1049
|
+
Cards usan `<div>` por defecto, pero considera añadir roles ARIA cuando sea apropiado.
|
|
1050
|
+
|
|
1051
|
+
```tsx
|
|
1052
|
+
{
|
|
1053
|
+
/* Para cards interactivas */
|
|
1054
|
+
}
|
|
1055
|
+
<Card role="article" aria-labelledby="card-title">
|
|
1056
|
+
<CardHeader>
|
|
1057
|
+
<CardTitle id="card-title">Article Title</CardTitle>
|
|
1058
|
+
</CardHeader>
|
|
1059
|
+
<CardContent>Content</CardContent>
|
|
1060
|
+
</Card>;
|
|
1061
|
+
|
|
1062
|
+
{
|
|
1063
|
+
/* Para cards clickeables */
|
|
1064
|
+
}
|
|
1065
|
+
<Card
|
|
1066
|
+
role="button"
|
|
1067
|
+
tabIndex={0}
|
|
1068
|
+
onClick={handleClick}
|
|
1069
|
+
onKeyDown={(e) => e.key === "Enter" && handleClick()}
|
|
1070
|
+
>
|
|
1071
|
+
<CardContent>Clickable card</CardContent>
|
|
1072
|
+
</Card>;
|
|
1073
|
+
```
|
|
1074
|
+
|
|
1075
|
+
### Labels para CardAction
|
|
1076
|
+
|
|
1077
|
+
```tsx
|
|
1078
|
+
{
|
|
1079
|
+
/* ✅ Correcto - aria-label descriptiva */
|
|
1080
|
+
}
|
|
1081
|
+
<CardAction>
|
|
1082
|
+
<Button variant="outline" size="sm" aria-label="More options">
|
|
1083
|
+
<MoreHorizontalIcon />
|
|
1084
|
+
</Button>
|
|
1085
|
+
</CardAction>;
|
|
1086
|
+
|
|
1087
|
+
{
|
|
1088
|
+
/* ❌ Incorrecto - Sin label para icono solo */
|
|
1089
|
+
}
|
|
1090
|
+
<CardAction>
|
|
1091
|
+
<Button variant="outline" size="sm">
|
|
1092
|
+
<MoreHorizontalIcon />
|
|
1093
|
+
</Button>
|
|
1094
|
+
</CardAction>;
|
|
1095
|
+
```
|
|
1096
|
+
|
|
1097
|
+
### Formularios Accesibles
|
|
1098
|
+
|
|
1099
|
+
```tsx
|
|
1100
|
+
{
|
|
1101
|
+
/* ✅ Correcto - Labels asociadas */
|
|
1102
|
+
}
|
|
1103
|
+
<CardContent>
|
|
1104
|
+
<div className="space-y-4">
|
|
1105
|
+
<div className="grid gap-2">
|
|
1106
|
+
<Label htmlFor="email">Email</Label>
|
|
1107
|
+
<Input id="email" type="email" />
|
|
1108
|
+
</div>
|
|
1109
|
+
</div>
|
|
1110
|
+
</CardContent>;
|
|
1111
|
+
```
|
|
1112
|
+
|
|
1113
|
+
### Focus Management
|
|
1114
|
+
|
|
1115
|
+
Cards no son focuseables por defecto. Si necesitas interactividad:
|
|
1116
|
+
|
|
1117
|
+
```tsx
|
|
1118
|
+
{
|
|
1119
|
+
/* Para cards clickeables */
|
|
1120
|
+
}
|
|
1121
|
+
<Card
|
|
1122
|
+
tabIndex={0}
|
|
1123
|
+
role="button"
|
|
1124
|
+
className="cursor-pointer hover:shadow-md transition-shadow focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
|
|
1125
|
+
onClick={handleClick}
|
|
1126
|
+
>
|
|
1127
|
+
<CardContent>Interactive card</CardContent>
|
|
1128
|
+
</Card>;
|
|
1129
|
+
```
|
|
1130
|
+
|
|
1131
|
+
## Troubleshooting
|
|
1132
|
+
|
|
1133
|
+
### CardAction No Se Alinea a la Derecha
|
|
1134
|
+
|
|
1135
|
+
**Problema**: CardAction no aparece en la posición correcta.
|
|
1136
|
+
|
|
1137
|
+
**Solución**:
|
|
1138
|
+
|
|
1139
|
+
```tsx
|
|
1140
|
+
// ❌ Problema - CardAction fuera de CardHeader
|
|
1141
|
+
<Card>
|
|
1142
|
+
<CardTitle>Title</CardTitle>
|
|
1143
|
+
<CardAction>
|
|
1144
|
+
<Button>Action</Button>
|
|
1145
|
+
</CardAction>
|
|
1146
|
+
</Card>
|
|
1147
|
+
|
|
1148
|
+
// ✅ Solución - CardAction dentro de CardHeader
|
|
1149
|
+
<Card>
|
|
1150
|
+
<CardHeader>
|
|
1151
|
+
<CardTitle>Title</CardTitle>
|
|
1152
|
+
<CardDescription>Description</CardDescription>
|
|
1153
|
+
<CardAction>
|
|
1154
|
+
<Button>Action</Button>
|
|
1155
|
+
</CardAction>
|
|
1156
|
+
</CardHeader>
|
|
1157
|
+
</Card>
|
|
1158
|
+
```
|
|
1159
|
+
|
|
1160
|
+
### Gap Excesivo entre Secciones
|
|
1161
|
+
|
|
1162
|
+
**Problema**: Mucho espacio entre header/content/footer.
|
|
1163
|
+
|
|
1164
|
+
**Solución**:
|
|
1165
|
+
|
|
1166
|
+
```tsx
|
|
1167
|
+
// ✅ El gap-6 es intencional, pero puedes reducirlo
|
|
1168
|
+
<Card className="gap-4"> {/* Override gap-6 */}
|
|
1169
|
+
<CardHeader>...</CardHeader>
|
|
1170
|
+
<CardContent>...</CardContent>
|
|
1171
|
+
</Card>
|
|
1172
|
+
|
|
1173
|
+
// O eliminar gap completamente
|
|
1174
|
+
<Card className="gap-0">
|
|
1175
|
+
<CardHeader>...</CardHeader>
|
|
1176
|
+
<CardContent>...</CardContent>
|
|
1177
|
+
</Card>
|
|
1178
|
+
```
|
|
1179
|
+
|
|
1180
|
+
### Bordes No Muestran Padding
|
|
1181
|
+
|
|
1182
|
+
**Problema**: `.border-b` o `.border-t` no agregan padding.
|
|
1183
|
+
|
|
1184
|
+
**Solución**:
|
|
1185
|
+
|
|
1186
|
+
```tsx
|
|
1187
|
+
// ❌ Problema - Border en elemento incorrecto
|
|
1188
|
+
<Card className="border-b">
|
|
1189
|
+
<CardHeader>...</CardHeader>
|
|
1190
|
+
</Card>
|
|
1191
|
+
|
|
1192
|
+
// ✅ Solución - Border en CardHeader o CardFooter
|
|
1193
|
+
<Card>
|
|
1194
|
+
<CardHeader className="border-b">...</CardHeader>
|
|
1195
|
+
<CardContent>...</CardContent>
|
|
1196
|
+
<CardFooter className="border-t">...</CardFooter>
|
|
1197
|
+
</Card>
|
|
1198
|
+
```
|
|
1199
|
+
|
|
1200
|
+
### Variante No Cambia Color
|
|
1201
|
+
|
|
1202
|
+
**Problema**: Variante primary/success/etc no aplica colores.
|
|
1203
|
+
|
|
1204
|
+
**Solución**:
|
|
1205
|
+
|
|
1206
|
+
```tsx
|
|
1207
|
+
// ✅ Verifica que la prop sea en Card root
|
|
1208
|
+
<Card variant="primary"> {/* Correcto */}
|
|
1209
|
+
<CardHeader>...</CardHeader>
|
|
1210
|
+
</Card>
|
|
1211
|
+
|
|
1212
|
+
// ❌ No funciona en subcomponentes
|
|
1213
|
+
<Card>
|
|
1214
|
+
<CardHeader variant="primary"> {/* No existe esta prop */}
|
|
1215
|
+
...
|
|
1216
|
+
</CardHeader>
|
|
1217
|
+
</Card>
|
|
1218
|
+
```
|
|
1219
|
+
|
|
1220
|
+
### Stats Cards con Layout Incorrecto
|
|
1221
|
+
|
|
1222
|
+
**Problema**: Íconos y títulos no se alinean horizontalmente.
|
|
1223
|
+
|
|
1224
|
+
**Solución**:
|
|
1225
|
+
|
|
1226
|
+
```tsx
|
|
1227
|
+
// ✅ Override grid con flex
|
|
1228
|
+
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
|
1229
|
+
<CardTitle className="text-sm font-medium">Revenue</CardTitle>
|
|
1230
|
+
<DollarSignIcon className="h-4 w-4" />
|
|
1231
|
+
</CardHeader>
|
|
1232
|
+
```
|
|
1233
|
+
|
|
1234
|
+
### Footer Buttons No Se Distribuyen
|
|
1235
|
+
|
|
1236
|
+
**Problema**: Botones en footer se pegan sin espacio.
|
|
1237
|
+
|
|
1238
|
+
**Solución**:
|
|
1239
|
+
|
|
1240
|
+
```tsx
|
|
1241
|
+
// ❌ Problema - Sin gap
|
|
1242
|
+
<CardFooter>
|
|
1243
|
+
<Button>Cancel</Button>
|
|
1244
|
+
<Button>Confirm</Button>
|
|
1245
|
+
</CardFooter>
|
|
1246
|
+
|
|
1247
|
+
// ✅ Solución - Añade gap
|
|
1248
|
+
<CardFooter className="gap-2">
|
|
1249
|
+
<Button>Cancel</Button>
|
|
1250
|
+
<Button>Confirm</Button>
|
|
1251
|
+
</CardFooter>
|
|
1252
|
+
|
|
1253
|
+
// ✅ O usa justify-between
|
|
1254
|
+
<CardFooter className="justify-between">
|
|
1255
|
+
<Button>Cancel</Button>
|
|
1256
|
+
<Button>Confirm</Button>
|
|
1257
|
+
</CardFooter>
|
|
1258
|
+
```
|
|
1259
|
+
|
|
1260
|
+
## Referencias
|
|
1261
|
+
|
|
1262
|
+
- **CVA (Class Variance Authority)**: https://cva.style/docs
|
|
1263
|
+
- **shadcn/ui Card**: https://ui.shadcn.com/docs/components/card
|
|
1264
|
+
- **Tailwind Container Queries**: https://tailwindcss.com/docs/hover-focus-and-other-states#container-queries
|
|
1265
|
+
- **ARIA Article Role**: https://www.w3.org/TR/wai-aria-1.2/#article
|