FlipCounter
flipcounter-1779388705785.tsx
'use client';
import { useState, useEffect } from 'react';
function FlipDigit({ digit, prev }) {
const [flipping, setFlipping] = useState(false);
useEffect(() => {
if (digit !== prev) {
setFlipping(true);
const t = setTimeout(() => setFlipping(false), 400);
return () => clearTimeout(t);
}
}, [digit, prev]);
return (
<div style={{
width: '48px', height: '64px',
background: '#1a1a1a',
border: '1px solid rgba(255,255,255,0.1)',
borderRadius: '8px',
display: 'flex', alignItems: 'center', justifyContent: 'center',
position: 'relative', overflow: 'hidden',
boxShadow: 'inset 0 2px 8px rgba(0,0,0,0.4)',
}}>
<div style={{
position: 'absolute', top: 0, left: 0, right: 0, height: '50%',
borderBottom: '1px solid rgba(0,0,0,0.5)',
background: 'rgba(0,0,0,0.2)',
}} />
<span style={{
fontSize: '36px', fontWeight: 900, color: '#C9A84C',
fontFamily: 'monospace',
transform: flipping ? 'rotateX(90deg)' : 'rotateX(0deg)',
transition: flipping ? 'transform 0.2s ease-in' : 'transform 0.2s ease-out',
display: 'block',
textShadow: '0 0 20px rgba(201,168,76,0.5)',
}}>{digit}</span>
</div>
);
}
export default function FlipCounter({ start = 0, end = 9999, duration = 4000 }) {
const [count, setCount] = useState(start);
const [prev, setPrev] = useState(start);
useEffect(() => {
const steps = 60;
const inc = (end - start) / steps;
let current = start;
const interval = setInterval(() => {
current = Math.min(end, current + inc);
setPrev(count => count);
setCount(Math.round(current));
if (current >= end) clearInterval(interval);
}, duration / steps);
return () => clearInterval(interval);
}, [start, end, duration]);
const digits = String(count).padStart(4, '0').split('');
const prevDigits = String(prev).padStart(4, '0').split('');
return (
<div style={{ fontFamily: 'system-ui, sans-serif', display: 'inline-flex', flexDirection: 'column', alignItems: 'center', gap: '12px' }}>
<div style={{ display: 'flex', gap: '6px', alignItems: 'center' }}>
{digits.map((d, i) => (
<FlipDigit key={i} digit={d} prev={prevDigits[i]} />
))}
</div>
<p style={{ margin: 0, color: 'rgba(245,245,240,0.4)', fontSize: '12px', letterSpacing: '0.1em', textTransform: 'uppercase' }}>
Active Users
</p>
</div>
);
}Component info
CategoryData Display
Frameworkreact
TierFREE
Views0
Copies0
About
Mechanical flip-style animated counter
More from Data Display
'use client'
import { useState, useRef, useCallback, useEffect } from 'react'
export default function ComparisonSlider() {
const [position, setPosition] = useState(50)
const [dragging, setDragging] = useState(false)
const containerRef = useRefComparisonSlider
Data Display
'use client'
import { useState } from 'react'
const WEEKS = 26
const DAYS = 7
function randomActivity(): number {
const r = Math.random()
if (r < 0.3) return 0
if (r < 0.55) return 1
if (r < 0.75) return 2
if (r < 0.9) return 3
return 4HeatmapCalendar
Data Display
'use client'
import { useState } from 'react'
const events = [
{ id: 1, icon: '🚀', title: 'Wave 7 generation complete', desc: '57 new components published across 14 categories', time: '14:32', type: 'success', day: 'Today' },
{ id: 2, icon: '👥TimelineActivity
Data Display
'use client';
import { useState } from 'react';
export default function SearchFilterBar() {
const [query, setQuery] = useState('');
const [filters, setFilters] = useState([]);
const [showDropdown, setShowDropdown] = useState(false);
const fSearchFilterBar
Data Display