mirror of
https://github.com/Since-3/since3-website.git
synced 2026-10-12 19:51:16 +00:00
36 lines
985 B
TypeScript
36 lines
985 B
TypeScript
"use client"
|
|
|
|
import { useEffect, useRef } from "react"
|
|
import { animate, useInView } from "motion/react"
|
|
|
|
/**
|
|
* Counts from 0 to `value` once it scrolls into view.
|
|
* The server renders the final number, so it is correct without JavaScript.
|
|
*/
|
|
export function CountUp({ value, className }: { value: number; className?: string }) {
|
|
const ref = useRef<HTMLSpanElement>(null)
|
|
const inView = useInView(ref, { once: true, margin: "0px 0px -15% 0px" })
|
|
|
|
useEffect(() => {
|
|
const el = ref.current
|
|
if (!el || window.matchMedia("(prefers-reduced-motion: reduce)").matches) return
|
|
if (!inView) {
|
|
el.textContent = "0"
|
|
return
|
|
}
|
|
const controls = animate(0, value, {
|
|
duration: 1.8,
|
|
ease: [0.16, 1, 0.3, 1],
|
|
onUpdate: (latest) => {
|
|
el.textContent = String(Math.round(latest))
|
|
},
|
|
})
|
|
return () => controls.stop()
|
|
}, [inView, value])
|
|
|
|
return (
|
|
<span ref={ref} className={className}>
|
|
{value}
|
|
</span>
|
|
)
|
|
}
|