Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin' into minor-edits
Browse files Browse the repository at this point in the history
  • Loading branch information
pranavvraja committed Nov 4, 2024
2 parents 3c78926 + 0a0c758 commit 3920738
Show file tree
Hide file tree
Showing 4 changed files with 159 additions and 127 deletions.
2 changes: 1 addition & 1 deletion src/components/ui/container-scroll-animation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export const ContainerScroll = ({
ref={containerRef}
>
<div
className="py-10 md:py-40 mt-96 w-full relative "
className="py-10 md:py-40 mt-80 md:mt-48 w-full relative "
style={{
perspective: "1000px",
}}
Expand Down
11 changes: 6 additions & 5 deletions src/components/ui/dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,16 +38,17 @@ const DialogContent = React.forwardRef<
<DialogPrimitive.Content
ref={ref}
className={cn(
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-2 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
className,
)}
{...props}
>
{children}
<DialogPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground">
<Cross2Icon className="h-4 w-4" />
<span className="sr-only">Close</span>
</DialogPrimitive.Close>
<DialogPrimitive.Close className="absolute w-20 h-20 -right-10 -top-4 rounded-sm transition-opacity hover:opacity-100 focus:outline-none disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground">
<Cross2Icon className="h-8 w-8" />
<span className="sr-only">Close</span>
</DialogPrimitive.Close>

</DialogPrimitive.Content>
</DialogPortal>
));
Expand Down
15 changes: 9 additions & 6 deletions src/components/widget/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -172,9 +171,13 @@ const Nav = () => {
<NavItem textOne="CONTACT" textTwo="CONTACT" onClick={() => handleClick('contact')} />
<li className="list-none listo overflow-hidden leading-[1] font-bold text-white mt-[30px]">
<Link href="/">
<button className="px-8 shadow-sm py-5 rounded-md bg-[#EB0028]">
REGISTER
</button>
<Button
size="lg"
className="bg-red-600 hover:bg-red-700 text-white py-4 "
>
Registrations Open Soon
{/* <ArrowRight className="ml-2" /> */}
</Button>
</Link>
</li>
</ul>
Expand Down
258 changes: 143 additions & 115 deletions src/components/widget/performers.tsx
Original file line number Diff line number Diff line change
@@ -1,68 +1,53 @@
/* 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[] = [
{
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<HTMLDivElement>(null);
const [currentImageIndices, setCurrentImageIndices] = useState<number[]>(
performerSections.map(() => 0)
);
const intervalRefs = useRef<(NodeJS.Timeout | null)[]>([]);
]

export default function Component() {
const containerRef = useRef<HTMLDivElement>(null)
const [currentImageIndices, setCurrentImageIndices] = useState<number[]>(performerSections.map(() => 0))
const intervalRefs = useRef<(NodeJS.Timeout | null)[]>([])
const [selectedSection, setSelectedSection] = useState<PerformerSection | null>(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<HTMLDivElement>(".img-container")
.forEach((container) => {
const img = container.querySelector("img");
const img = container.querySelector("img")

if (img) {
gsap.fromTo(
Expand All @@ -78,96 +63,139 @@ export default function Performers() {
end: "bottom top",
},
}
);
)
}
});

// Set up hover animations for description
gsap.utils
.toArray<HTMLDivElement>(".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<HTMLDivElement>(".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 (
<div ref={containerRef} className="overflow-hidden">
{performerSections.map((section, sectionIndex) => (
<section
key={sectionIndex}
className="flex md:max-w-[1200px] items-center justify-center relative mx-auto px-4 my-16 first:mt-0 last:mb-0"
aria-labelledby={`section-title-${sectionIndex}`}
>
<div className="relative w-full aspect-[16/9] overflow-hidden img-container performer-section">
{section.images.map((image, imageIndex) => (
<Dialog open={!!selectedSection} onOpenChange={(open) => !open && setSelectedSection(null)}>
<div ref={containerRef} className="overflow-hidden ">
{performerSections.map((section, sectionIndex) => (
<section
key={sectionIndex}
className="flex md:max-w-[1200px] items-center justify-center relative mx-auto px-4 my-24 first:mt-0 last:mb-0"
aria-labelledby={`section-title-${sectionIndex}`}
>
<div
className={`relative w-full aspect-[16/9] overflow-hidden img-container performer-section ${!isLargeScreen ? 'cursor-pointer' : ''}`}
onClick={() => handleSectionClick(section)}
>
{section.images.map((image, imageIndex) => (
<img
key={imageIndex}
src={image}
alt={`Performer section ${sectionIndex + 1}, slide ${imageIndex + 1} of ${section.images.length}`}
className={`absolute inset-0 w-full h-full object-cover transition-opacity duration-1000 ${imageIndex === currentImageIndices[sectionIndex] ? "opacity-100" : "opacity-0"}`}
aria-hidden={imageIndex !== currentImageIndices[sectionIndex]}
/>
))}
<div className="absolute inset-0 bg-black bg-opacity-40 flex flex-col justify-end p-8">
<h2
id={`section-title-${sectionIndex}`}
className="text-3xl md:text-5xl lg:text-6xl font-bold text-white mb-2"
>
{section.name}
</h2>
<p className="text-xl md:text-2xl text-white italic">
{section.profession}
</p>
</div>
<div className="description absolute inset-0 bg-black bg-opacity-75 flex items-center justify-center p-8 opacity-0 pointer-events-none lg:pointer-events-auto">
<p className="text-white text-lg md:text-xl lg:text-2xl text-center">
{section.description}
</p>
</div>
</div>
</section>
))}
</div>
{!isLargeScreen && selectedSection && (
<DialogContent className="rounded-md sm:max-w-[calc(95vw-15px)] max-w-[calc(100vw-15px)] max-h-[calc(100vh-15px)] overflow-hidden flex z-[999] items-center justify-center p-2">
<div className="flex flex-col md:flex-col gap-6 max-h-full overflow-y-auto p-2">
<div className="">
<img
key={imageIndex}
src={image}
alt={`Performer section ${sectionIndex + 1}, slide ${
imageIndex + 1
} of ${section.images.length}`}
className={`absolute inset-0 w-full h-full object-cover transition-opacity duration-1000 ${
imageIndex === currentImageIndices[sectionIndex]
? "opacity-100"
: "opacity-0"
}`}
aria-hidden={imageIndex !== currentImageIndices[sectionIndex]}
src={selectedSection.images[0]}
alt={`${selectedSection.name} - ${selectedSection.profession}`}
className="w-full h-auto object-cover rounded-lg"
/>
))}
<div className="absolute inset-0 bg-black bg-opacity-40 flex flex-col justify-end p-8">
<h2
id={`section-title-${sectionIndex}`}
className="text-3xl md:text-5xl lg:text-6xl font-bold text-white mb-2"
>
{section.name}
</h2>
<p className="text-xl md:text-2xl text-white italic">
{section.profession}
</p>
</div>
<div className="description absolute inset-0 bg-black bg-opacity-75 flex items-center justify-center p-8 opacity-0">
<p className="text-white text-lg md:text-xl lg:text-2xl text-center">
{section.description}
</p>
<div className="">
<h2 className="text-2xl font-bold mb-2">{selectedSection.name}</h2>
<p className="text-xl italic mb-4">{selectedSection.profession}</p>
<p className="text-base">{selectedSection.description}</p>
</div>
</div>
</section>
))}
</div>
);
</DialogContent>
)}
</Dialog>
)
}

0 comments on commit 3920738

Please sign in to comment.