@@ -5,27 +5,54 @@ import Link from "@docusaurus/Link";
55import useBaseUrl from "@docusaurus/useBaseUrl" ;
66
77// --- REVEAL HOOK ---
8+ // Elements already in or above the viewport on mount (e.g., page refreshed
9+ // while scrolled down) are shown instantly without animation.
10+ // We wait a frame for the browser to restore scroll position, then check
11+ // whether the element is in or above the viewport. If so, show instantly.
12+ // Otherwise, use IntersectionObserver for the scroll-triggered reveal.
813function useReveal ( threshold = 0.15 ) {
914 const ref = useRef ( null ) ;
1015 const [ visible , setVisible ] = useState ( false ) ;
16+ const [ skipAnimation , setSkipAnimation ] = useState ( false ) ;
1117
1218 useEffect ( ( ) => {
1319 const el = ref . current ;
1420 if ( ! el ) return ;
15- const observer = new IntersectionObserver (
16- ( [ entry ] ) => {
17- if ( entry . isIntersecting ) {
18- setVisible ( true ) ;
19- observer . disconnect ( ) ;
20- }
21- } ,
22- { threshold }
23- ) ;
24- observer . observe ( el ) ;
25- return ( ) => observer . disconnect ( ) ;
21+
22+ // Wait one rAF so the browser has restored scroll position after refresh.
23+ const raf = requestAnimationFrame ( ( ) => {
24+ const rect = el . getBoundingClientRect ( ) ;
25+ // Element is above the viewport (scrolled past) or currently visible
26+ if ( rect . bottom <= 0 || rect . top < window . innerHeight ) {
27+ setSkipAnimation ( true ) ;
28+ setVisible ( true ) ;
29+ return ;
30+ }
31+
32+ // Element is below the viewport — observe for scroll-triggered reveal
33+ const observer = new IntersectionObserver (
34+ ( [ entry ] ) => {
35+ if ( entry . isIntersecting ) {
36+ setVisible ( true ) ;
37+ observer . disconnect ( ) ;
38+ }
39+ } ,
40+ { threshold }
41+ ) ;
42+ observer . observe ( el ) ;
43+ // Store for cleanup
44+ el . _revealObserver = observer ;
45+ } ) ;
46+
47+ return ( ) => {
48+ cancelAnimationFrame ( raf ) ;
49+ if ( el . _revealObserver ) {
50+ el . _revealObserver . disconnect ( ) ;
51+ }
52+ } ;
2653 } , [ threshold ] ) ;
2754
28- return [ ref , visible ] ;
55+ return [ ref , visible , skipAnimation ] ;
2956}
3057
3158// --- COUNT UP HOOK ---
@@ -34,6 +61,10 @@ function useCountUp(target, duration, start) {
3461
3562 useEffect ( ( ) => {
3663 if ( ! start ) return ;
64+ if ( duration <= 0 ) {
65+ setValue ( target ) ;
66+ return ;
67+ }
3768 let startTime = null ;
3869 let raf ;
3970
@@ -160,18 +191,22 @@ export default function Homepage() {
160191--header 'Gotenberg-Webhook-Events-Url: https://my-api.com/events'
161192` ;
162193
163- const [ sponsorRowRef , sponsorRowVisible ] = useReveal ( 0.1 ) ;
164- const [ poweredByRowRef , poweredByRowVisible ] = useReveal ( 0.1 ) ;
165- const [ sponsorBtnRef , sponsorBtnVisible ] = useReveal ( 0.1 ) ;
166- const [ sectionHeaderRef , sectionHeaderVisible ] = useReveal ( 0.2 ) ;
167- const [ feature1Ref , feature1Visible ] = useReveal ( 0.15 ) ;
168- const [ feature2Ref , feature2Visible ] = useReveal ( 0.15 ) ;
169- const [ feature3Ref , feature3Visible ] = useReveal ( 0.15 ) ;
170- const [ feature4Ref , feature4Visible ] = useReveal ( 0.15 ) ;
171- const [ ctaRef , ctaVisible ] = useReveal ( 0.2 ) ;
194+ const [ sectionHeaderRef , sectionHeaderVisible , sectionHeaderSkip ] =
195+ useReveal ( 0.2 ) ;
196+ const [ feature1Ref , feature1Visible , feature1Skip ] = useReveal ( 0.15 ) ;
197+ const [ feature2Ref , feature2Visible , feature2Skip ] = useReveal ( 0.15 ) ;
198+ const [ feature3Ref , feature3Visible , feature3Skip ] = useReveal ( 0.15 ) ;
199+ const [ feature4Ref , feature4Visible , feature4Skip ] = useReveal ( 0.15 ) ;
200+ const [ ctaRef , ctaVisible , ctaSkip ] = useReveal ( 0.2 ) ;
201+
202+ // Helper: returns the right CSS classes for reveal animations
203+ const revealClasses = ( visible , skip ) =>
204+ skip
205+ ? styles . revealInstant
206+ : clsx ( styles . reveal , visible && styles . revealVisible ) ;
172207
173- const dockerCount = useCountUp ( 55 , 1800 , ctaVisible ) ;
174- const starsCount = useCountUp ( 11 , 1800 , ctaVisible ) ;
208+ const dockerCount = useCountUp ( 55 , ctaSkip ? 0 : 1800 , ctaVisible ) ;
209+ const starsCount = useCountUp ( 11 , ctaSkip ? 0 : 1800 , ctaVisible ) ;
175210
176211 return (
177212 < main className = { styles . mainContainer } >
@@ -280,15 +315,7 @@ export default function Homepage() {
280315 < section className = { styles . communitySection } >
281316 < div className = "container" >
282317 < div className = { styles . sponsorsStrip } >
283- < div
284- ref = { sponsorRowRef }
285- className = { clsx (
286- styles . sponsorRow ,
287- styles . reveal ,
288- sponsorRowVisible && styles . revealVisible
289- ) }
290- style = { { animationDelay : "0.4s" } }
291- >
318+ < div className = { styles . sponsorRow } >
292319 < span className = { styles . sponsorStripLabel } > Sponsors</ span >
293320 < div className = { styles . sponsorLogos } >
294321 < a href = "https://thecodingmachine.com" target = "_blank" >
@@ -315,15 +342,7 @@ export default function Homepage() {
315342 </ div >
316343 </ div >
317344
318- < div
319- ref = { poweredByRowRef }
320- className = { clsx (
321- styles . sponsorRow ,
322- styles . reveal ,
323- poweredByRowVisible && styles . revealVisible
324- ) }
325- style = { { animationDelay : "0.7s" } }
326- >
345+ < div className = { styles . sponsorRow } >
327346 < span className = { styles . sponsorStripLabel } > Powered By</ span >
328347 < div className = { styles . sponsorLogos } >
329348 < a
@@ -346,14 +365,7 @@ export default function Homepage() {
346365 </ div >
347366 </ div >
348367
349- < div
350- ref = { sponsorBtnRef }
351- className = { clsx (
352- styles . reveal ,
353- sponsorBtnVisible && styles . revealVisible
354- ) }
355- style = { { animationDelay : "1s" } }
356- >
368+ < div >
357369 < Link
358370 to = "https://github.com/sponsors/gulien"
359371 className = { styles . heartBtnStrip }
@@ -381,8 +393,7 @@ export default function Homepage() {
381393 ref = { sectionHeaderRef }
382394 className = { clsx (
383395 styles . sectionHeader ,
384- styles . reveal ,
385- sectionHeaderVisible && styles . revealVisible
396+ revealClasses ( sectionHeaderVisible , sectionHeaderSkip )
386397 ) }
387398 >
388399 < h2 >
@@ -397,8 +408,7 @@ export default function Homepage() {
397408 ref = { feature1Ref }
398409 className = { clsx (
399410 styles . splitRow ,
400- styles . reveal ,
401- feature1Visible && styles . revealVisible
411+ revealClasses ( feature1Visible , feature1Skip )
402412 ) }
403413 >
404414 < div className = { styles . splitContent } >
@@ -439,8 +449,7 @@ export default function Homepage() {
439449 className = { clsx (
440450 styles . splitRow ,
441451 styles . splitRowReverse ,
442- styles . reveal ,
443- feature2Visible && styles . revealVisible
452+ revealClasses ( feature2Visible , feature2Skip )
444453 ) }
445454 >
446455 < div className = { styles . splitContent } >
@@ -478,8 +487,7 @@ export default function Homepage() {
478487 ref = { feature3Ref }
479488 className = { clsx (
480489 styles . splitRow ,
481- styles . reveal ,
482- feature3Visible && styles . revealVisible
490+ revealClasses ( feature3Visible , feature3Skip )
483491 ) }
484492 >
485493 < div className = { styles . splitContent } >
@@ -519,8 +527,7 @@ export default function Homepage() {
519527 className = { clsx (
520528 styles . splitRow ,
521529 styles . splitRowReverse ,
522- styles . reveal ,
523- feature4Visible && styles . revealVisible
530+ revealClasses ( feature4Visible , feature4Skip )
524531 ) }
525532 >
526533 < div className = { styles . splitContent } >
@@ -586,11 +593,7 @@ export default function Homepage() {
586593 < div className = { styles . ctaGlow } />
587594 < div
588595 ref = { ctaRef }
589- className = { clsx (
590- "container" ,
591- styles . reveal ,
592- ctaVisible && styles . revealVisible
593- ) }
596+ className = { clsx ( "container" , revealClasses ( ctaVisible , ctaSkip ) ) }
594597 >
595598 < h2 >
596599 Ready to transform your{ " " }
0 commit comments