Skip to content
This repository has been archived by the owner on Feb 22, 2023. It is now read-only.

Commit

Permalink
Fix the header scrolling (#2155)
Browse files Browse the repository at this point in the history
* Fix scrolling header by using min-height

* Split the layouts to fix height and scrolling

* Make search page layout test less flaky
  • Loading branch information
obulat committed Feb 8, 2023
1 parent d2926b7 commit 202935c
Show file tree
Hide file tree
Showing 15 changed files with 250 additions and 159 deletions.
1 change: 1 addition & 0 deletions src/components/VHeader/VHeaderMobile/VHeaderMobile.vue
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,7 @@ export default defineComponent({
} = useDialogControl({
visibleRef: contentSettingsOpen,
nodeRef: headerRef,
lockBodyScroll: true,
emit,
})
Expand Down
211 changes: 211 additions & 0 deletions src/layouts/content-layout.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
<template>
<div
class="app flex min-h-screen min-h-[100dvh] flex-col bg-white"
:class="[isDesktopLayout ? 'desktop' : 'mobile', breakpoint]"
>
<div class="sticky top-0 z-40 block">
<VTeleportTarget name="skip-to-content" :force-destroy="true" />
<VBanners />
<template v-if="isNewHeaderEnabled">
<template v-if="isSearchHeader">
<VHeaderDesktop v-if="isDesktopLayout" class="bg-white" />
<VHeaderMobile v-else class="bg-white" />
</template>
<VHeaderInternal
v-else
:class="[
'bg-white',
{ 'border-b-dark-charcoal-20': isHeaderScrolled },
]"
/>
</template>
<VHeaderOld v-else class="bg-white" />
</div>

<main
class="main grid h-full flex-grow"
:class="[
{ 'has-sidebar': isSidebarVisible },
isSidebarVisible
? 'grid-cols-[1fr_var(--filter-sidebar-width)]'
: 'grid-cols-1',
]"
>
<div
v-if="isNewHeaderEnabled"
class="main-page flex h-full w-full min-w-0 flex-col justify-between"
>
<Nuxt />
<VFooter
:mode="isSearchHeader ? 'content' : 'search'"
class="border-t border-dark-charcoal-20 bg-white"
/>
</div>
<Nuxt v-else class="main-page flex h-full w-full min-w-0 flex-col" />

<aside
v-if="isSidebarVisible"
class="sidebar fixed z-10 h-[calc(100vh-81px)] h-[calc(100dvh-81px)] overflow-y-auto border-dark-charcoal-20 bg-dark-charcoal-06 end-0 border-s"
>
<VSearchGridFilter class="px-10 pt-8 pb-10" @close="closeSidebar" />
</aside>
</main>

<VModalTarget class="modal" />
<VGlobalAudioSection />
</div>
</template>
<script lang="ts">
import {
computed,
defineComponent,
onMounted,
provide,
ref,
useContext,
watch,
} from "@nuxtjs/composition-api"
import { PortalTarget as VTeleportTarget } from "portal-vue"
import { useWindowScroll } from "~/composables/use-window-scroll"
import {
useMatchSearchRoutes,
useMatchSingleResultRoutes,
useMatchContentPageRoutes,
} from "~/composables/use-match-routes"
import { useLayout } from "~/composables/use-layout"
import { useFeatureFlagStore } from "~/stores/feature-flag"
import { useUiStore } from "~/stores/ui"
import { useSearchStore } from "~/stores/search"
import { IsHeaderScrolledKey, IsSidebarVisibleKey } from "~/types/provides"
import VBanners from "~/components/VBanner/VBanners.vue"
import VHeaderOld from "~/components/VHeaderOld/VHeaderOld.vue"
import VModalTarget from "~/components/VModal/VModalTarget.vue"
import VGlobalAudioSection from "~/components/VGlobalAudioSection/VGlobalAudioSection.vue"
import VSearchGridFilter from "~/components/VFilters/VSearchGridFilter.vue"
/**
* This is the ContentLayout: the search page, the single result page,
* and the content pages.
* It has white background and is scrollable. It can also have a sidebar.
*/
export default defineComponent({
name: "ContentLayout",
components: {
VBanners,
VHeaderDesktop: () => import("~/components/VHeader/VHeaderDesktop.vue"),
VHeaderInternal: () => import("~/components/VHeader/VHeaderInternal.vue"),
VHeaderMobile: () =>
import("~/components/VHeader/VHeaderMobile/VHeaderMobile.vue"),
VFooter: () => import("~/components/VFooter/VFooter.vue"),
VHeaderOld,
VModalTarget,
VTeleportTarget,
VGlobalAudioSection,
VSearchGridFilter,
},
setup() {
const { app } = useContext()
const uiStore = useUiStore()
const featureFlagStore = useFeatureFlagStore()
const searchStore = useSearchStore()
const isNewHeaderEnabled = computed(() =>
featureFlagStore.isOn("new_header")
)
const { updateBreakpoint } = useLayout()
/**
* Update the breakpoint value in the cookie on mounted.
* The Pinia state might become different from the cookie state if, for example, the cookies were saved when the screen was `sm`,
* and then a page is opened on SSR on a `lg` screen.
*/
onMounted(() => {
updateBreakpoint()
})
const { matches: isSearchRoute } = useMatchSearchRoutes()
const { matches: isSingleResultRoute } = useMatchSingleResultRoutes()
const { matches: isContentPageRoute } = useMatchContentPageRoutes()
const nuxtError = computed(() => app.nuxt.err)
const isWhite = computed(
() =>
!nuxtError.value &&
(isSearchRoute.value ||
isSingleResultRoute.value ||
isContentPageRoute.value)
)
const isSearchHeader = computed(
() =>
!nuxtError.value && (isSearchRoute.value || isSingleResultRoute.value)
)
const isDesktopLayout = computed(() => uiStore.isDesktopLayout)
const breakpoint = computed(() => uiStore.breakpoint)
/**
* Filters sidebar is visible only on desktop layouts
* on search result pages for supported search types.
*/
const isSidebarVisible = computed(
() =>
isSearchRoute.value &&
searchStore.searchTypeIsSupported &&
uiStore.isFilterVisible &&
isDesktopLayout.value
)
const closeSidebar = () => {
uiStore.setFiltersState(false)
}
const isHeaderScrolled = ref(false)
const { isScrolled: isMainContentScrolled, y: scrollY } = useWindowScroll()
watch([isMainContentScrolled], ([isMainContentScrolled]) => {
isHeaderScrolled.value = isMainContentScrolled
})
const showScrollButton = computed(() => scrollY.value > 70)
provide("isHeaderScrolled", isHeaderScrolled)
provide("showScrollButton", showScrollButton)
provide(IsHeaderScrolledKey, isHeaderScrolled)
provide(IsSidebarVisibleKey, isSidebarVisible)
// TODO: remove `headerHasTwoRows` provide after the new header is enabled.
const headerHasTwoRows = computed(
() =>
isSearchRoute.value && !isHeaderScrolled.value && !isDesktopLayout.value
)
provide("headerHasTwoRows", headerHasTwoRows)
return {
isHeaderScrolled,
isDesktopLayout,
isSidebarVisible,
isSearchRoute,
isSearchHeader,
headerHasTwoRows,
isNewHeaderEnabled,
isWhite,
breakpoint,
closeSidebar,
}
},
head() {
return this.$nuxtI18nHead({ addSeoAttributes: true, addDirAttribute: true })
},
})
</script>

<style scoped>
.has-sidebar .sidebar {
width: var(--filter-sidebar-width);
}
</style>
Loading

0 comments on commit 202935c

Please sign in to comment.