Skip to content

Commit da627d3

Browse files
committed
fix: improve navigation active state detection with hash support
- Compare full URLs (pathname + hash) instead of just pathname - Add event listeners for hashchange, popstate, and menu clicks - Fixes issue where multiple menu items with same path but different hashes were all marked active - Ensures active state updates immediately when clicking hash-based navigation links
1 parent 49cf711 commit da627d3

1 file changed

Lines changed: 36 additions & 4 deletions

File tree

src/layouts/components/Header/components/Navigation.astro

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,10 @@ const { items } = menuTexts[currentLang]
222222
const setActiveMenuItem = (): void => {
223223
const allMenus = mainNav.querySelectorAll('nav > ul')
224224
const currentPathname = window.location.pathname
225+
const currentHash = window.location.hash
226+
227+
// Build the full current URL (without trailing slash in pathname)
228+
const currentFullUrl = currentPathname.replace(/\/$/, '') + currentHash
225229

226230
allMenus.forEach((menu) => {
227231
const menuItems = [...menu.querySelectorAll('a:not([rel*="external"])')] as HTMLAnchorElement[]
@@ -231,10 +235,17 @@ const { items } = menuTexts[currentLang]
231235
menuItem.classList.remove('is-active')
232236
menuItem.removeAttribute('aria-current')
233237

234-
const itemPathname = menuItem.pathname.replace(/\/$/, '') // Remove trailing slash
235-
const currentPath = currentPathname.replace(/\/$/, '')
236-
237-
if (itemPathname === currentPath || (itemPathname === '' && currentPath === '')) {
238+
// Build the full URL for the menu item
239+
const itemPathname = menuItem.pathname.replace(/\/$/, '')
240+
const itemHash = menuItem.hash || ''
241+
const itemFullUrl = itemPathname + itemHash
242+
243+
// Compare full URLs
244+
if (
245+
itemFullUrl === currentFullUrl ||
246+
(itemFullUrl === '' && currentFullUrl === '') ||
247+
(itemPathname === '' && currentPathname.replace(/\/$/, '') === '')
248+
) {
238249
menuItem.classList.add('is-active')
239250
menuItem.setAttribute('aria-current', 'page')
240251
}
@@ -474,6 +485,27 @@ const { items } = menuTexts[currentLang]
474485

475486
// Initialize active menu item
476487
setActiveMenuItem()
488+
489+
// Update active menu item when hash changes (for same-page navigation)
490+
window.addEventListener('hashchange', setActiveMenuItem)
491+
492+
// Also listen for popstate (back/forward navigation)
493+
window.addEventListener('popstate', setActiveMenuItem)
494+
495+
// Listen for clicks on menu items to update immediately
496+
const allMenus = mainNav.querySelectorAll('nav > ul')
497+
allMenus.forEach((menu) => {
498+
menu.addEventListener('click', (event) => {
499+
const target = event.target as HTMLElement
500+
const link = target.closest('a') as HTMLAnchorElement
501+
if (link && !link.hasAttribute('rel')) {
502+
// Small delay to ensure URL has changed
503+
setTimeout(() => {
504+
setActiveMenuItem()
505+
}, 10)
506+
}
507+
})
508+
})
477509
})
478510
</script>
479511

0 commit comments

Comments
 (0)