From 2ed845a68da9574e255ca47cfb50e7e7dd634089 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 6 Aug 2026 10:51:47 +0000 Subject: [PATCH 1/8] Remove "Home" item from site navigation The expandable navigation menu grows too tall on desktop. Removing the redundant "Home" entry from the main menu shortens it. The homepage stays reachable via the logo in the top-left, and the / route is unchanged. --- nuxt-app/components/Header.vue | 1 - 1 file changed, 1 deletion(-) diff --git a/nuxt-app/components/Header.vue b/nuxt-app/components/Header.vue index 715ee4bd..c1edbc96 100644 --- a/nuxt-app/components/Header.vue +++ b/nuxt-app/components/Header.vue @@ -149,7 +149,6 @@ const FLAG_SHOW_LOGIN = useRuntimeConfig().public.FLAG_SHOW_LOGIN const FLAG_SHOW_NEWS = useRuntimeConfig().public.FLAG_SHOW_NEWS const mainMenuItems = [ - { label: 'Home', href: '/' }, { label: 'Podcast', href: '/podcast' }, ...(FLAG_SHOW_NEWS ? [{ label: 'News', href: '/news' }] : []), { label: 'Meetup', href: '/meetup' }, From 064084bc9cda4ede3e2bb5ba751c97e6d30555db Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 6 Aug 2026 11:35:48 +0000 Subject: [PATCH 2/8] Tighten spacing in expandable nav so all items fit without scrolling --- nuxt-app/components/Header.vue | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/nuxt-app/components/Header.vue b/nuxt-app/components/Header.vue index c1edbc96..a263fa39 100644 --- a/nuxt-app/components/Header.vue +++ b/nuxt-app/components/Header.vue @@ -82,10 +82,10 @@ tabindex="-1" >
-
    +
    • From e165ee5422a2d203c128e8e76847e98d7c2170b8 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 6 Aug 2026 11:39:34 +0000 Subject: [PATCH 3/8] Format Header.vue with Prettier The spacing-class change shortened a div's class string so it now fits on one line; run Prettier to collapse the multi-line attribute and satisfy the prettier:check CI step. --- nuxt-app/components/Header.vue | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/nuxt-app/components/Header.vue b/nuxt-app/components/Header.vue index a263fa39..98daab87 100644 --- a/nuxt-app/components/Header.vue +++ b/nuxt-app/components/Header.vue @@ -108,9 +108,7 @@
    -
    +
    From d2430a5607e9722e2d55007298d7b500fc65606e Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 6 Aug 2026 11:44:16 +0000 Subject: [PATCH 4/8] Left-align legal links, keep social icons right, and lock background scroll when menu open --- nuxt-app/components/Header.vue | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/nuxt-app/components/Header.vue b/nuxt-app/components/Header.vue index 98daab87..947ce9f6 100644 --- a/nuxt-app/components/Header.vue +++ b/nuxt-app/components/Header.vue @@ -108,7 +108,7 @@
-
+
@@ -137,8 +137,8 @@ import SearchSVG from '~/assets/icons/search.svg' import BrandIcon from '~/assets/images/brand-icon.svg' import BrandLogo from '~/assets/images/brand-logo.svg' import PrimaryPbButton from '~/components/PrimaryPbButton.vue' -import { nextTick, onMounted, ref, watch } from 'vue' -import { useDocument, useEventListener } from '../composables' +import { nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue' +import { useBodyElement, useDocument, useEventListener } from '../composables' import { CLOSE_MENU_EVENT_ID, CLOSE_SEARCH_EVENT_ID, OPEN_MENU_EVENT_ID, OPEN_SEARCH_EVENT_ID } from '../config' import { trackGoal } from '../helpers' import SocialNetworks from './SocialNetworks.vue' @@ -177,6 +177,9 @@ const searchPlaceholder = ref('') const searchInputElement = ref() const menuElement = ref() +// Create body element reference for locking background scroll +const bodyElement = useBodyElement() + // Track analytic menu events watch(menuIsOpen, () => { if (menuIsOpen.value) { @@ -186,6 +189,22 @@ watch(menuIsOpen, () => { } }) +// Lock background scroll while the menu is open so the underlying +// page can't move behind the overlay, and release it when it closes +watch(menuIsOpen, () => { + if (bodyElement.value) { + bodyElement.value.style.overflow = menuIsOpen.value ? 'hidden' : '' + } +}) + +// Make sure the scroll lock is released if the component is unmounted +// while the menu is still open, so the page can't stay locked +onBeforeUnmount(() => { + if (bodyElement.value) { + bodyElement.value.style.overflow = '' + } +}) + // Track analytic search events watch(searchIsOpen, () => { if (searchIsOpen.value) { From b17ecb8cc05efcb2e23aed349c082134f00f83c5 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 6 Aug 2026 11:58:08 +0000 Subject: [PATCH 5/8] Preserve previous body overflow in menu scroll-lock Save the body's current inline overflow value when locking scroll on menu open and restore it on close and unmount, instead of hard-resetting to an empty string, so a pre-existing inline overflow is not clobbered. --- nuxt-app/components/Header.vue | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/nuxt-app/components/Header.vue b/nuxt-app/components/Header.vue index 947ce9f6..a23ddc75 100644 --- a/nuxt-app/components/Header.vue +++ b/nuxt-app/components/Header.vue @@ -180,6 +180,10 @@ const menuElement = ref() // Create body element reference for locking background scroll const bodyElement = useBodyElement() +// Remember the body's inline overflow value so it can be restored when the +// scroll lock is released, instead of clobbering a pre-existing value +const previousBodyOverflow = ref('') + // Track analytic menu events watch(menuIsOpen, () => { if (menuIsOpen.value) { @@ -193,7 +197,15 @@ watch(menuIsOpen, () => { // page can't move behind the overlay, and release it when it closes watch(menuIsOpen, () => { if (bodyElement.value) { - bodyElement.value.style.overflow = menuIsOpen.value ? 'hidden' : '' + if (menuIsOpen.value) { + // Save the current inline overflow before locking so a value set + // elsewhere isn't lost, then lock the scroll + previousBodyOverflow.value = bodyElement.value.style.overflow + bodyElement.value.style.overflow = 'hidden' + } else { + // Restore the previously saved overflow value on close + bodyElement.value.style.overflow = previousBodyOverflow.value + } } }) @@ -201,7 +213,7 @@ watch(menuIsOpen, () => { // while the menu is still open, so the page can't stay locked onBeforeUnmount(() => { if (bodyElement.value) { - bodyElement.value.style.overflow = '' + bodyElement.value.style.overflow = previousBodyOverflow.value } }) From f0ba3341557b897378f672cb1e13928b59b26d50 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 6 Aug 2026 12:02:51 +0000 Subject: [PATCH 6/8] Only restore body overflow on unmount when scroll lock is held --- nuxt-app/components/Header.vue | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/nuxt-app/components/Header.vue b/nuxt-app/components/Header.vue index a23ddc75..3362cabc 100644 --- a/nuxt-app/components/Header.vue +++ b/nuxt-app/components/Header.vue @@ -210,9 +210,11 @@ watch(menuIsOpen, () => { }) // Make sure the scroll lock is released if the component is unmounted -// while the menu is still open, so the page can't stay locked +// while the menu is still open, so the page can't stay locked. Only +// restore when the menu is open (i.e. the lock is actually held), so we +// don't clobber a pre-existing overflow value we never captured onBeforeUnmount(() => { - if (bodyElement.value) { + if (bodyElement.value && menuIsOpen.value) { bodyElement.value.style.overflow = previousBodyOverflow.value } }) From 9b5ca99379b7cbfc0a215167e30d6efbd88c7cf5 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 6 Aug 2026 12:07:11 +0000 Subject: [PATCH 7/8] Track scroll-lock state with a flag so unmount always releases it --- nuxt-app/components/Header.vue | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/nuxt-app/components/Header.vue b/nuxt-app/components/Header.vue index 3362cabc..cb47ee55 100644 --- a/nuxt-app/components/Header.vue +++ b/nuxt-app/components/Header.vue @@ -184,6 +184,10 @@ const bodyElement = useBodyElement() // scroll lock is released, instead of clobbering a pre-existing value const previousBodyOverflow = ref('') +// Track whether the scroll lock is actually applied, set synchronously with +// the overflow change so it stays consistent regardless of watcher timing +const scrollLocked = ref(false) + // Track analytic menu events watch(menuIsOpen, () => { if (menuIsOpen.value) { @@ -202,20 +206,23 @@ watch(menuIsOpen, () => { // elsewhere isn't lost, then lock the scroll previousBodyOverflow.value = bodyElement.value.style.overflow bodyElement.value.style.overflow = 'hidden' - } else { + scrollLocked.value = true + } else if (scrollLocked.value) { // Restore the previously saved overflow value on close bodyElement.value.style.overflow = previousBodyOverflow.value + scrollLocked.value = false } } }) -// Make sure the scroll lock is released if the component is unmounted -// while the menu is still open, so the page can't stay locked. Only -// restore when the menu is open (i.e. the lock is actually held), so we -// don't clobber a pre-existing overflow value we never captured +// Release the lock if the component is unmounted while it still holds it +// (e.g. a route change unmounts before the close watcher has run), so the +// page can't stay permanently locked. Drive this off the actual lock state, +// not menuIsOpen, since the watcher is async and may not have run yet onBeforeUnmount(() => { - if (bodyElement.value && menuIsOpen.value) { + if (bodyElement.value && scrollLocked.value) { bodyElement.value.style.overflow = previousBodyOverflow.value + scrollLocked.value = false } }) From d082f54a96573b884879fd7b7db20abd0aa75c55 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 6 Aug 2026 12:26:25 +0000 Subject: [PATCH 8/8] Compensate scrollbar width while menu scroll-lock is active to avoid layout shift --- nuxt-app/components/Header.vue | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/nuxt-app/components/Header.vue b/nuxt-app/components/Header.vue index cb47ee55..ff76bcd7 100644 --- a/nuxt-app/components/Header.vue +++ b/nuxt-app/components/Header.vue @@ -184,6 +184,10 @@ const bodyElement = useBodyElement() // scroll lock is released, instead of clobbering a pre-existing value const previousBodyOverflow = ref('') +// Remember the body's inline padding-right for the same reason, since it is +// adjusted to compensate for the width of the hidden scrollbar +const previousBodyPaddingRight = ref('') + // Track whether the scroll lock is actually applied, set synchronously with // the overflow change so it stays consistent regardless of watcher timing const scrollLocked = ref(false) @@ -202,14 +206,25 @@ watch(menuIsOpen, () => { watch(menuIsOpen, () => { if (bodyElement.value) { if (menuIsOpen.value) { - // Save the current inline overflow before locking so a value set - // elsewhere isn't lost, then lock the scroll + // Measure the scrollbar width before hiding overflow (afterwards + // the scrollbar is gone and the measurement would be 0) + const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth + // Save the current inline overflow and padding-right before locking + // so values set elsewhere aren't lost, then lock the scroll previousBodyOverflow.value = bodyElement.value.style.overflow + previousBodyPaddingRight.value = bodyElement.value.style.paddingRight bodyElement.value.style.overflow = 'hidden' + // Compensate the hidden scrollbar with padding-right so the fixed + // header doesn't shift when the scrollbar disappears + if (scrollbarWidth > 0) { + const currentPaddingRight = parseFloat(getComputedStyle(bodyElement.value).paddingRight) || 0 + bodyElement.value.style.paddingRight = `${currentPaddingRight + scrollbarWidth}px` + } scrollLocked.value = true } else if (scrollLocked.value) { - // Restore the previously saved overflow value on close + // Restore the previously saved overflow and padding-right on close bodyElement.value.style.overflow = previousBodyOverflow.value + bodyElement.value.style.paddingRight = previousBodyPaddingRight.value scrollLocked.value = false } } @@ -222,6 +237,7 @@ watch(menuIsOpen, () => { onBeforeUnmount(() => { if (bodyElement.value && scrollLocked.value) { bodyElement.value.style.overflow = previousBodyOverflow.value + bodyElement.value.style.paddingRight = previousBodyPaddingRight.value scrollLocked.value = false } })