Implement auto-hiding sticky navbar on scroll and pointer-event safe smooth scroll

This commit is contained in:
Vishva
2026-07-30 10:36:30 +05:30
parent 80ae755825
commit 48f8ab9716
+60 -15
View File
@@ -380,6 +380,30 @@ export default function App({ previewMode = false }) {
const [isCareersOpen, setIsCareersOpen] = useState(false);
const [activeSection, setActiveSection] = useState('home');
const [currentPage, setCurrentPage] = useState('home');
const [navbarVisible, setNavbarVisible] = useState(true);
const lastScrollY = useRef(0);
const smoothScrollTo = (top) => {
document.body.style.pointerEvents = 'none';
window.scrollTo({ top, behavior: 'smooth' });
let scrollTimeout;
const handleScrollEnd = () => {
document.body.style.pointerEvents = '';
window.removeEventListener('scrollend', handleScrollEnd);
window.removeEventListener('scroll', handleScrollDebounce);
clearTimeout(scrollTimeout);
};
const handleScrollDebounce = () => {
clearTimeout(scrollTimeout);
scrollTimeout = setTimeout(handleScrollEnd, 100);
};
window.addEventListener('scrollend', handleScrollEnd);
window.addEventListener('scroll', handleScrollDebounce);
scrollTimeout = setTimeout(handleScrollEnd, 800);
};
useEffect(() => {
const syncPageFromHash = () => {
@@ -387,11 +411,11 @@ export default function App({ previewMode = false }) {
if (hash === '#contact' || hash === '#contactus') {
setCurrentPage('contact');
setActiveSection('contactus');
window.scrollTo({ top: 0, behavior: 'smooth' });
smoothScrollTo(0);
} else if (hash === '#about' || hash === '#aboutus') {
setCurrentPage('about');
setActiveSection('aboutus');
window.scrollTo({ top: 0, behavior: 'smooth' });
smoothScrollTo(0);
} else if (hash === '#home' || hash === '') {
setCurrentPage('home');
}
@@ -461,20 +485,36 @@ export default function App({ previewMode = false }) {
}, []);
useEffect(() => {
if (previewMode || currentPage === 'contact') return;
if (previewMode) return;
let lastScroll = window.scrollY;
const handleScroll = () => {
const currentScroll = window.scrollY;
const diff = currentScroll - lastScroll;
if (currentScroll <= 50) {
setNavbarVisible(true);
} else if (diff > 5 && currentScroll > 100) {
setNavbarVisible(false);
} else if (diff < -5) {
setNavbarVisible(true);
}
lastScroll = currentScroll;
if (currentPage === 'home') {
// If at top of the page, home is active
if (window.scrollY < 100) {
if (currentScroll < 100) {
setActiveSection('home');
return;
}
const sections = ['home', 'aboutus', 'services', 'whyus', 'products', 'insights', 'contactus'];
const scrollPosition = window.scrollY + 120; // 120px offset for header height and visual center
const scrollPosition = currentScroll + 120; // 120px offset for header height and visual center
// Special case: if scrolled down near the very bottom of the page, contactus is active
if (window.scrollY > 300 && window.innerHeight + window.scrollY >= document.documentElement.scrollHeight - 100) {
if (currentScroll > 300 && window.innerHeight + currentScroll >= document.documentElement.scrollHeight - 100) {
setActiveSection('contactus');
return;
}
@@ -490,12 +530,13 @@ export default function App({ previewMode = false }) {
}
}
}
}
};
window.addEventListener('scroll', handleScroll);
handleScroll(); // run once on mount
return () => window.removeEventListener('scroll', handleScroll);
}, [previewMode]);
}, [previewMode, currentPage]);
const getActiveNavItem = () => {
if (currentPage === 'contact') return 'Contact Us';
@@ -548,15 +589,16 @@ export default function App({ previewMode = false }) {
const el = document.getElementById(sectionId);
if (el) {
const top = el.getBoundingClientRect().top + window.scrollY - NAV_OFFSET;
window.scrollTo({ top, behavior: 'smooth' });
smoothScrollTo(top);
setActiveSection(sectionId);
} else if (sectionId === 'contactus') {
window.scrollTo({ top: document.documentElement.scrollHeight, behavior: 'smooth' });
smoothScrollTo(document.documentElement.scrollHeight);
setActiveSection('contactus');
}
};
const handleNavClick = (item) => {
setNavbarVisible(true);
setMobileMenuOpen(false);
if (item === 'Careers') {
setIsCareersOpen(true);
@@ -567,7 +609,7 @@ export default function App({ previewMode = false }) {
setCurrentPage('contact');
setActiveSection('contactus');
window.location.hash = 'contact';
window.scrollTo({ top: 0, behavior: 'smooth' });
smoothScrollTo(0);
return;
}
@@ -575,7 +617,7 @@ export default function App({ previewMode = false }) {
setCurrentPage('about');
setActiveSection('aboutus');
window.location.hash = 'aboutus';
window.scrollTo({ top: 0, behavior: 'smooth' });
smoothScrollTo(0);
return;
}
@@ -587,14 +629,14 @@ export default function App({ previewMode = false }) {
const doScroll = (sectionId) => {
if (!sectionId || sectionId === 'home') {
window.scrollTo({ top: 0, behavior: 'smooth' });
smoothScrollTo(0);
return;
}
requestAnimationFrame(() => {
const el = document.getElementById(sectionId);
if (el) {
const top = el.getBoundingClientRect().top + window.scrollY - NAV_OFFSET;
window.scrollTo({ top, behavior: 'smooth' });
smoothScrollTo(top);
setActiveSection(sectionId);
}
});
@@ -695,9 +737,12 @@ export default function App({ previewMode = false }) {
{/* Navigation Bar */}
<nav className="glass site-nav" style={{
position: 'sticky', top: 0, zIndex: 50,
position: 'sticky',
top: navbarVisible ? 0 : (isMobile ? '-72px' : '-88px'),
zIndex: 50,
padding: isMobile ? '0.85rem 1.25rem' : '1.2rem 4rem',
borderBottom: activeSection === 'products' ? '1px solid rgba(15, 23, 42, 0.08)' : '1px solid rgba(255, 255, 255, 0.05)'
borderBottom: activeSection === 'products' ? '1px solid rgba(15, 23, 42, 0.08)' : '1px solid rgba(255, 255, 255, 0.05)',
transition: 'top 0.3s cubic-bezier(0.16, 1, 0.3, 1), border-bottom 0.3s ease, padding 0.3s ease'
}}>
<div style={{ maxWidth: '1440px', margin: '0 auto', width: '100%', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<div