Files
whispering-tree/sections/Hero.tsx
2025-11-10 17:10:34 +05:30

150 lines
5.6 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client";
import React, { useEffect, useRef } from "react";
import gsap from "gsap";
import { SplitText } from "gsap/SplitText";
import Image from "next/image";
import Button from "@/components/shared/Button";
import SecondaryButton from "@/components/shared/Secondary";
import Navbar from "@/components/shared/Navbar";
import MobileNavbar from "@/components/ui/mobile-navbar";
// Register plugins (once)
gsap.registerPlugin(SplitText);
const Hero = () => {
// ── Refs ─────────────────────────────────────────────────────────────────────
const containerRef = useRef<HTMLDivElement>(null);
const headingRef = useRef<HTMLHeadingElement>(null);
const subHeadingRef = useRef<HTMLParagraphElement>(null);
const buttonWrapperRef = useRef<HTMLDivElement>(null);
useEffect(() => {
const ctx = gsap.context(() => {
// ── 2. HEADING char-by-char ───────────────────────────────────
if (!headingRef.current) return;
const headingSplit = new SplitText(headingRef.current, { type: "words" });
gsap.fromTo(
headingSplit.words,
{ yPercent: 120, opacity: 0 },
{
yPercent: 0,
opacity: 1,
duration: 1.2,
ease: "expo.out",
stagger: 0.09,
delay: 0.3, // after navbar
}
);
// ── 3. SUB-HEADING char-by-char ───────────────────────────────
if (subHeadingRef.current) {
const subSplit = new SplitText(subHeadingRef.current, {
type: "words",
});
gsap.fromTo(
subSplit.words,
{ yPercent: 100, opacity: 0 },
{
yPercent: 0,
opacity: 1,
duration: 1,
ease: "expo.out",
stagger: 0.04,
delay: 0.6, // after heading
}
);
}
// ── 4. BUTTONS slide up ───────────────────────────────────────
const buttons = buttonWrapperRef.current?.children;
if (buttons?.length) {
gsap.fromTo(
buttons,
{ y: 40, opacity: 0 },
{
y: 0,
opacity: 1,
duration: 0.8,
ease: "power3.out",
stagger: 0.15,
delay: 0.9, // after sub-heading
}
);
}
}, containerRef);
// ── Cleanup ────────────────────────────────────────────────────────
return () => ctx.revert();
}, []);
return (
<section
ref={containerRef}
id="home"
className="font-switzer tab:p-5 tab:h-[110vh] mx-auto max-h-[900px] w-full max-w-[1650px] overflow-hidden sm:h-screen sm:p-2.5"
>
{/* ── Desktop Navbar (wrapped) ───────────────────────────────────── */}
<Navbar />
{/* ── Mobile Navbar (wrapped) ────────────────────────────────────── */}
<MobileNavbar />
{/* ── Hero Content ───────────────────────────────────────────────── */}
<div className="relative mx-auto flex h-full w-full items-center justify-center overflow-hidden rounded-2xl">
<video
autoPlay
muted
loop
playsInline
className="absolute inset-0 h-full w-full object-cover"
>
<source src="/video/video-1.mp4" type="video/mp4" />
Your browser does not support the video tag.
</video>
<div className="tab:p-0 tab:mt-0 tab:max-w-[600px] relative z-20 mx-auto flex flex-col gap-5 sm:mt-10 sm:px-3 md:max-w-[750px] lg:max-w-[850px]">
{/* Heading */}
<h1
ref={headingRef}
className="font-switzer sm:text-hero-mobile tab:text-h-2-60 lg:text-h-1-96 tab:leading-h2 text-center font-semibold text-white sm:leading-[54px] md:text-[75px] md:leading-[75px]"
>
Trees can talk. We help you{" "}
<span className="font-playfair font-semibold italic">listen.</span>
</h1>
{/* Sub-heading */}
<p
ref={subHeadingRef}
className="font-mium-reg tab:text-b-3-16 lg:text-b-1-20 sm:text-b-3-16 w-full text-center leading-normal text-white sm:tracking-[-0.6px]"
>
Whispering Trees shows you if a tree is healthy or thirsty in real
time. So you water only when needed, save money, and keep trees
alive longer.
</p>
{/* Buttons */}
<div
ref={buttonWrapperRef}
className="tab:gap-5 flex w-full justify-center sm:flex-wrap sm:gap-3"
>
<Button text="Tree for Free" />
<SecondaryButton targetId="how-it-works" text="How It Works" />
</div>
</div>
{/* Blob overlay */}
<Image
src="/images/png/Blob 5.png"
width={700}
height={500}
alt="overlay"
className="tab:h-[550px] absolute bottom-0 left-0 w-full object-cover sm:h-[70vh]"
/>
</div>
</section>
);
};
export default Hero;