141 lines
3 KiB
TypeScript
141 lines
3 KiB
TypeScript
import * as React from 'react'
|
|
import { cva, type VariantProps } from 'class-variance-authority'
|
|
|
|
import { cn } from '@/lib/utils'
|
|
|
|
const cardVariants = cva(
|
|
'flex flex-col rounded-xl border text-card-foreground transition-all',
|
|
{
|
|
variants: {
|
|
variant: {
|
|
default:
|
|
'bg-card shadow-sm',
|
|
|
|
elevated:
|
|
'bg-card shadow-lg hover:shadow-xl',
|
|
|
|
ghost:
|
|
'bg-transparent border-transparent',
|
|
|
|
outline:
|
|
'bg-transparent border-border',
|
|
|
|
muted:
|
|
'bg-muted/50 border-transparent',
|
|
|
|
glass:
|
|
'bg-card/80 backdrop-blur-xl border-border/50',
|
|
|
|
interactive:
|
|
'bg-card shadow-sm cursor-pointer hover:shadow-lg hover:border-primary/50 hover:-translate-y-0.5',
|
|
|
|
glow:
|
|
'bg-card shadow-sm hover:shadow-[0_0_30px_oklch(0.75_0.18_195_/_0.15)] hover:border-primary/50',
|
|
|
|
glowMagenta:
|
|
'bg-card shadow-sm hover:shadow-[0_0_30px_oklch(0.65_0.25_330_/_0.15)] hover:border-secondary/50',
|
|
},
|
|
padding: {
|
|
none: '',
|
|
sm: 'p-4',
|
|
default: 'p-6',
|
|
lg: 'p-8',
|
|
},
|
|
},
|
|
defaultVariants: {
|
|
variant: 'default',
|
|
padding: 'none',
|
|
},
|
|
},
|
|
)
|
|
|
|
interface CardProps
|
|
extends React.ComponentProps<'div'>,
|
|
VariantProps<typeof cardVariants> {}
|
|
|
|
function Card({ className, variant, padding, ...props }: CardProps) {
|
|
return (
|
|
<div
|
|
data-slot="card"
|
|
className={cn(cardVariants({ variant, padding }), className)}
|
|
{...props}
|
|
/>
|
|
)
|
|
}
|
|
|
|
function CardHeader({ className, ...props }: React.ComponentProps<'div'>) {
|
|
return (
|
|
<div
|
|
data-slot="card-header"
|
|
className={cn(
|
|
'flex flex-col gap-1.5 p-6 pb-0',
|
|
className,
|
|
)}
|
|
{...props}
|
|
/>
|
|
)
|
|
}
|
|
|
|
function CardTitle({ className, ...props }: React.ComponentProps<'h3'>) {
|
|
return (
|
|
<h3
|
|
data-slot="card-title"
|
|
className={cn('text-lg font-semibold leading-tight tracking-tight', className)}
|
|
{...props}
|
|
/>
|
|
)
|
|
}
|
|
|
|
function CardDescription({ className, ...props }: React.ComponentProps<'p'>) {
|
|
return (
|
|
<p
|
|
data-slot="card-description"
|
|
className={cn('text-sm text-muted-foreground', className)}
|
|
{...props}
|
|
/>
|
|
)
|
|
}
|
|
|
|
function CardAction({ className, ...props }: React.ComponentProps<'div'>) {
|
|
return (
|
|
<div
|
|
data-slot="card-action"
|
|
className={cn(
|
|
'absolute top-4 right-4',
|
|
className,
|
|
)}
|
|
{...props}
|
|
/>
|
|
)
|
|
}
|
|
|
|
function CardContent({ className, ...props }: React.ComponentProps<'div'>) {
|
|
return (
|
|
<div
|
|
data-slot="card-content"
|
|
className={cn('p-6 pt-4', className)}
|
|
{...props}
|
|
/>
|
|
)
|
|
}
|
|
|
|
function CardFooter({ className, ...props }: React.ComponentProps<'div'>) {
|
|
return (
|
|
<div
|
|
data-slot="card-footer"
|
|
className={cn('flex items-center gap-3 p-6 pt-0', className)}
|
|
{...props}
|
|
/>
|
|
)
|
|
}
|
|
|
|
export {
|
|
Card,
|
|
CardHeader,
|
|
CardFooter,
|
|
CardTitle,
|
|
CardAction,
|
|
CardDescription,
|
|
CardContent,
|
|
cardVariants,
|
|
}
|