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

Fix the header scrolling #2155

Merged
merged 3 commits into from
Feb 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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