| import { TrendingUp, TrendingDown, Minus } from "lucide-react"; | |
| interface StatsCardComponentProps { | |
| title: string; | |
| value: number | string; | |
| icon?: React.ReactNode; | |
| trend?: number; | |
| description?: string; | |
| } | |
| export function StatsCardComponent({ title, value, icon, trend, description }: StatsCardComponentProps) { | |
| const trendIcon = trend && trend > 0 ? <TrendingUp className="w-4 h-4 text-green-500" /> : trend && trend < 0 ? <TrendingDown className="w-4 h-4 text-red-500" /> : <Minus className="w-4 h-4 text-gray-400" />; | |
| return ( | |
| <div className="bg-white dark:bg-gray-800 rounded-xl p-4 shadow-sm border border-gray-100 dark:border-gray-700"> | |
| <div className="flex items-center justify-between"> | |
| <span className="text-sm text-gray-500">{title}</span> | |
| {icon && <span className="text-2xl">{icon}</span>} | |
| </div> | |
| <p className="text-3xl font-bold mt-2">{value}</p> | |
| {(trend !== undefined || description) && ( | |
| <div className="flex items-center gap-1 mt-1 text-xs"> | |
| {trend !== undefined && <>{trendIcon} <span className={trend > 0 ? "text-green-600" : trend < 0 ? "text-red-600" : "text-gray-500"}>{Math.abs(trend)}%</span></>} | |
| {description && <span className="text-gray-400 ml-2">{description}</span>} | |
| </div> | |
| )} | |
| </div> | |
| ); | |
| } |
Xet Storage Details
- Size:
- 1.32 kB
- Xet hash:
- d186279dbc69f9abaf27ea9f0c8740824ee7f4212da1da2e2a38fc91c9046943
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.