@@ -12,16 +12,25 @@ interface ProductCarouselProps {
1212 slides : CarouselSlide [ ] ;
1313 autoplayDelay ?: number ;
1414 videoUrl ?: string ;
15+ rightPanel ?: React . ReactNode ;
1516}
1617
1718const ProductCarousel : React . FC < ProductCarouselProps > = ( {
1819 slides,
1920 autoplayDelay = 5000 ,
2021 videoUrl = "https://framerusercontent.com/assets/sRXQsZpCuTpukMUfotGcRUuvg.mp4" ,
22+ rightPanel,
2123} ) => {
2224 const [ currentIndex , setCurrentIndex ] = useState ( 0 ) ;
2325 const [ videoLoaded , setVideoLoaded ] = useState ( false ) ;
2426 const [ videoError , setVideoError ] = useState ( false ) ;
27+ const [ isMobile , setIsMobile ] = useState ( ( ) => window . innerWidth < 1024 ) ;
28+
29+ useEffect ( ( ) => {
30+ const handleResize = ( ) => setIsMobile ( window . innerWidth < 1024 ) ;
31+ window . addEventListener ( "resize" , handleResize ) ;
32+ return ( ) => window . removeEventListener ( "resize" , handleResize ) ;
33+ } , [ ] ) ;
2534
2635 useEffect ( ( ) => {
2736 if ( slides . length <= 1 ) return ;
@@ -63,57 +72,65 @@ const ProductCarousel: React.FC<ProductCarouselProps> = ({
6372 </ div >
6473
6574 { /* Carousel Content */ }
66- < div className = "relative w-full h-[350px] md:h-[450px] lg:h-[500px] z-10 pt-24 md:pt-32" >
67- { /* Animated Text Content */ }
75+ < div className = "relative w-full h-auto lg:h-[500px] z-10 pt-20 pb-8 lg:pt-32 lg:pb-0" >
6876 < div className = "relative z-10 h-full flex items-center" >
69- < div className = "container mx-auto px-4 md:px-8 lg:px-16" >
70- < div className = "max-w-3xl" >
71- < AnimatePresence mode = "wait" >
72- < motion . div
73- key = { currentSlide . id }
74- initial = { { opacity : 0 , x : - 60 , scale : 0.95 } }
75- animate = { { opacity : 1 , x : 0 , scale : 1 } }
76- exit = { { opacity : 0 , x : 60 , scale : 0.95 } }
77- transition = { { duration : 1 , ease : [ 0.22 , 1 , 0.36 , 1 ] } }
78- >
79- { currentSlide . subtitle && (
80- < motion . p
81- className = "text-blue-400 font-semibold text-xs md:text-sm lg:text-base uppercase tracking-wider mb-2 md:mb-3"
82- initial = { { opacity : 0 , x : - 40 } }
83- animate = { { opacity : 1 , x : 0 } }
84- transition = { { delay : 0.2 , duration : 0.8 , ease : "easeOut" } }
85- >
86- { currentSlide . subtitle }
87- </ motion . p >
88- ) }
89- < motion . h2
90- className = "text-3xl md:text-5xl lg:text-7xl xl:text-8xl font-bold text-white mb-2 md:mb-3 leading-tight"
91- initial = { { opacity : 0 , x : - 50 , rotateX : - 15 } }
92- animate = { { opacity : 1 , x : 0 , rotateX : 0 } }
93- transition = { { delay : 0.3 , duration : 0.9 , ease : [ 0.22 , 1 , 0.36 , 1 ] } }
77+ < div className = "container mx-auto px-4 md:px-8 lg:px-16 w-full" >
78+ < div className = "flex flex-col items-center gap-8 lg:flex-row lg:justify-center lg:gap-24 xl:gap-48" >
79+ { /* Left: animated text */ }
80+ < div className = "w-full lg:w-72 xl:w-[408px] lg:shrink-0" >
81+ < AnimatePresence mode = "wait" >
82+ < motion . div
83+ key = { currentSlide . id }
84+ initial = { { opacity : 0 , x : isMobile ? 0 : - 60 , scale : 0.95 } }
85+ animate = { { opacity : 1 , x : 0 , scale : 1 } }
86+ exit = { { opacity : 0 , x : isMobile ? 0 : 60 , scale : 0.95 } }
87+ transition = { { duration : 1 , ease : [ 0.22 , 1 , 0.36 , 1 ] } }
9488 >
95- { currentSlide . title }
96- </ motion . h2 >
97- { currentSlide . description && (
98- < motion . p
99- className = "text-gray-300 text-sm md:text-lg lg:text-2xl mb-6 md:mb-10 max-w-2xl"
100- initial = { { opacity : 0 , x : - 40 } }
101- animate = { { opacity : 1 , x : 0 } }
102- transition = { { delay : 0.5 , duration : 0.8 , ease : "easeOut" } }
89+ { currentSlide . subtitle && (
90+ < motion . p
91+ className = "text-blue-400 font-semibold text-xs md:text-sm uppercase tracking-wider mb-2"
92+ initial = { { opacity : 0 , x : isMobile ? 0 : - 40 } }
93+ animate = { { opacity : 1 , x : 0 } }
94+ transition = { { delay : 0.2 , duration : 0.8 , ease : "easeOut" } }
95+ >
96+ { currentSlide . subtitle }
97+ </ motion . p >
98+ ) }
99+ < motion . h2
100+ className = "text-3xl md:text-4xl lg:text-5xl xl:text-6xl font-bold text-white mb-3 leading-tight"
101+ initial = { { opacity : 0 , x : isMobile ? 0 : - 50 , rotateX : - 15 } }
102+ animate = { { opacity : 1 , x : 0 , rotateX : 0 } }
103+ transition = { { delay : 0.3 , duration : 0.9 , ease : [ 0.22 , 1 , 0.36 , 1 ] } }
103104 >
104- { currentSlide . description }
105- </ motion . p >
106- ) }
107- </ motion . div >
108- </ AnimatePresence >
105+ { currentSlide . title }
106+ </ motion . h2 >
107+ { currentSlide . description && (
108+ < motion . p
109+ className = "text-gray-300 text-sm md:text-base mb-6 md:mb-8 max-w-sm"
110+ initial = { { opacity : 0 , x : isMobile ? 0 : - 40 } }
111+ animate = { { opacity : 1 , x : 0 } }
112+ transition = { { delay : 0.5 , duration : 0.8 , ease : "easeOut" } }
113+ >
114+ { currentSlide . description }
115+ </ motion . p >
116+ ) }
117+ </ motion . div >
118+ </ AnimatePresence >
119+
120+ < a
121+ href = "#products"
122+ className = "inline-block bg-blue-500/10 backdrop-blur-xl border border-blue-400/20 hover:bg-blue-500/20 hover:border-blue-400/40 text-white font-semibold px-6 py-3 rounded-lg transition-all duration-300 hover:scale-105 shadow-lg shadow-blue-500/10 text-sm md:text-base"
123+ >
124+ Shop Now
125+ </ a >
126+ </ div >
109127
110- { /* Static CTA Button */ }
111- < a
112- href = "#products"
113- className = "inline-block bg-blue-500/10 backdrop-blur-xl border border-blue-400/20 hover:bg-blue-500/20 hover:border-blue-400/40 text-white font-semibold px-6 py-3 md:px-10 md:py-4 rounded-lg md:rounded-xl transition-all duration-300 hover:scale-105 shadow-lg shadow-blue-500/10 text-sm md:text-base lg:text-lg"
114- >
115- Shop Now
116- </ a >
128+ { /* Right: optional panel (e.g. points table) */ }
129+ { rightPanel && (
130+ < div className = "w-full max-h-[45vh] overflow-y-auto lg:max-h-none lg:overflow-visible lg:w-[440px] lg:shrink-0" >
131+ { rightPanel }
132+ </ div >
133+ ) }
117134 </ div >
118135 </ div >
119136 </ div >
0 commit comments