|
1 | | -import React from 'react'; |
2 | | -import { motion } from 'framer-motion'; |
| 1 | +import React, { useRef } from 'react'; |
| 2 | +import { motion, useScroll, useTransform } from 'framer-motion'; |
3 | 3 | import { roadmapItems, roadmapContent } from '@/constants/aboutUs/roadmap'; |
4 | 4 |
|
5 | 5 | const RoadmapSection: React.FC = () => { |
| 6 | + const sectionRef = useRef<HTMLElement>(null); |
| 7 | + const timelineRef = useRef<HTMLDivElement>(null); |
| 8 | + const mobileTimelineRef = useRef<HTMLDivElement>(null); |
| 9 | + |
| 10 | + const { scrollYProgress } = useScroll({ |
| 11 | + target: sectionRef, |
| 12 | + offset: ['start end', 'end start'], |
| 13 | + }); |
| 14 | + |
| 15 | + const progressHeight = useTransform( |
| 16 | + scrollYProgress, |
| 17 | + [0, 0.8], |
| 18 | + ['0%', '100%'], |
| 19 | + ); |
| 20 | + |
| 21 | + const mobileProgressHeight = useTransform( |
| 22 | + scrollYProgress, |
| 23 | + [0, 0.8], |
| 24 | + ['0%', '100%'], |
| 25 | + ); |
| 26 | + |
6 | 27 | return ( |
7 | 28 | <section |
| 29 | + ref={sectionRef} |
8 | 30 | id={roadmapContent.sectionId} |
9 | 31 | className="w-full py-24 bg-white dark:bg-gray-900" |
10 | 32 | > |
@@ -45,13 +67,14 @@ const RoadmapSection: React.FC = () => { |
45 | 67 | </motion.p> |
46 | 68 | </div> |
47 | 69 |
|
48 | | - <div className="hidden md:block relative w-full mt-20"> |
| 70 | + <div |
| 71 | + ref={timelineRef} |
| 72 | + className="hidden md:block relative w-full mt-20" |
| 73 | + > |
| 74 | + <div className="absolute top-0 bottom-0 left-1/2 w-0.5 bg-gray-200 dark:bg-gray-600/50 transform -translate-x-1/2" /> |
49 | 75 | <motion.div |
50 | | - className="absolute top-0 bottom-0 left-1/2 w-0.5 bg-gray-200 dark:bg-gray-600/50 transform -translate-x-1/2" |
51 | | - initial={{ scaleY: 0, transformOrigin: 'top' }} |
52 | | - whileInView={{ scaleY: 1 }} |
53 | | - viewport={{ once: true }} |
54 | | - transition={{ duration: 1.2 }} |
| 76 | + className="absolute top-0 left-1/2 w-0.5 bg-gradient-to-b from-blue-500 via-purple-500 to-red-500 transform -translate-x-1/2 origin-top" |
| 77 | + style={{ height: progressHeight }} |
55 | 78 | /> |
56 | 79 |
|
57 | 80 | {/* Roadmap items */} |
@@ -102,18 +125,19 @@ const RoadmapSection: React.FC = () => { |
102 | 125 | </div> |
103 | 126 |
|
104 | 127 | {/* Mobile Timeline - Single Column */} |
105 | | - <div className="md:hidden relative w-full mt-16"> |
| 128 | + <div |
| 129 | + ref={mobileTimelineRef} |
| 130 | + className="md:hidden relative w-full mt-16" |
| 131 | + > |
106 | 132 | <div className="flex flex-col items-start space-y-12"> |
107 | | - {/* Vertical connecting line */} |
108 | | - <motion.div |
| 133 | + <div |
109 | 134 | className="absolute top-0 bottom-0 left-5 w-0.5 bg-slate-200 dark:bg-gray-700 h-full" |
110 | 135 | style={{ zIndex: 1 }} |
111 | | - initial={{ scaleY: 0, transformOrigin: 'top' }} |
112 | | - whileInView={{ scaleY: 1 }} |
113 | | - viewport={{ once: true }} |
114 | | - transition={{ duration: 1.2 }} |
115 | 136 | /> |
116 | | - |
| 137 | + <motion.div |
| 138 | + className="absolute top-0 left-5 w-0.5 bg-gradient-to-b from-blue-500 via-purple-500 to-red-500 origin-top" |
| 139 | + style={{ height: mobileProgressHeight, zIndex: 2 }} |
| 140 | + /> |
117 | 141 | {roadmapItems.map((item, index) => ( |
118 | 142 | <motion.div |
119 | 143 | key={index} |
|
0 commit comments