ScanMenu / src /components /ui /stat-card.tsx
HamzaAri's picture
๐Ÿš€ Deploy ScanMenu - Production-ready SaaS web app for digital restaurant menus & QR ordering
e1ef9fc verified
'use client';
import { cn } from '@/lib/utils';
import { LucideIcon } from 'lucide-react';
interface StatCardProps {
title: string;
value: string;
change?: string;
changeType?: 'positive' | 'negative' | 'neutral';
icon: LucideIcon;
iconColor?: string;
}
export function StatCard({ title, value, change, changeType = 'neutral', icon: Icon, iconColor = 'text-emerald-600' }: StatCardProps) {
return (
<div className="group relative overflow-hidden rounded-2xl border border-zinc-200/60 bg-white p-6 shadow-sm transition-all hover:shadow-md hover:border-zinc-300/60 dark:border-zinc-800 dark:bg-zinc-900">
<div className="flex items-start justify-between">
<div className="space-y-2">
<p className="text-sm font-medium text-zinc-500 dark:text-zinc-400">{title}</p>
<p className="text-3xl font-bold tracking-tight text-zinc-900 dark:text-zinc-100">{value}</p>
{change && (
<p className={cn(
'text-sm font-medium',
changeType === 'positive' && 'text-emerald-600',
changeType === 'negative' && 'text-red-600',
changeType === 'neutral' && 'text-zinc-500'
)}>
{change}
</p>
)}
</div>
<div className={cn('rounded-xl bg-zinc-50 p-3 dark:bg-zinc-800', iconColor)}>
<Icon className="h-5 w-5" />
</div>
</div>
<div className="absolute inset-x-0 bottom-0 h-0.5 bg-gradient-to-r from-emerald-500 to-cyan-500 opacity-0 transition-opacity group-hover:opacity-100" />
</div>
);
}