diff --git a/src/components/ui/container-scroll-animation.tsx b/src/components/ui/container-scroll-animation.tsx index f7a598e..fe3e675 100644 --- a/src/components/ui/container-scroll-animation.tsx +++ b/src/components/ui/container-scroll-animation.tsx @@ -40,7 +40,7 @@ export const ContainerScroll = ({ ref={containerRef} >
{children} - - - Close - + + + Close + + )); diff --git a/src/components/widget/header.tsx b/src/components/widget/header.tsx index dae2807..33b1bdb 100644 --- a/src/components/widget/header.tsx +++ b/src/components/widget/header.tsx @@ -7,9 +7,8 @@ import { ScrollTrigger } from "gsap/ScrollTrigger"; import { tedxsjecAssetsPrefix } from "@/lib/utils"; import React from "react"; import Link from "next/link"; -import SocialLinks from "../common/social-links"; import NavItem from "../navbar/nav-items"; - +import { Button } from "../ui/button"; const Nav = () => { gsap.registerPlugin(ScrollTrigger); @@ -87,7 +86,7 @@ const Nav = () => { if (targetId) { const targetElement = document.getElementById(targetId); if (targetElement) { - const offset = targetElement.getBoundingClientRect().top + window.scrollY - (window.innerHeight * 0.1); + const offset = targetElement.getBoundingClientRect().top + window.scrollY - (window.innerHeight * 0.12); window.scrollTo({ top: offset, behavior: "smooth", @@ -172,9 +171,13 @@ const Nav = () => { handleClick('contact')} />
  • - +
  • diff --git a/src/components/widget/performers.tsx b/src/components/widget/performers.tsx index 58f05ee..24e1179 100644 --- a/src/components/widget/performers.tsx +++ b/src/components/widget/performers.tsx @@ -1,20 +1,19 @@ -/* eslint-disable @next/next/no-img-element */ -"use client"; +"use client" -import { useEffect, useRef, useState } from "react"; -import { gsap } from "gsap"; -import { ScrollTrigger } from "gsap/ScrollTrigger"; -import Lenis from "@studio-freight/lenis"; -import { useGSAP } from "@gsap/react"; -import { tedxsjecAssetsPrefix } from "@/lib/utils"; - -gsap.registerPlugin(ScrollTrigger); +import { useEffect, useRef, useState } from "react" +import { gsap } from "gsap" +import { ScrollTrigger } from "gsap/ScrollTrigger" +import Lenis from "@studio-freight/lenis" +import { useGSAP } from "@gsap/react" +import { tedxsjecAssetsPrefix } from "@/lib/utils" +import { Dialog, DialogContent } from "@/components/ui/dialog" +gsap.registerPlugin(ScrollTrigger) interface PerformerSection { - images: string[]; - name: String; - profession: string; - description: string; + images: string[] + name: string + profession: string + description: string } const performerSections: PerformerSection[] = [ @@ -22,47 +21,33 @@ const performerSections: PerformerSection[] = [ name: "Yukthi Udupa", profession: "Bharatanatyam artist", description: - "Yukthi Udupa, a passionate Bharatanatyam artist, began her journey at 12 under Guru Vid Smt. Pravitha Ashok at Nritya Vasantha Natyalaya® Kundapura. She completed her “Vidwath” exams with distinction and earned the Karnataka State Music and Dance Scholarship. Yukthi has won numerous awards, including “Natya Sammohini,” “Yuva Kala Prashasti,” and the “Kalashree Award,” excelling in international, national, and state-level competitions. Her Bharatanatyam Arangetram was a celebrated display of her technical skill and expressive artistry. Yukthi is also a ‘B’ grade Doordarshan artist, inspiring young dancers and honoring Bharatanatyam's legacy.", + "Yukthi Udupa, a passionate Bharatanatyam artist, began her journey at 12 under Guru Vid Smt. Pravitha Ashok at Nritya Vasantha Natyalaya® Kundapura. She completed her exams with distinction and earned the Karnataka State Music and Dance Scholarship. Yukthi has won numerous awards, including and the excelling in international, national, and state-level competitions. Her Bharatanatyam Arangetram was a celebrated display of her technical skill and expressive artistry. Yukthi is also a 'B' grade Doordarshan artist, inspiring young dancers and honoring Bharatanatyam's legacy.", images: [ `${tedxsjecAssetsPrefix}/performers/Yukthi1.avif`, - // `${tedxsjecAssetsPrefix}/performers/Yukthi1.avif`, - // `${tedxsjecAssetsPrefix}/performers/Yukthi1.avif`, - // `${tedxsjecAssetsPrefix}/performers/Yukthi2.avif`, ], }, - // { - // name: "Agasthyam Kalaripayattu", - // profession: "Martial Arts Institution", - // description: - // "Agasthyam Kalaripayattu, a premier martial arts institution, preserves and teaches the ancient art of Kalaripayattu from Kerala, India. Founded and led by Gurukkal S Mahesh, Agasthyam continues a legacy over 129 years old, deeply rooted in traditional combat techniques, self-defense, weaponry, and spiritual growth. This renowned school offers rigorous training that builds agility, strength, and resilience, merging physical discipline with profound cultural heritage. Agasthyam is a respected destination for those who seek not only to master Kalaripayattu but also to forge a deeper, spiritual connection to this timeless art form.", - // images: [ - // `${tedxsjecAssetsPrefix}/performers/Agasthyam1.avif`, - // // `${tedxsjecAssetsPrefix}/performers/Agasthyam2.avif`, - // // `${tedxsjecAssetsPrefix}/performers/Agasthyam3.avif`, - // ], - // }, -]; - -export default function Performers() { - const containerRef = useRef(null); - const [currentImageIndices, setCurrentImageIndices] = useState( - performerSections.map(() => 0) - ); - const intervalRefs = useRef<(NodeJS.Timeout | null)[]>([]); +] + +export default function Component() { + const containerRef = useRef(null) + const [currentImageIndices, setCurrentImageIndices] = useState(performerSections.map(() => 0)) + const intervalRefs = useRef<(NodeJS.Timeout | null)[]>([]) + const [selectedSection, setSelectedSection] = useState(null) + const [isLargeScreen, setIsLargeScreen] = useState(false) useGSAP(() => { - const lenis = new Lenis({ lerp: 0.07 }); + const lenis = new Lenis({ lerp: 0.07 }) - lenis.on("scroll", ScrollTrigger.update); + lenis.on("scroll", ScrollTrigger.update) gsap.ticker.add((time) => { - lenis.raf(time * 1000); - }); + lenis.raf(time * 1000) + }) gsap.utils .toArray(".img-container") .forEach((container) => { - const img = container.querySelector("img"); + const img = container.querySelector("img") if (img) { gsap.fromTo( @@ -78,96 +63,139 @@ export default function Performers() { end: "bottom top", }, } - ); + ) } - }); - - // Set up hover animations for description - gsap.utils - .toArray(".performer-section") - .forEach((section) => { - const description = section.querySelector(".description"); - const tl = gsap.timeline({ paused: true }); - - tl.fromTo( - description, - { yPercent: 100, opacity: 0 }, - { yPercent: 0, opacity: 1, duration: 0.3, ease: "power2.out" } - ); - - section.addEventListener("mouseenter", () => tl.play()); - section.addEventListener("mouseleave", () => tl.reverse()); - }); + }) + + // Set up hover animations for description on desktop + const mm = gsap.matchMedia() + + mm.add("(min-width: 1200px)", () => { + setIsLargeScreen(true) + gsap.utils + .toArray(".performer-section") + .forEach((section) => { + const description = section.querySelector(".description") + const tl = gsap.timeline({ paused: true }) + + tl.fromTo( + description, + { yPercent: 100, opacity: 0 }, + { yPercent: 0, opacity: 1, duration: 0.3, ease: "power2.out" } + ) + + section.addEventListener("mouseenter", () => tl.play()) + section.addEventListener("mouseleave", () => tl.reverse()) + }) + }) + + mm.add("(max-width: 1200px)", () => { + setIsLargeScreen(false) + }) return () => { - lenis.destroy(); - ScrollTrigger.getAll().forEach((st) => st.kill()); - }; - }, []); + lenis.destroy() + ScrollTrigger.getAll().forEach((st) => st.kill()) + mm.revert() + } + }, []) useEffect(() => { performerSections.forEach((_, index) => { intervalRefs.current[index] = setInterval(() => { setCurrentImageIndices((prevIndices) => { - const newIndices = [...prevIndices]; + const newIndices = [...prevIndices] newIndices[index] = - (newIndices[index] + 1) % performerSections[index].images.length; - return newIndices; - }); - }, 2500 + index * 1000); // Stagger the intervals to make the changes less synchronized - }); + (newIndices[index] + 1) % performerSections[index].images.length + return newIndices + }) + }, 2500 + index * 1000) + }) return () => { - // eslint-disable-next-line react-hooks/exhaustive-deps intervalRefs.current.forEach((interval) => { - if (interval) clearInterval(interval); - }); - }; - }, []); + if (interval) clearInterval(interval) + }) + } + }, []) + + const handleSectionClick = (section: PerformerSection) => { + if (!isLargeScreen) { + setSelectedSection(section) + } + } + + // Effect to disable body scroll when dialog is open + useEffect(() => { + if (selectedSection) { + document.body.classList.add("no-scroll") + } else { + document.body.classList.remove("no-scroll") + } + + return () => document.body.classList.remove("no-scroll") + }, [selectedSection]) return ( -
    - {performerSections.map((section, sectionIndex) => ( -
    -
    - {section.images.map((image, imageIndex) => ( + !open && setSelectedSection(null)}> +
    + {performerSections.map((section, sectionIndex) => ( +
    +
    handleSectionClick(section)} + > + {section.images.map((image, imageIndex) => ( + {`Performer + ))} +
    +

    + {section.name} +

    +

    + {section.profession} +

    +
    +
    +

    + {section.description} +

    +
    +
    +
    + ))} +
    + {!isLargeScreen && selectedSection && ( + +
    +
    {`Performer - ))} -
    -

    - {section.name} -

    -

    - {section.profession} -

    -
    -

    - {section.description} -

    +
    +

    {selectedSection.name}

    +

    {selectedSection.profession}

    +

    {selectedSection.description}

    -
    - ))} -
    - ); + + )} + + ) }