@@ -2,6 +2,7 @@ import React, { useState, useEffect } from 'react';
2
2
3
3
const Navbar = ( { onToggle } ) => {
4
4
const [ isOpen , setIsOpen ] = useState ( false ) ;
5
+ const [ hoveredItem , setHoveredItem ] = useState ( null ) ;
5
6
6
7
const handleMouseEnter = ( ) => {
7
8
setIsOpen ( true ) ;
@@ -11,35 +12,53 @@ const Navbar = ({ onToggle }) => {
11
12
const handleMouseLeave = ( ) => {
12
13
setIsOpen ( false ) ;
13
14
onToggle ( false ) ;
15
+ setHoveredItem ( null ) ; // Reset hovered item on mouse leave
14
16
} ;
15
17
16
- useEffect ( ( ) => {
17
- const handleResize = ( ) => {
18
- if ( window . innerWidth >= 600 ) {
19
- setIsOpen ( false ) ;
20
- onToggle ( false ) ;
21
- }
22
- } ;
23
-
24
- window . addEventListener ( 'resize' , handleResize ) ;
18
+ const handleItemHover = ( item ) => {
19
+ setHoveredItem ( item ) ;
20
+ } ;
25
21
26
- return ( ) => {
27
- window . removeEventListener ( 'resize' , handleResize ) ;
28
- } ;
29
- } , [ ] ) ;
22
+ const handleItemLeave = ( ) => {
23
+ setHoveredItem ( null ) ;
24
+ } ;
30
25
31
26
const smoothScroll = ( targetId ) => {
32
27
const targetElement = document . getElementById ( targetId ) ;
33
28
if ( targetElement ) {
34
29
const offsetTop = targetElement . getBoundingClientRect ( ) . top + window . pageYOffset ;
35
-
36
30
window . scrollTo ( {
37
31
top : offsetTop ,
38
32
behavior : 'smooth' ,
39
33
} ) ;
40
34
}
41
35
} ;
42
36
37
+ // Helper function to render animated text
38
+ const renderAnimatedText = ( item , text , shortText ) => {
39
+ return (
40
+ < span className = "inline-block overflow-hidden" >
41
+ { isOpen ? (
42
+ < span className = "flex" >
43
+ { text . split ( '' ) . map ( ( letter , index ) => (
44
+ < span
45
+ key = { index }
46
+ className = { `letter ${
47
+ hoveredItem === item ? 'animate-letter' : ''
48
+ } `}
49
+ style = { { animationDelay : `${ index * 0.1 } s` } }
50
+ >
51
+ { letter }
52
+ </ span >
53
+ ) ) }
54
+ </ span >
55
+ ) : (
56
+ shortText
57
+ ) }
58
+ </ span >
59
+ ) ;
60
+ } ;
61
+
43
62
return (
44
63
< nav
45
64
className = { `fixed top-1/2 right-0 w-16 sm:w-32 h-[300px] bg-gray-800 bg-opacity-70 text-white transition-all duration-300 transform -translate-y-1/2 ${
@@ -58,11 +77,13 @@ const Navbar = ({ onToggle }) => {
58
77
href = "#"
59
78
className = "hover:text-blue-400 whitespace-nowrap text-shadow-lg"
60
79
onClick = { ( e ) => {
61
- e . preventDefault ( ) ;
80
+ e . preventDefault ( ) ;
62
81
smoothScroll ( 'hero' ) ;
63
82
} }
83
+ onMouseEnter = { ( ) => handleItemHover ( 'home' ) }
84
+ onMouseLeave = { handleItemLeave }
64
85
>
65
- { isOpen ? 'Home' : 'H' }
86
+ { renderAnimatedText ( 'home' , 'Home' , 'H' ) }
66
87
</ a >
67
88
</ li >
68
89
< li className = "mb-4" >
@@ -71,10 +92,12 @@ const Navbar = ({ onToggle }) => {
71
92
className = "hover:text-blue-400 whitespace-nowrap text-shadow-lg"
72
93
onClick = { ( e ) => {
73
94
e . preventDefault ( ) ;
74
- smoothScroll ( 'portfolio' ) ;
95
+ smoothScroll ( 'portfolio' ) ;
75
96
} }
97
+ onMouseEnter = { ( ) => handleItemHover ( 'projects' ) }
98
+ onMouseLeave = { handleItemLeave }
76
99
>
77
- { isOpen ? 'Projects' : 'P' }
100
+ { renderAnimatedText ( 'projects' , 'Projects' , 'P' ) }
78
101
</ a >
79
102
</ li >
80
103
< li >
@@ -85,8 +108,10 @@ const Navbar = ({ onToggle }) => {
85
108
e . preventDefault ( ) ;
86
109
smoothScroll ( 'contact' ) ;
87
110
} }
111
+ onMouseEnter = { ( ) => handleItemHover ( 'contact' ) }
112
+ onMouseLeave = { handleItemLeave }
88
113
>
89
- { isOpen ? 'Contact' : 'C' }
114
+ { renderAnimatedText ( 'contact' , 'Contact' , 'C' ) }
90
115
</ a >
91
116
</ li >
92
117
</ ul >
0 commit comments