03ae372509
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)
55 lines
1.5 KiB
TypeScript
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>
|
|
);
|
|
} |