Please use Desktop to view and interact with components
Blocks2000msspring
Stats Counter Block
Animated statistics counters with icons and gradient backgrounds
statscounternumbersmetricsanimationresponsiveshadcn
Useto navigate between components
Preview
Our Impact
Numbers That Speak For Themselves
We're proud of the impact we've made and the trust our users place in us
0+
Active Users
Growing community worldwide
0+
Countries
Global reach and presence
0%
Satisfaction Rate
Customer happiness score
0+
Awards Won
Industry recognition
"These numbers represent real people, real businesses, and real success stories. We're just getting started."
This component requires shadcn/ui
This component uses shadcn/ui components. Make sure you have shadcn/ui set up in your project.
- Install shadcn/ui:
npx shadcn-ui@latest init - Install required components based on the imports in the code (e.g.,
npx shadcn-ui@latest add button) - Ensure your
tailwind.config.tsandglobals.cssare configured as per shadcn/ui documentation
Code
TypeScript + React
'use client'
import { useEffect, useState } from 'react'
import { motion, useInView } from 'framer-motion'
import { useRef } from 'react'
import { Card } from '@/components/ui/card'
import { Badge } from '@/components/ui/badge'
import { TrendingUp, Users, Globe, Award } from 'lucide-react'
const stats = [
{
icon: Users,
value: 50000,
suffix: '+',
label: 'Active Users',
description: 'Growing community worldwide',
bgColor: 'bg-blue-500/10',
iconColor: 'text-blue-500',
},
{
icon: Globe,
value: 120,
suffix: '+',
label: 'Countries',
description: 'Global reach and presence',
bgColor: 'bg-green-500/10',
iconColor: 'text-green-500',
},
{
icon: TrendingUp,
value: 98,
suffix: '%',
label: 'Satisfaction Rate',
description: 'Customer happiness score',
bgColor: 'bg-purple-500/10',
iconColor: 'text-purple-500',
},
{
icon: Award,
value: 25,
suffix: '+',
label: 'Awards Won',
description: 'Industry recognition',
bgColor: 'bg-orange-500/10',
iconColor: 'text-orange-500',
},
]
function Counter({ value, suffix }: { value: number; suffix: string }) {
const [count, setCount] = useState(0)
const ref = useRef(null)
const isInView = useInView(ref, { once: true })
useEffect(() => {
if (isInView) {
let start = 0
const end = value
const duration = 2000
const increment = end / (duration / 16)
const timer = setInterval(() => {
start += increment
if (start >= end) {
setCount(end)
clearInterval(timer)
} else {
setCount(Math.floor(start))
}
}, 16)
return () => clearInterval(timer)
}
}, [isInView, value])
return (
<span ref={ref}>
{count.toLocaleString()}
{suffix}
</span>
)
}
export function StatsCounterBlock() {
return (
<section className="w-full bg-gradient-to-b from-background to-primary/5 px-4 py-16 md:py-24">
<div className="mx-auto max-w-7xl">
{/* Header */}
<motion.div
initial={{ opacity: 0, y: -20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6 }}
className="mb-12 text-center md:mb-16"
>
<Badge className="mb-4" variant="secondary">
Our Impact
</Badge>
<h2 className="mb-4 text-3xl font-bold tracking-tight md:text-4xl lg:text-5xl">
Numbers That Speak{' '}
<span className="bg-gradient-to-r from-primary to-primary/60 bg-clip-text text-transparent">
For Themselves
</span>
</h2>
<p className="mx-auto max-w-2xl text-base text-muted-foreground md:text-lg">
We're proud of the impact we've made and the trust our users place
in us
</p>
</motion.div>
{/* Stats Grid */}
<div className="grid gap-6 sm:grid-cols-2 lg:grid-cols-2">
{stats.map((stat, index) => {
const Icon = stat.icon
return (
<motion.div
key={stat.label}
initial={{ opacity: 0, y: 30, scale: 0.9 }}
animate={{ opacity: 1, y: 0, scale: 1 }}
transition={{
delay: index * 0.1,
duration: 0.5,
type: 'spring',
stiffness: 100,
}}
>
<Card className="group relative overflow-hidden border-border/50 bg-card p-6 transition-all hover:border-primary/50 hover:shadow-2xl md:p-8">
{/* Gradient overlay */}
<motion.div
className={`absolute inset-0 ${stat.bgColor} opacity-50`}
initial={{ opacity: 0 }}
whileHover={{ opacity: 1 }}
transition={{ duration: 0.3 }}
/>
{/* Animated background circle */}
<motion.div
className={`absolute -right-8 -top-8 h-32 w-32 rounded-full ${stat.bgColor} opacity-50 blur-2xl`}
animate={{
scale: [1, 1.2, 1],
rotate: [0, 90, 0],
}}
transition={{
duration: 4,
repeat: Infinity,
ease: 'easeInOut',
}}
/>
<div className="relative z-10">
{/* Icon */}
<motion.div
transition={{ duration: 0.6 }}
className="mb-4"
>
<div
className={`w-fit rounded-xl ${stat.bgColor} p-3`}
>
<Icon className={`h-6 w-6 ${stat.iconColor} md:h-8 md:w-8`} />
</div>
</motion.div>
{/* Counter */}
<motion.div
className="mb-2 text-3xl font-bold tracking-tight md:text-4xl lg:text-5xl"
initial={{ scale: 1 }}
whileInView={{ scale: [1, 1.05, 1] }}
transition={{ duration: 0.5 }}
viewport={{ once: true }}
>
<Counter value={stat.value} suffix={stat.suffix} />
</motion.div>
{/* Label */}
<h3 className="mb-1 text-base font-semibold md:text-lg">
{stat.label}
</h3>
{/* Description */}
<p className="text-xs text-muted-foreground md:text-sm">
{stat.description}
</p>
</div>
{/* Hover effect line */}
<motion.div
className={`absolute bottom-0 left-0 h-1 ${stat.iconColor.replace('text-', 'bg-')}`}
initial={{ width: 0 }}
whileHover={{ width: '100%' }}
transition={{ duration: 0.3 }}
/>
</Card>
</motion.div>
)
})}
</div>
{/* Bottom Quote */}
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.8, duration: 0.5 }}
className="mt-12 text-center md:mt-16"
>
<blockquote className="mx-auto max-w-2xl">
<p className="mb-4 text-lg font-medium italic text-muted-foreground md:text-xl">
"These numbers represent real people, real businesses, and real
success stories. We're just getting started."
</p>
<footer className="text-sm font-semibold">
— Our CEO
</footer>
</blockquote>
</motion.div>
</div>
</section>
)
}
How to Use
- 1Install Framer Motion:
npm install framer-motion - 2Set up shadcn/ui: Install shadcn/ui components used in this code. Check the imports in the code above and install the required components (e.g.,
npx shadcn-ui@latest add button card) - 3Copy the code from above
- 4Paste it into your project and customize as needed
- 5Colors are customizable via Tailwind CSS classes. The default theme uses dark mode colors defined in your globals.css file