Boost Your Productivity
Learn the best techniques to manage your time and code smarter, not harder.
Discover tips, tools, and tricks that help developers stay focused and efficient. From keyboard shortcuts to workflow optimizations, elevate your coding game.
1'use client';23import { Button } from '@/components/ui/button';4import { Card } from '@/components/ui/card';56export function Default() {7 return (8 <Card className="w-full max-w-sm shadow-lg transition-shadow duration-300 hover:shadow-xl">9 <Card.Header>10 <Card.Title>Boost Your Productivity</Card.Title>11 <Card.Description>12 Learn the best techniques to manage your time and code smarter, not harder.13 </Card.Description>14 </Card.Header>15 <Card.Content className="text-muted-foreground text-sm">16 <p>17 Discover tips, tools, and tricks that help developers stay focused and efficient. From18 keyboard shortcuts to workflow optimizations, elevate your coding game.19 </p>20 </Card.Content>21 <Card.Footer className="flex justify-end gap-2">22 <Button variant="secondary">Learn More</Button>23 <Button variant="ghost">Subscribe</Button>24 </Card.Footer>25 </Card>26 );27}
Instalación
Copia y pega el siguiente código en tu proyecto.
'use client';import { cva, type VariantProps } from 'class-variance-authority';import React from 'react';import { cn } from '../lib/cn';const cardVariants = cva('rounded-lg transition-all duration-200 h-full flex flex-col justify-between',{variants: {variant: {default: 'bg-card text-card-foreground border border-border shadow-sm',outline: 'bg-card text-card-foreground border-2 border-border shadow-none',ghost: 'bg-transparent text-card-foreground border-0 shadow-none',},gradient: {true: 'bg-gradient-to-br from-card to-card/80',},},defaultVariants: {variant: 'default',gradient: false,},},);const cardHeaderVariants = cva('flex flex-col space-y-1.5', {variants: {compact: {true: 'p-4',false: 'p-6',},},defaultVariants: {compact: false,},});const cardTitleVariants = cva('text-lg font-semibold leading-none tracking-tight');const cardDescriptionVariants = cva('text-sm text-muted-foreground leading-relaxed');const cardContentVariants = cva('flex-1', {variants: {compact: {true: 'p-4 pt-0',false: 'p-6 pt-0',},},defaultVariants: {compact: false,},});const cardFooterVariants = cva('flex items-center', {variants: {align: {start: 'justify-start',center: 'justify-center',end: 'justify-end',between: 'justify-between',},compact: {true: 'p-4 pt-0',false: 'p-6 pt-0',},},defaultVariants: {align: 'start',compact: false,},});interface CardPropsextends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof cardVariants> {as?: React.ElementType;}interface CardHeaderPropsextends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof cardHeaderVariants> {}interface CardTitleProps extends React.HTMLAttributes<HTMLHeadingElement> {as?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';}interface CardDescriptionProps extends React.HTMLAttributes<HTMLParagraphElement> {}interface CardContentPropsextends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof cardContentVariants> {}interface CardFooterPropsextends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof cardFooterVariants> {}const CardRoot = ({className,variant = 'default',gradient = false,as: Component = 'div',children,ref,...props}: CardProps & { ref?: React.Ref<HTMLDivElement> }) => {return (<Component ref={ref} className={cn(cardVariants({ variant, gradient }), className)} {...props}>{children}</Component>);};CardRoot.displayName = 'Card';const CardHeader = ({className,compact,children,ref,...props}: CardHeaderProps & { ref?: React.Ref<HTMLDivElement> }) => {return (<div ref={ref} className={cn(cardHeaderVariants({ compact }), className)} {...props}>{children}</div>);};CardHeader.displayName = 'CardHeader';const CardTitle = ({className,as: Component = 'h3',children,ref,...props}: CardTitleProps & { ref?: React.Ref<HTMLHeadingElement> }) => {return (<Component ref={ref} className={cn(cardTitleVariants(), className)} {...props}>{children}</Component>);};CardTitle.displayName = 'CardTitle';const CardDescription = ({className,children,ref,...props}: CardDescriptionProps & { ref?: React.Ref<HTMLParagraphElement> }) => {return (<p ref={ref} className={cn(cardDescriptionVariants(), className)} {...props}>{children}</p>);};CardDescription.displayName = 'CardDescription';const CardContent = ({className,compact,children,ref,...props}: CardContentProps & { ref?: React.Ref<HTMLDivElement> }) => {return (<div ref={ref} className={cn(cardContentVariants({ compact }), className)} {...props}>{children}</div>);};CardContent.displayName = 'CardContent';const CardFooter = ({className,align,compact,children,ref,...props}: CardFooterProps & { ref?: React.Ref<HTMLDivElement> }) => {return (<div ref={ref} className={cn(cardFooterVariants({ align, compact }), className)} {...props}>{children}</div>);};CardFooter.displayName = 'CardFooter';const Card = Object.assign(CardRoot, {Header: CardHeader,Title: CardTitle,Description: CardDescription,Content: CardContent,Footer: CardFooter,});export {Card,cardContentVariants,cardDescriptionVariants,cardFooterVariants,cardHeaderVariants,cardTitleVariants,cardVariants,};export type {CardContentProps,CardDescriptionProps,CardFooterProps,CardHeaderProps,CardProps,CardTitleProps,};
Asegúrate de actualizar las rutas de importación según la estructura de tu proyecto.
Anatomía
import { Card } from '@/components/ui/card';
<Card><Card.Header><Card.Title>Título de la tarjeta</Card.Title><Card.Description>Descripción de la tarjeta</Card.Description></Card.Header><Card.Content><p>Contenido de la tarjeta</p></Card.Content><Card.Footer><p>Pie de la tarjeta</p></Card.Footer></Card>
Variantes
Outline
Tarjetas con un borde prominente y sin sombra.
Outline Card
Clean and defined with a bold border
Outline cards work great for forms, settings, and structured content.
1'use client';23import { Card } from '@/components/ui/card';45export function Outline() {6 return (7 <Card variant="outline" className="w-[350px]">8 <Card.Header>9 <Card.Title>Outline Card</Card.Title>10 <Card.Description>Clean and defined with a bold border</Card.Description>11 </Card.Header>12 <Card.Content>13 <p>Outline cards work great for forms, settings, and structured content.</p>14 </Card.Content>15 </Card>16 );17}
Ghost
Tarjetas transparentes sin borde ni sombra.
Ghost Card
Subtle and unobtrusive
Ghost cards are perfect for minimalist designs where you want grouping without visual weight.
1'use client';23import { Card } from '@/components/ui/card';45export function Ghost() {6 return (7 <Card variant="ghost" className="w-[350px]">8 <Card.Header>9 <Card.Title>Ghost Card</Card.Title>10 <Card.Description>Subtle and unobtrusive</Card.Description>11 </Card.Header>12 <Card.Content>13 <p>14 Ghost cards are perfect for minimalist designs where you want grouping without visual15 weight.16 </p>17 </Card.Content>18 </Card>19 );20}
Compacta
Tarjetas con padding reducido para diseños densos.
Regular Spacing
Default padding
This card uses the default padding for comfortable spacing.
Compact Spacing
Reduced padding
This card uses compact padding for denser layouts.
1'use client';23import { Button } from '@/components/ui/button';4import { Card } from '@/components/ui/card';56export function Compact() {7 return (8 <div className="grid gap-4">9 <Card className="w-full">10 <Card.Header>11 <Card.Title>Regular Spacing</Card.Title>12 <Card.Description>Default padding</Card.Description>13 </Card.Header>14 <Card.Content>15 <p>This card uses the default padding for comfortable spacing.</p>16 </Card.Content>17 <Card.Footer>18 <Button variant="secondary">Action</Button>19 </Card.Footer>20 </Card>21 <Card className="w-full">22 <Card.Header compact>23 <Card.Title>Compact Spacing</Card.Title>24 <Card.Description>Reduced padding</Card.Description>25 </Card.Header>26 <Card.Content compact>27 <p>This card uses compact padding for denser layouts.</p>28 </Card.Content>29 <Card.Footer compact>30 <Button variant="secondary">Action</Button>31 </Card.Footer>32 </Card>33 </div>34 );35}
Referencia de API
Card
| Prop | Tipo | Default | Descripción |
|---|---|---|---|
variant | "default" | "outline" | "ghost" | "default" | Variante visual del card. |
as | React.ElementType | 'div' | Cambia el elemento raíz del card. |
className | string | — | Clases adicionales. |
children | React.ReactNode | — | Contenido del card. |
Card.Header
| Prop | Tipo | Default | Descripción |
|---|---|---|---|
compact | boolean | false | Reduce el padding superior e inferior del header. |
className | string | — | Clases adicionales. |
children | React.ReactNode | — | Contenido del header. |
Card.Title
| Prop | Tipo | Default | Descripción |
|---|---|---|---|
as | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'h3' | Tag HTML para el título del card. |
className | string | — | Clases adicionales. |
children | React.ReactNode | — | Contenido del título. |
Card.Description
| Prop | Tipo | Default | Descripción |
|---|---|---|---|
className | string | — | Clases adicionales. |
children | React.ReactNode | — | Texto descriptivo. |
Card.Content
| Prop | Tipo | Default | Descripción |
|---|---|---|---|
compact | boolean | false | Reduce el padding del contenido. |
className | string | — | Clases adicionales. |
children | React.ReactNode | — | Contenido principal del card. |
Card.Footer
| Prop | Tipo | Default | Descripción |
|---|---|---|---|
align | 'start' | 'center' | 'end' | 'between' | 'start' | Controla la alineación horizontal del pie. |
compact | boolean | false | Reduce el padding del footer. |
className | string | — | Clases adicionales. |
children | React.ReactNode | — | Contenido del footer. |