Files
route-commerce/src/app/LandingPageClient.tsx
T
tyler 03ae372509 fix(home): resilient homepage animations + anchors + counters
Subagent 1 (Codex review pass):

LandingPageClient.tsx
- Guard GSAP .scroll-reveal loop to prevent 'missing target' warnings when no targets exist

brands/page.tsx
- Comment cleanup for selector scoping

tuxedo/page.tsx
- Add pageScopeRef + use as explicit GSAP context scope (fixes 'Invalid scope' warnings)
- Reduced-motion guard for counter animations
- Comments noting scope is now resilient

HeroSection.tsx
- Wrap sections in containerRef for proper GSAP context
- Reduced-motion support (final states shown immediately, no heavy anims)
- Counter animation: switched from textContent tween (unreliable, left values at 0) to proxy object pattern (val -> display)
- Added IO + rAF fallback if GSAP is unavailable
- Added section ids: #features, #stats, #reviews (matches nav anchors)
- Reduced blank scroll region (300vh -> 140vh on story section)
- Removed duplicate inline footer (LandingPageWrapper <Footer /> now sole source)

LandingPageWrapper.tsx
- Anchor comments noting ids added in HeroSection

Docs + scripts:
- docs/ADMIN_FUNCTIONALITY_CHECKLIST.md (admin app coverage notes)
- docs/pricing-assessment.md (pricing model notes)
- scripts/apply-admin-create-stop.js, check-stop-fns*.js, verify-stop-fns.js (admin stop creation tooling)
2026-06-03 15:36:40 +00:00

55 lines
1.5 KiB
TypeScript

"use client";
import { useEffect, useRef } from "react";
import HeroSection from "@/components/landing/HeroSection";
import { LandingPageWrapper } from "@/components/landing/LandingPageWrapper";
import { gsap } from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";
// Register GSAP plugins
if (typeof window !== "undefined") {
gsap.registerPlugin(ScrollTrigger);
}
export default function LandingPageClient() {
const mainRef = useRef<HTMLDivElement>(null);
// Global scroll animations (guarded to prevent missing-target warnings when no .scroll-reveal elements)
useEffect(() => {
if (typeof window === "undefined" || !mainRef.current) return;
const ctx = gsap.context(() => {
// Reveal animations for sections - only if targets exist (prevents GSAP "missing targets" warnings)
const revealElements = gsap.utils.toArray<Element>(".scroll-reveal");
if (revealElements.length > 0) {
revealElements.forEach((el) => {
gsap.fromTo(
el,
{ opacity: 0, y: 60 },
{
opacity: 1,
y: 0,
duration: 1,
ease: "power3.out",
scrollTrigger: {
trigger: el,
start: "top 85%",
toggleActions: "play none none reverse",
},
}
);
});
}
}, mainRef);
return () => ctx.revert();
}, []);
return (
<LandingPageWrapper>
<div ref={mainRef}>
<HeroSection />
</div>
</LandingPageWrapper>
);
}