Skip to content

Commit 51b90b3

Browse files
nikoshellpre-commit-ci[bot]clytaemnestra
authored
Update navbar (#1312)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Mia Bajić <[email protected]>
1 parent 17ca76d commit 51b90b3

File tree

1 file changed

+104
-14
lines changed

1 file changed

+104
-14
lines changed

src/components/Header.astro

Lines changed: 104 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import links from "@data/links.json";
1010

1111
<section
1212
id="navbar"
13-
class="fixed top-0 z-50 transition-transform duration-300 transform-gpu w-full"
1413
>
1514
<div
1615
class="container max-w-[1150px] mx-auto px-6 py-2 mt-1 lg:p-2 lg:mt-6 flex items-center justify-between relative z-40 bg-white/80 rounded-full backdrop-blur-md shadow-lg"
@@ -47,28 +46,119 @@ import links from "@data/links.json";
4746
</section>
4847
<Search />
4948

49+
<style>
50+
#navbar {
51+
position: fixed;
52+
top: 0;
53+
width: 100%;
54+
z-index: 1000;
55+
transition: transform 0.3s ease-in-out;
56+
transform: translateY(0);
57+
}
58+
</style>
5059
<script>
51-
document.addEventListener("DOMContentLoaded", () => {
52-
let prevScrollPos = window.pageYOffset;
60+
document.addEventListener("DOMContentLoaded", function() {
5361
const navbar = document.getElementById("navbar") as HTMLElement;
62+
if (!navbar) return;
5463

55-
window.addEventListener("scroll", () => {
56-
let currentScrollPos = window.pageYOffset;
57-
if (prevScrollPos > currentScrollPos) {
64+
let prevScrollPos = window.pageYOffset || document.documentElement.scrollTop;
65+
let ticking = false;
66+
let isVisible = true;
67+
68+
// Ensure navbar is visible initially
69+
navbar.style.transform = "translateY(0)";
70+
navbar.style.transition = "transform 0.3s ease-in-out";
71+
72+
function updateNavbar() {
73+
// Handle iOS bounce - scroll position can be negative during bounce
74+
const rawScrollPos = window.pageYOffset || document.documentElement.scrollTop;
75+
const currentScrollPos = Math.max(0, rawScrollPos);
76+
77+
// Show navbar immediately if we're bouncing above the page (negative scroll)
78+
// or if we're very close to the top
79+
if (rawScrollPos <= 0 || currentScrollPos <= 50) {
80+
if (!isVisible) {
81+
navbar.style.transform = "translateY(0)";
82+
isVisible = true;
83+
}
84+
prevScrollPos = currentScrollPos;
85+
ticking = false;
86+
return;
87+
}
88+
89+
const documentHeight = document.documentElement.scrollHeight;
90+
const windowHeight = window.innerHeight;
91+
92+
// Don't hide navbar when at the very bottom
93+
if (currentScrollPos + windowHeight >= documentHeight - 50) {
94+
if (!isVisible) {
95+
navbar.style.transform = "translateY(0)";
96+
isVisible = true;
97+
}
98+
prevScrollPos = currentScrollPos;
99+
ticking = false;
100+
return;
101+
}
102+
103+
// Only update if scroll difference is significant
104+
const scrollDiff = Math.abs(currentScrollPos - prevScrollPos);
105+
if (scrollDiff < 3) {
106+
ticking = false;
107+
return;
108+
}
109+
110+
// Show navbar when scrolling up, hide when scrolling down
111+
if (prevScrollPos > currentScrollPos && !isVisible) {
58112
navbar.style.transform = "translateY(0)";
59-
} else {
113+
isVisible = true;
114+
} else if (prevScrollPos < currentScrollPos && isVisible && currentScrollPos > 100) {
60115
navbar.style.transform = "translateY(-100%)";
116+
isVisible = false;
61117
}
118+
62119
prevScrollPos = currentScrollPos;
63-
});
120+
ticking = false;
121+
}
64122

65-
navbar.addEventListener("focusin", () => {
66-
navbar.style.transform = "translateY(0)";
67-
});
123+
function requestTick() {
124+
if (!ticking) {
125+
requestAnimationFrame(updateNavbar);
126+
ticking = true;
127+
}
128+
}
68129

69-
navbar.addEventListener("focusout", () => {
70-
if (window.pageYOffset > 100) {
71-
navbar.style.transform = "translateY(-100%)";
130+
// Use passive listener for better performance on mobile
131+
window.addEventListener("scroll", requestTick, { passive: true });
132+
133+
// Additional safety check specifically for iOS bounce recovery
134+
let bounceCheckTimeout: any = null;
135+
136+
window.addEventListener("scroll", function() {
137+
// Clear any existing timeout
138+
if (bounceCheckTimeout) {
139+
clearTimeout(bounceCheckTimeout);
140+
}
141+
142+
// Set a timeout to check position after scroll momentum stops
143+
bounceCheckTimeout = setTimeout(() => {
144+
const finalScrollPos = Math.max(0, window.pageYOffset || document.documentElement.scrollTop);
145+
if (finalScrollPos <= 50 && !isVisible) {
146+
navbar.style.transform = "translateY(0)";
147+
isVisible = true;
148+
prevScrollPos = finalScrollPos;
149+
}
150+
}, 150);
151+
}, { passive: true });
152+
153+
// Handle page visibility changes (when switching tabs/apps)
154+
document.addEventListener("visibilitychange", function() {
155+
if (!document.hidden) {
156+
const currentScrollPos = Math.max(0, window.pageYOffset || document.documentElement.scrollTop);
157+
if (currentScrollPos <= 50) {
158+
navbar.style.transform = "translateY(0)";
159+
isVisible = true;
160+
prevScrollPos = currentScrollPos;
161+
}
72162
}
73163
});
74164
});

0 commit comments

Comments
 (0)