wip: getting closer

This commit is contained in:
2026-01-10 23:26:30 +00:00
parent 4722094f0c
commit 7d06d18ccb
19 changed files with 475 additions and 471 deletions

View File

@@ -43,31 +43,37 @@ const { version } = Astro.props;
<nav class="hidden md:flex items-center gap-1">
<a
href="#about"
class="inline-flex items-center px-4 py-2 text-sm font-medium rounded-lg
transition-colors cursor-pointer
class="nav-link inline-flex items-center px-4 py-2 text-sm font-medium
rounded-lg transition-colors cursor-pointer
text-gray-600 dark:text-slate-400
hover:bg-gray-100 hover:text-gray-950
dark:hover:bg-slate-800 dark:hover:text-slate-50"
data-nav-link
data-section-id="about"
>
About
</a>
<a
href="#spec"
class="inline-flex items-center px-4 py-2 text-sm font-medium rounded-lg
transition-colors cursor-pointer
class="nav-link inline-flex items-center px-4 py-2 text-sm font-medium
rounded-lg transition-colors cursor-pointer
text-gray-600 dark:text-slate-400
hover:bg-gray-100 hover:text-gray-950
dark:hover:bg-slate-800 dark:hover:text-slate-50"
data-nav-link
data-section-id="spec"
>
Spec
</a>
<a
href="#faq"
class="inline-flex items-center px-4 py-2 text-sm font-medium rounded-lg
transition-colors cursor-pointer
class="nav-link inline-flex items-center px-4 py-2 text-sm font-medium
rounded-lg transition-colors cursor-pointer
text-gray-600 dark:text-slate-400
hover:bg-gray-100 hover:text-gray-950
dark:hover:bg-slate-800 dark:hover:text-slate-50"
data-nav-link
data-section-id="faq"
>
FAQ
</a>
@@ -133,19 +139,28 @@ const { version } = Astro.props;
</div>
<a
href="#about"
class="block py-2 text-gray-600 dark:text-slate-400 hover:text-sky-600"
class="nav-link block py-2 text-gray-600 dark:text-slate-400
hover:text-sky-600"
data-nav-link
data-section-id="about"
>
About
</a>
<a
href="#spec"
class="block py-2 text-gray-600 dark:text-slate-400 hover:text-sky-600"
class="nav-link block py-2 text-gray-600 dark:text-slate-400
hover:text-sky-600"
data-nav-link
data-section-id="spec"
>
Spec
</a>
<a
href="#faq"
class="block py-2 text-gray-600 dark:text-slate-400 hover:text-sky-600"
class="nav-link block py-2 text-gray-600 dark:text-slate-400
hover:text-sky-600"
data-nav-link
data-section-id="faq"
>
FAQ
</a>
@@ -162,23 +177,22 @@ const { version } = Astro.props;
if (!header || !hero) return;
// Show/hide header based on scroll past hero
// Show header when top half of hero is above the fold
const topMargin = Math.floor(window.innerHeight / 2);
const observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
header.classList.add("translate-y-[-100%]");
header.classList.remove("border-gray-200", "dark:border-slate-800");
} else {
header.classList.remove("translate-y-[-100%]");
header.classList.add("border-gray-200", "dark:border-slate-800");
}
},
{ threshold: 0, rootMargin: `-${topMargin}px 0px 0px 0px` }
);
// Show/hide header based on scroll position
// Show header once scrolled down by the navbar height (64px)
const navbarHeight = 64;
observer.observe(hero);
function updateHeaderVisibility() {
if (window.scrollY >= navbarHeight) {
header.classList.remove("translate-y-[-100%]");
header.classList.add("border-gray-200", "dark:border-slate-800");
} else {
header.classList.add("translate-y-[-100%]");
header.classList.remove("border-gray-200", "dark:border-slate-800");
}
}
window.addEventListener("scroll", updateHeaderVisibility, { passive: true });
updateHeaderVisibility();
// Mobile menu toggle
if (mobileMenuBtn && mobileNav) {
@@ -193,6 +207,53 @@ const { version } = Astro.props;
});
});
}
// Active section tracking for nav links
const navLinks = document.querySelectorAll("[data-nav-link]");
const sections: { id: string; element: Element }[] = [];
// Collect unique section IDs
const seenIds = new Set<string>();
navLinks.forEach((link) => {
const id = link.getAttribute("data-section-id");
if (id && !seenIds.has(id)) {
seenIds.add(id);
const section = document.getElementById(id);
if (section) {
sections.push({ id, element: section });
}
}
});
function updateActiveNavSection() {
const headerOffset = 100;
let activeId: string | null = null;
for (const { id, element } of sections) {
const rect = element.getBoundingClientRect();
if (rect.top <= headerOffset) {
activeId = id;
}
}
navLinks.forEach((link) => {
const linkId = link.getAttribute("data-section-id");
link.classList.toggle("active", linkId === activeId);
});
}
let ticking = false;
window.addEventListener("scroll", () => {
if (!ticking) {
requestAnimationFrame(() => {
updateActiveNavSection();
ticking = false;
});
ticking = true;
}
});
updateActiveNavSection();
}
// Initialize on load