22import React , { type ReactNode , useState , useEffect } from 'react' ;
33import Link from "@docusaurus/Link" ;
44import type { Props } from '@theme/Footer/Layout' ;
5+ import SlotCounter from "react-slot-counter" ;
56import './enhanced-footer.css' ;
67
78// Dynamic stats interface
@@ -12,6 +13,15 @@ interface FooterStats {
1213 supportHours : string ;
1314}
1415
16+ // Helper function to parse stat values for SlotCounter
17+ const parseStatValue = ( statValue : string ) => {
18+ // Extract numeric part and suffix from strings like "52K+", "215+", "95%", "24/7"
19+ const numericMatch = statValue . match ( / ^ ( \d + ) / ) ;
20+ const numericValue = numericMatch ? parseInt ( numericMatch [ 1 ] ) : 0 ;
21+ const suffix = statValue . replace ( / ^ \d + / , '' ) ;
22+ return { numericValue, suffix } ;
23+ } ;
24+
1525export default function FooterLayout ( {
1626 style,
1727 links,
@@ -105,7 +115,16 @@ export default function FooterLayout({
105115 </ svg >
106116 </ div >
107117 < div className = "stat-content" >
108- < div className = "stat-number" > { stats . activeUsers } </ div >
118+ < div className = "stat-number" >
119+ < SlotCounter
120+ value = { parseStatValue ( stats . activeUsers ) . numericValue }
121+ animateOnVisible = { true }
122+ duration = { 1200 }
123+ delay = { 100 }
124+ sequentialAnimationMode = { true }
125+ />
126+ { parseStatValue ( stats . activeUsers ) . suffix }
127+ </ div >
109128 < div className = "stat-label" > Active Learners</ div >
110129 </ div >
111130 </ div >
@@ -117,7 +136,16 @@ export default function FooterLayout({
117136 </ svg >
118137 </ div >
119138 < div className = "stat-content" >
120- < div className = "stat-number" > { stats . tutorials } </ div >
139+ < div className = "stat-number" >
140+ < SlotCounter
141+ value = { parseStatValue ( stats . tutorials ) . numericValue }
142+ animateOnVisible = { true }
143+ duration = { 1200 }
144+ delay = { 200 }
145+ sequentialAnimationMode = { true }
146+ />
147+ { parseStatValue ( stats . tutorials ) . suffix }
148+ </ div >
121149 < div className = "stat-label" > Tutorials</ div >
122150 </ div >
123151 </ div >
@@ -129,7 +157,16 @@ export default function FooterLayout({
129157 </ svg >
130158 </ div >
131159 < div className = "stat-content" >
132- < div className = "stat-number" > { stats . successRate } </ div >
160+ < div className = "stat-number" >
161+ < SlotCounter
162+ value = { parseStatValue ( stats . successRate ) . numericValue }
163+ animateOnVisible = { true }
164+ duration = { 1200 }
165+ delay = { 300 }
166+ sequentialAnimationMode = { true }
167+ />
168+ { parseStatValue ( stats . successRate ) . suffix }
169+ </ div >
133170 < div className = "stat-label" > Success Rate</ div >
134171 </ div >
135172 </ div >
@@ -141,7 +178,38 @@ export default function FooterLayout({
141178 </ svg >
142179 </ div >
143180 < div className = "stat-content" >
144- < div className = "stat-number" > { stats . supportHours } </ div >
181+ < div className = "stat-number" >
182+ { stats . supportHours === '24/7' ? (
183+ < >
184+ < SlotCounter
185+ value = { 24 }
186+ animateOnVisible = { true }
187+ duration = { 1200 }
188+ delay = { 400 }
189+ sequentialAnimationMode = { true }
190+ />
191+ /
192+ < SlotCounter
193+ value = { 7 }
194+ animateOnVisible = { true }
195+ duration = { 1200 }
196+ delay = { 500 }
197+ sequentialAnimationMode = { true }
198+ />
199+ </ >
200+ ) : (
201+ < >
202+ < SlotCounter
203+ value = { parseStatValue ( stats . supportHours ) . numericValue }
204+ animateOnVisible = { true }
205+ duration = { 1200 }
206+ delay = { 400 }
207+ sequentialAnimationMode = { true }
208+ />
209+ { parseStatValue ( stats . supportHours ) . suffix }
210+ </ >
211+ ) }
212+ </ div >
145213 < div className = "stat-label" > Support</ div >
146214 </ div >
147215 </ div >
0 commit comments