KPICards
kpicards-1779379195514.tsx
'use client'
import { useState, useEffect, useRef } from 'react'
const METRICS = [
{ label: 'Monthly Revenue', value: 48320, prev: 41200, prefix: '$', suffix: '', color: '#C9A84C', data: [22,28,24,32,28,38,35,42,40,48] },
{ label: 'Active Users', value: 12847, prev: 10230, prefix: '', suffix: '', color: '#6366f1', data: [60,72,68,80,76,88,84,95,90,100] },
{ label: 'Conversion Rate', value: 3.42, prev: 2.91, prefix: '', suffix: '%', color: '#22c55e', data: [2.1,2.4,2.2,2.8,2.6,3.0,2.9,3.2,3.1,3.4] },
{ label: 'Churn Rate', value: 1.2, prev: 1.8, prefix: '', suffix: '%', color: '#ef4444', data: [2.4,2.1,2.3,1.9,2.1,1.8,1.7,1.5,1.3,1.2], invert: true },
]
function Sparkline({ data, color }: { data: number[]; color: string }) {
const max = Math.max(...data), min = Math.min(...data)
const W = 80, H = 32
const points = data.map((v, i) => [i / (data.length - 1) * W, H - (v - min) / (max - min + 0.01) * H] as [number,number])
const path = points.map((p, i) => `${i === 0 ? 'M' : 'L'}${p[0]},${p[1]}`).join(' ')
const area = path + ` L${W},${H} L0,${H} Z`
return (
<svg width={W} height={H} viewBox={`0 0 ${W} ${H}`}>
<path d={area} fill={color + '18'} />
<path d={path} fill="none" stroke={color} strokeWidth={1.5} strokeLinecap="round" />
</svg>
)
}
function CountUp({ target, prefix, suffix }: { target: number; prefix: string; suffix: string }) {
const [v, setV] = useState(0)
useEffect(() => {
const start = Date.now()
const dur = 1200
const tick = () => {
const p = Math.min((Date.now() - start) / dur, 1)
setV(target * (1 - Math.pow(1 - p, 3)))
if (p < 1) requestAnimationFrame(tick)
}
requestAnimationFrame(tick)
}, [target])
const fmt = target < 10 ? v.toFixed(2) : target < 1000 ? Math.round(v).toLocaleString() : Math.round(v).toLocaleString()
return <span>{prefix}{fmt}{suffix}</span>
}
export default function KPICards() {
return (
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(2,1fr)', gap: 12, padding: 24, background: '#080808' }}>
{METRICS.map(m => {
const pct = ((m.value - m.prev) / m.prev * 100).toFixed(1)
const up = m.value > m.prev
const good = m.invert ? !up : up
return (
<div key={m.label} style={{ background: '#0F0F0F', border: '1px solid rgba(255,255,255,0.06)', borderRadius: 14, padding: 20 }}>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', marginBottom: 12 }}>
<span style={{ color: 'rgba(255,255,255,0.45)', fontSize: 12, fontWeight: 500 }}>{m.label}</span>
<Sparkline data={m.data} color={m.color} />
</div>
<div style={{ color: '#F5F5F0', fontSize: 26, fontWeight: 800, letterSpacing: '-0.02em', marginBottom: 8 }}>
<CountUp target={m.value} prefix={m.prefix} suffix={m.suffix} />
</div>
<div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
<span style={{ color: good ? '#22c55e' : '#ef4444', fontSize: 12, fontWeight: 600, background: (good ? '#22c55e' : '#ef4444') + '18', padding: '2px 6px', borderRadius: 4 }}>
{up ? '↑' : '↓'} {Math.abs(Number(pct))}%
</span>
<span style={{ color: 'rgba(255,255,255,0.3)', fontSize: 12 }}>vs last month</span>
</div>
</div>
)
})}
</div>
)
}Component info
CategoryDashboard & App UI
Frameworkreact
TierFREE
Views0
Copies0
About
4 KPI metric cards with trend sparklines, comparison to last period, and animated count-up
More from Dashboard & App UI
import React from 'react';
interface MetricCardProps {
value: number;
trend: 'up' | 'down';
sparklineData: number[];
}
const MetricCard: React.FC<MetricCardProps> = ({ value, trend, sparklineData }) => {
return (
<div style={{ backgrounMetricCard
Dashboard & App UI
import React from 'react';
import './ProgressRing.css';
interface ProgressRingProps {
percentage: number;
}
const ProgressRing: React.FC<ProgressRingProps> = ({ percentage }) => {
const circleDashArray = 2 * Math.PI * 50;
const circleDashOffsetProgressRing
Dashboard & App UI
'use client';
import React from 'react';
interface KPIWidgetProps {
metric: number;
label: string;
target: number;
progress: number;
sparklineData: number[];
periodComparison: string;
}
const KPIWidget: React.FC<KPIWidgetProps> = ({
KPIWidget
Dashboard & App UI
'use client'
import { useState, useEffect } from 'react'
type EventType = 'component_added' | 'user_signup' | 'purchase' | 'api_call' | 'review'
const EVENTS: { id: number; type: EventType; user: string; detail: string; time: number; color: string;ActivityFeed
Dashboard & App UI