-
Notifications
You must be signed in to change notification settings - Fork 29
Improve navbar overflow handling and simplify link width measurement #200
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
e055da4
f0593e4
07ac600
9578ed7
afb4075
495c0b5
a32d249
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,10 +5,15 @@ | |
PUBLIC_NAV_BAR_LINKS | ||
} from '$env/static/public'; | ||
import { onMount } from 'svelte'; | ||
import ThemeSwitcher from '$lib/ThemeSwitch/ThemeSwitcher.svelte'; | ||
import MobileMenu from './MobileMenu.svelte'; | ||
let isMobileMenuOpen = $state(false); | ||
let shouldShowMobile = $state(false); | ||
let navContainer; | ||
let linksContainer = $state(null); | ||
let linksWidthCache = 0; | ||
let headerLinks = $state(null); | ||
|
@@ -19,13 +24,80 @@ | |
function toggleNavbar() { | ||
isMobileMenuOpen = !isMobileMenuOpen; | ||
} | ||
function checkOverflow() { | ||
if (!navContainer) return; | ||
const navWidth = navContainer.clientWidth; | ||
const logoWidth = navContainer.querySelector('.logo-container')?.clientWidth || 0; | ||
const themeWidth = 48; | ||
tarunsinghofficial marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
const availableWidth = navWidth - logoWidth - themeWidth - 32; | ||
let linksWidth = 0; | ||
if (linksContainer) { | ||
linksWidth = linksContainer.scrollWidth; | ||
linksWidthCache = linksWidth; | ||
} else { | ||
linksWidth = linksWidthCache; | ||
} | ||
const newShouldShowMobileMenu = linksWidth > availableWidth; | ||
if (shouldShowMobile !== newShouldShowMobileMenu) { | ||
shouldShowMobile = newShouldShowMobileMenu; | ||
} | ||
} | ||
function measureLinksWidth() { | ||
if (headerLinks && !linksContainer) { | ||
|
||
const tempDiv = document.createElement('div'); | ||
tempDiv.style.position = 'absolute'; | ||
tempDiv.style.visibility = 'hidden'; | ||
tempDiv.style.display = 'flex'; | ||
tempDiv.style.gap = '1rem'; | ||
|
||
if (Object.keys(headerLinks).length > 0) { | ||
Object.keys(headerLinks).forEach((key) => { | ||
const linkDiv = document.createElement('div'); | ||
linkDiv.style.padding = '0.25rem 0.5rem'; | ||
linkDiv.style.flexShrink = '0'; | ||
linkDiv.textContent = key; | ||
tempDiv.appendChild(linkDiv); | ||
}); | ||
} else { | ||
const linkDiv = document.createElement('div'); | ||
linkDiv.style.width = '600px'; | ||
tempDiv.appendChild(linkDiv); | ||
} | ||
document.body.appendChild(tempDiv); | ||
linksWidthCache = tempDiv.scrollWidth; | ||
document.body.removeChild(tempDiv); | ||
} | ||
} | ||
onMount(() => { | ||
measureLinksWidth(); | ||
checkOverflow(); | ||
const headerResizeObserver = new ResizeObserver(() => { | ||
checkOverflow(); | ||
}); | ||
headerResizeObserver.observe(navContainer); | ||
return () => { | ||
headerResizeObserver.disconnect(); | ||
}; | ||
}); | ||
</script> | ||
<div | ||
class="bg-blur-md flex items-center justify-between border-b border-gray-500 bg-white/80 px-4 dark:bg-black dark:text-white md:flex-row md:px-8" | ||
bind:this={navContainer} | ||
> | ||
<div class="flex flex-1 items-center justify-between md:flex-none"> | ||
<div class="flex w-full justify-between gap-4 px-2 py-2 md:w-auto"> | ||
<div class="logo-container flex w-full items-center gap-4 px-2 py-2 md:w-auto"> | ||
<div class="flex items-center justify-center gap-x-2"> | ||
<a href="/" class="block"> | ||
<img src={PUBLIC_OBA_LOGO_URL} alt={PUBLIC_OBA_REGION_NAME} class="h-10 rounded-sm" /> | ||
|
@@ -34,42 +106,48 @@ | |
{PUBLIC_OBA_REGION_NAME} | ||
</a> | ||
</div> | ||
|
||
<div class="flex items-center justify-end md:hidden"> | ||
<button onclick={toggleNavbar} aria-label="Toggle navigation menu"> | ||
<svg | ||
class="burger-icon h-6 w-6 text-gray-900 dark:text-white" | ||
fill="none" | ||
stroke="currentColor" | ||
viewBox="0 0 24 24" | ||
xmlns="http://www.w3.org/2000/svg" | ||
> | ||
<path | ||
stroke-linecap="round" | ||
stroke-linejoin="round" | ||
stroke-width="2" | ||
d="M4 6h16M4 12h16m-7 6h7" | ||
></path> | ||
</svg> | ||
</button> | ||
</div> | ||
</div> | ||
<div class="hidden items-center gap-4 px-2 py-2 md:flex"> | ||
<div class="flex gap-x-4"> | ||
{#each Object.entries(headerLinks) as [key, value]} | ||
<div class="rounded-md border bg-white/80 dark:bg-gray-800"> | ||
<a href={value} class="block px-2 py-1 font-semibold text-gray-900 dark:text-white" | ||
>{key}</a | ||
> | ||
</div> | ||
{/each} | ||
{#if !shouldShowMobile} | ||
<div class="flex items-center px-2 py-2" bind:this={linksContainer}> | ||
<div class="no-scrollbar flex gap-x-4 overflow-x-auto"> | ||
{#if headerLinks && Object.keys(headerLinks).length > 0} | ||
{#each Object.entries(headerLinks) as [key, value]} | ||
<div class="flex-shrink-0 rounded-md border bg-white/80 dark:bg-gray-800"> | ||
<a href={value} class="block px-2 py-1 font-semibold text-gray-900 dark:text-white" | ||
>{key}</a | ||
> | ||
</div> | ||
{/each} | ||
{/if} | ||
</div> | ||
</div> | ||
</div> | ||
{/if} | ||
</div> | ||
<div class="hidden md:flex"> | ||
<ThemeSwitcher /> | ||
<div class="flex items-center"> | ||
{#if shouldShowMobile} | ||
<button onclick={toggleNavbar} aria-label="Toggle navigation menu" class="mr-2"> | ||
<svg | ||
class="burger-icon h-6 w-6 text-gray-900 dark:text-white" | ||
fill="none" | ||
stroke="currentColor" | ||
viewBox="0 0 24 24" | ||
xmlns="http://www.w3.org/2000/svg" | ||
> | ||
<path | ||
stroke-linecap="round" | ||
stroke-linejoin="round" | ||
stroke-width="2" | ||
d="M4 6h16M4 12h16m-7 6h7" | ||
></path> | ||
</svg> | ||
</button> | ||
{:else} | ||
<div class={shouldShowMobile ? '' : 'flex'}> | ||
<ThemeSwitcher /> | ||
</div> | ||
{/if} | ||
</div> | ||
</div> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rename this to
cachedLinksWidth
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done