1- import React , { useState } from "react" ;
1+ "use client" ;
2+
3+ import React , { useState , useEffect } from "react" ;
24import Link from "next/link" ;
35import { Menu , X , Slack } from "lucide-react" ;
46import Logo from "./Logo" ;
57import ThemeToggle from "./ThemeToggle" ;
68import GitHubStarButton from "./GitHubStarsButton" ;
79
810// constants/contact.ts
9- export const CONTACT_EMAIL = ' [email protected] ' ; 11+ export const CONTACT_EMAIL = " [email protected] " ; 1012export const CONTACT_MAILTO = `mailto:${ CONTACT_EMAIL } ` ;
1113
1214interface NavigationItem {
@@ -17,6 +19,8 @@ interface NavigationItem {
1719
1820const Navbar : React . FC = ( ) => {
1921 const [ isMenuOpen , setIsMenuOpen ] = useState ( false ) ;
22+ const [ activeSection , setActiveSection ] = useState < string > ( "" ) ;
23+ const [ scrolled , setScrolled ] = useState ( false ) ;
2024
2125 const navigation : NavigationItem [ ] = [
2226 { name : "Features" , href : "/#features" } ,
@@ -28,20 +32,52 @@ const Navbar: React.FC = () => {
2832 external : true ,
2933 } ,
3034 ] ;
35+
3136 const slackLink : NavigationItem = {
3237 name : "Slack" ,
3338 href : "https://join.slack.com/t/opsimate/shared_invite/zt-39bq3x6et-NrVCZzH7xuBGIXmOjJM7gA" ,
3439 external : true ,
3540 } ;
36- // New Contact link
41+
3742 const contactLink : NavigationItem = {
3843 name : "Contact Us" ,
3944 href : CONTACT_MAILTO ,
4045 external : true ,
4146 } ;
4247
48+ // Highlight active section on scroll
49+ useEffect ( ( ) => {
50+ const sections = document . querySelectorAll ( "section[id]" ) ;
51+ const observer = new IntersectionObserver (
52+ ( entries ) => {
53+ entries . forEach ( ( entry ) => {
54+ if ( entry . isIntersecting ) {
55+ setActiveSection ( entry . target . id ) ;
56+ }
57+ } ) ;
58+ } ,
59+ { rootMargin : "-50% 0px -50% 0px" }
60+ ) ;
61+
62+ sections . forEach ( ( section ) => observer . observe ( section ) ) ;
63+ return ( ) => sections . forEach ( ( section ) => observer . unobserve ( section ) ) ;
64+ } , [ ] ) ;
65+
66+ // Blur effect on scroll
67+ useEffect ( ( ) => {
68+ const handleScroll = ( ) => setScrolled ( window . scrollY > 20 ) ;
69+ window . addEventListener ( "scroll" , handleScroll ) ;
70+ return ( ) => window . removeEventListener ( "scroll" , handleScroll ) ;
71+ } , [ ] ) ;
72+
4373 return (
44- < nav className = "bg-surface-50 dark:bg-surface-950 shadow-sm border-b border-surface-200 dark:border-surface-800 sticky top-0 z-50 transition-colors duration-200" >
74+ < nav
75+ className = { `sticky top-0 z-50 border-b border-surface-200 dark:border-surface-800 transition-all duration-300 ${
76+ scrolled
77+ ? "navbar-blur shadow-md"
78+ : "bg-surface-50 dark:bg-surface-950 shadow-sm"
79+ } `}
80+ >
4581 < div className = "container-max" >
4682 < div className = "flex justify-between items-center py-4" >
4783 { /* Logo */ }
@@ -55,7 +91,11 @@ const Navbar: React.FC = () => {
5591 < Link
5692 key = { item . name }
5793 href = { item . href }
58- className = "text-surface-700 dark:text-surface-300 hover:text-primary-500 dark:hover:text-primary-400 font-medium transition-colors duration-200"
94+ className = { `nav-link text-surface-700 dark:text-surface-300 hover:text-primary-500 dark:hover:text-primary-400 font-medium ${
95+ activeSection === item . href . replace ( "/#" , "" )
96+ ? "nav-link-active"
97+ : ""
98+ } `}
5999 { ...( item . external && {
60100 target : "_blank" ,
61101 rel : "noopener noreferrer" ,
@@ -64,7 +104,9 @@ const Navbar: React.FC = () => {
64104 { item . name }
65105 </ Link >
66106 ) ) }
107+
67108 < GitHubStarButton />
109+
68110 < Link
69111 href = { slackLink . href }
70112 className = "text-surface-700 dark:text-surface-300 hover:text-primary-500 dark:hover:text-primary-400 font-medium transition-colors duration-200 inline-flex items-center gap-2"
@@ -77,13 +119,15 @@ const Navbar: React.FC = () => {
77119 < Slack size = { 18 } aria-hidden = "true" />
78120 { slackLink . name }
79121 </ Link >
80- { /* Contact Us button */ }
81- < a
122+
123+ { /* Contact Us button */ }
124+ < a
82125 href = { contactLink . href }
83126 className = "px-4 py-2 bg-primary-600 text-white rounded-lg hover:bg-primary-700 transition-colors duration-200"
84127 >
85128 { contactLink . name }
86129 </ a >
130+
87131 < ThemeToggle />
88132 </ div >
89133
@@ -106,7 +150,11 @@ const Navbar: React.FC = () => {
106150 < Link
107151 key = { item . name }
108152 href = { item . href }
109- className = "text-gray-700 hover:text-blue-600 font-medium transition-colors duration-200 px-2 py-1"
153+ className = { `text-gray-700 hover:text-blue-600 font-medium transition-colors duration-200 px-2 py-1 ${
154+ activeSection === item . href . replace ( "/#" , "" )
155+ ? "text-primary-600 dark:text-primary-400"
156+ : ""
157+ } `}
110158 onClick = { ( ) => setIsMenuOpen ( false ) }
111159 { ...( item . external && {
112160 target : "_blank" ,
@@ -116,6 +164,7 @@ const Navbar: React.FC = () => {
116164 { item . name }
117165 </ Link >
118166 ) ) }
167+
119168 { /* Mobile Contact Us link */ }
120169 < a
121170 href = { contactLink . href }
0 commit comments