- HeroSection: 3-col layout (copy | concentric circles+dashboard | display headline) - 'use client' + framer-motion entrance animations (slide in from sides, scale centre) - DashboardPreview inline component (compact portal mockup) - Two floating stat mini-cards (Avg Tax Saved, Response Time) - Mobile: stacked layout, right headline column hidden, H1 in left column - ContainerScroll: simplified — removed 72rem scroll container and scroll transforms; now plain layout wrapper with CSS fadeInUp entrance - Header: logo size increased h-10 → h-13 (40px → 52px) - fix: escape apostrophes in ProcessSection, SolutionSection, TestimonialsSection - fix: remove unused customSize param from SpotlightCard - docs: update CONTEXT_HANDOVER.md with session 4 changes Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
40 lines
820 B
TypeScript
40 lines
820 B
TypeScript
'use client';
|
|
|
|
import { useEffect, useRef } from 'react';
|
|
import { gsap, ScrollTrigger } from '@/lib/gsap';
|
|
|
|
interface Props {
|
|
value: number;
|
|
decimals?: number;
|
|
}
|
|
|
|
export function StatCounter({ value, decimals = 0 }: Props) {
|
|
const ref = useRef<HTMLSpanElement>(null);
|
|
|
|
useEffect(() => {
|
|
const el = ref.current;
|
|
if (!el) return;
|
|
|
|
const obj = { val: 0 };
|
|
|
|
const trigger = ScrollTrigger.create({
|
|
trigger: el,
|
|
start: 'top 80%',
|
|
once: true,
|
|
onEnter: () => {
|
|
gsap.to(obj, {
|
|
val: value,
|
|
duration: 2.2,
|
|
ease: 'power2.out',
|
|
onUpdate() {
|
|
el.textContent = obj.val.toFixed(decimals);
|
|
},
|
|
});
|
|
},
|
|
});
|
|
|
|
return () => trigger.kill();
|
|
}, [value, decimals]);
|
|
|
|
return <span ref={ref}>0</span>;
|
|
}
|