({
title,
value,
icon,
iconColor = "var(--info)",
trend,
}: StatsCardProps)
| 14 | } |
| 15 | |
| 16 | export function StatsCard({ |
| 17 | title, |
| 18 | value, |
| 19 | icon, |
| 20 | iconColor = "var(--info)", |
| 21 | trend, |
| 22 | }: StatsCardProps) { |
| 23 | return ( |
| 24 | <div |
| 25 | className="rounded-xl p-4 md:p-6" |
| 26 | style={{ |
| 27 | backgroundColor: 'var(--card)', |
| 28 | border: '1px solid var(--border)', |
| 29 | }} |
| 30 | > |
| 31 | <div className="flex items-center justify-between mb-1.5 md:mb-2"> |
| 32 | <span |
| 33 | className="text-xs md:text-sm font-medium" |
| 34 | style={{ color: 'var(--text-secondary)' }} |
| 35 | > |
| 36 | {title} |
| 37 | </span> |
| 38 | <div className="[&>svg]:w-4 [&>svg]:h-4 md:[&>svg]:w-5 md:[&>svg]:h-5" style={{ color: iconColor }}> |
| 39 | {icon} |
| 40 | </div> |
| 41 | </div> |
| 42 | |
| 43 | <div className="flex items-end justify-between"> |
| 44 | <span |
| 45 | className="text-2xl md:text-3xl font-bold tracking-tight" |
| 46 | style={{ |
| 47 | fontFamily: 'var(--font-heading)', |
| 48 | color: 'var(--text-primary)', |
| 49 | letterSpacing: '-1.5px' |
| 50 | }} |
| 51 | > |
| 52 | {value} |
| 53 | </span> |
| 54 | {trend && ( |
| 55 | <span |
| 56 | className="text-xs md:text-sm font-medium" |
| 57 | style={{ color: trend.isPositive ? 'var(--success)' : 'var(--error)' }} |
| 58 | > |
| 59 | {trend.isPositive ? "↑" : "↓"} {trend.value}% |
| 60 | </span> |
| 61 | )} |
| 62 | </div> |
| 63 | </div> |
| 64 | ); |
| 65 | } |
nothing calls this directly
no outgoing calls
no test coverage detected