@@ -8,63 +8,58 @@ import ProjectButton from "./ProjectButton";
8
8
import { ProjectItemProps } from "./types" ;
9
9
10
10
export default function ProjectItem ( { repo, index } : ProjectItemProps ) {
11
- // Track if component is in viewport for animation
12
- const { ref, inView } = useInView ( {
13
- triggerOnce : false ,
14
- } ) ;
11
+ const { ref, inView } = useInView ( { triggerOnce : true } ) ;
12
+
13
+ const isReversed = index % 2 === 0 ;
15
14
16
15
return (
17
16
< motion . div
18
17
ref = { ref }
19
- key = { repo . documentId }
20
- className = { `flex flex-col items-center justify-between gap-12 text-center sm:flex-row sm:text-left ${
21
- index % 2 === 0 ? "sm:flex-row-reverse" : ""
18
+ className = { `flex flex-col-reverse items-center justify-between gap-12 sm:flex-row ${
19
+ isReversed ? "sm:flex-row-reverse" : ""
22
20
} `}
23
- initial = { { opacity : 0 } }
24
- animate = { { opacity : inView ? 1 : 0 } }
25
- transition = { { duration : 0.3 } }
21
+ initial = { { opacity : 0 , y : 50 } }
22
+ animate = { { opacity : inView ? 1 : 0 , y : inView ? 0 : 50 } }
23
+ transition = { { duration : 0.6 , ease : "easeOut" } }
26
24
>
27
- { /* Project content - alternates left/right based on index */ }
28
- < div className = "mx-auto w-full md:w-1/2 lg:w-1/2" >
29
- < motion . h1
30
- className = "mb-4 max-w-2xl text-4xl font-extrabold leading-none tracking-tight dark:text-white md:text-5xl xl:text-6xl"
31
- initial = { { y : - 50 , opacity : 0 } }
32
- animate = { { y : 0 , opacity : 1 } }
33
- transition = { { duration : 0.3 } }
25
+ < div className = "w-full sm:w-1/2" >
26
+ < motion . h2
27
+ className = "mb-4 text-3xl font-extrabold tracking-tight text-gray-900 dark:text-white sm:text-4xl"
28
+ initial = { { opacity : 0 , y : - 20 } }
29
+ animate = { { opacity : inView ? 1 : 0 , y : inView ? 0 : - 20 } }
30
+ transition = { { delay : 0.1 , duration : 0.4 } }
34
31
>
35
32
{ repo . name }
36
- </ motion . h1 >
33
+ </ motion . h2 >
34
+
37
35
< motion . p
38
- className = "mb-6 max-w-2xl font-light text-gray-500 dark:text-gray-400 md:text-lg lg:mb-8 lg:text-xl "
39
- initial = { { y : - 50 , opacity : 0 } }
40
- animate = { { y : 0 , opacity : 1 } }
41
- transition = { { duration : 0.3 } }
36
+ className = "mb-6 text-gray-600 dark:text-gray-400"
37
+ initial = { { opacity : 0 , y : - 20 } }
38
+ animate = { { opacity : inView ? 1 : 0 , y : inView ? 0 : - 20 } }
39
+ transition = { { delay : 0.2 , duration : 0.4 } }
42
40
>
43
41
{ repo . description }
44
42
</ motion . p >
45
- < div className = "flex justify-center sm:justify-start" >
46
- < a href = { repo . repository_url } target = "_blank" rel = "noreferrer" >
47
- < ProjectButton title = "Repository" />
48
- </ a >
49
- </ div >
43
+
44
+ < a href = { repo . repository_url } target = "_blank" rel = "noreferrer" >
45
+ < ProjectButton title = "Repository" />
46
+ </ a >
50
47
</ div >
51
48
52
- { /* Project image with animation */ }
53
- < div className = "w-full overflow-hidden md:w-1/2 lg:w-1/2" >
49
+ < div className = "w-full sm:w-1/2 overflow-hidden rounded-xl shadow-lg" >
54
50
< motion . div
55
- initial = { { y : - 50 , opacity : 0 } }
56
- animate = { { y : 0 , opacity : 1 } }
57
- transition = { { duration : 0.3 } }
51
+ className = "group relative"
52
+ initial = { { scale : 0.98 , opacity : 0 } }
53
+ animate = { { scale : inView ? 1 : 0.98 , opacity : inView ? 1 : 0 } }
54
+ transition = { { delay : 0.1 , duration : 0.5 } }
58
55
>
59
56
< Image
60
- alt = { `${ repo . name } project image` }
61
57
src = { repo . banner_url }
62
- className = "mx-auto hidden rounded-xl object-cover sm:block"
63
- height = { 500 }
58
+ alt = { repo . name }
64
59
width = { 1000 }
65
- priority = { index < 2 }
60
+ height = { 500 }
61
+ className = "h-auto w-full transform object-cover transition-transform duration-500 group-hover:scale-105"
66
62
quality = { 85 }
67
- sizes = "(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
68
63
/>
69
64
</ motion . div >
70
65
</ div >
0 commit comments