Minimal Count Up
Example
0
New Detections
Props
Prop | Datatype |
---|---|
title | String |
number | int > 0 |
limit | int < number prop |
Notes
- Hard width and height, adjust to your needs
- You may have to edit the font styling, padding, and margin due to your sites existing stylesheets.
Code
import React, { useState, useEffect, useRef } from 'react';import './minimal_count_up.css'
const MinimalCountUp = ({ title = "New Detections", number = 1492, limit = 2000,}) => { const [count, setCount] = useState(0); const [counted, setCounted] = useState(0);
useEffect(() => { setCount(0); setCount(number <= 100 ? 0 : number - 100) let i = number <= 100 ? 0 : number - 100; const interval = setInterval(() => { if (i < number) { setCount((currentCount) => currentCount + 1); i += 1; } else { clearInterval(interval); } }, 0);
return () => clearInterval(interval); }, [number]);
useEffect(() => { setCounted(0);
const scaledNumber = ((number - 0) / (limit - 0)) * (50 - 0) + 0; const countLimit = Math.round(scaledNumber); const easeOutQuad = (t) => t * (2 - t);
let i = 0; const interval = setInterval(() => { if (i < countLimit) { const progress = i / countLimit; // Progress ratio (0 to 1) const easedProgress = easeOutQuad(progress); // Apply easing function const easedValue = easedProgress * countLimit; // Scale eased progress
setCounted(Math.round(easedValue)); // Update state with eased value (rounded) i += 1; } else { clearInterval(interval); } }, 20);
return () => clearInterval(interval); }, [number, limit, setCounted]);
return ( <div className="mcu_wrap"> <div className="mcu_txt_wrap"> <p className="mcu_num"> {count} </p> <p className="mcu_title"> {title} </p> </div> <div className="mcu_line_chart_wrap"> <div className="mcu_line_chart"> {Array.from({ length: 50 }, (_, index) => index).map((line, i) => <div className="mcu_line" style={{ height: `${0.07 * i * i + 6}px` }}></div> )} </div> </div> <div className="mcu_line_chart_wrap"> <div className="mcu_line_chart"> {Array.from({ length: 50 }, (_, index) => index).map((line, i) => { return ( <div> <div className={`mcu_line ${i <= counted ? 'mcu_line_counted' : ''}`} style={{ height: `${0.07 * i * i + 6}px` }}> <div className="mcu_line indicator" style={{ display: i == counted ? 'block' : 'none', height: `${0.07 * i * i + 20}px`, bottom: '14px' }}></div> </div> </div> ) })} </div> </div> </div> );};
export { MinimalCountUp };
.mcu_wrap { height: 240px; width: 400px; padding: 20px; margin: 0px !important; background-color: #DDDDDD; position: relative; font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; border-radius: 6px; color: #515151;}
.mcu_num { margin: 0px !important; font-weight: 300; font-size: 70px; line-height: 45px;}
.mcu_title { margin: 0px !important; font-weight: bold; font-weight: 100; font-size: 30px; padding-left: 4px;}
.mcu_line_chart_wrap { position: absolute; bottom: 20px; left: 0px; margin: 0px !important; width: 100%;}
.mcu_line_chart { width: 90%; margin: 0px auto; display: flex; justify-content: space-around; align-items: flex-end;}
.mcu_line { margin: 0px !important; background-color: #BBBBBB; width: 1px;}
.mcu_line_counted { background-color: #515151;}
.indicator{ background-color: red; position: relative; bottom: 0px;}
.indicator::after{ content: ''; position: absolute; top: -2px; left: -2px; background-color: red; height: 5px; width: 5px; border-radius: 1000px;}