diff --git a/app/components/AppFooter.vue b/app/components/AppFooter.vue index 08a498f92e..804d4a19fb 100644 --- a/app/components/AppFooter.vue +++ b/app/components/AppFooter.vue @@ -48,6 +48,9 @@ function onResize() { updateFooterPadding() } +useEventListener('scroll', onScroll, { passive: true }) +useEventListener('resize', onResize, { passive: true }) + onMounted(() => { // Feature detect CSS scroll-state container queries (Chrome 133+) // @see https://developer.mozilla.org/en-US/docs/Web/CSS/@container#scroll-state_container_descriptors @@ -60,14 +63,6 @@ onMounted(() => { // Only apply dynamic classes after mount to avoid hydration mismatch isMounted.value = true }) - - window.addEventListener('scroll', onScroll, { passive: true }) - window.addEventListener('resize', onResize, { passive: true }) -}) - -onUnmounted(() => { - window.removeEventListener('scroll', onScroll) - window.removeEventListener('resize', onResize) }) diff --git a/app/components/ScrollToTop.vue b/app/components/ScrollToTop.vue index 4fa1f8f9a5..1fc82cac9d 100644 --- a/app/components/ScrollToTop.vue +++ b/app/components/ScrollToTop.vue @@ -6,12 +6,15 @@ const excludedRoutes = new Set(['index', 'code']) const isActive = computed(() => !excludedRoutes.has(route.name as string)) -const isMounted = ref(false) +const isMounted = useMounted() const isVisible = ref(false) const scrollThreshold = 300 const supportsScrollStateQueries = ref(false) function onScroll() { + if (!supportsScrollStateQueries.value) { + return + } isVisible.value = window.scrollY > scrollThreshold } @@ -19,20 +22,13 @@ function scrollToTop() { window.scrollTo({ top: 0, behavior: 'smooth' }) } +useEventListener('scroll', onScroll, { passive: true }) + onMounted(() => { // Feature detect CSS scroll-state container queries (Chrome 133+) supportsScrollStateQueries.value = CSS.supports('container-type', 'scroll-state') - if (!supportsScrollStateQueries.value) { - window.addEventListener('scroll', onScroll, { passive: true }) - onScroll() - } - - isMounted.value = true -}) - -onUnmounted(() => { - window.removeEventListener('scroll', onScroll) + onScroll() }) diff --git a/app/pages/code/[...path].vue b/app/pages/code/[...path].vue index 665f807bde..dd24a6c3d3 100644 --- a/app/pages/code/[...path].vue +++ b/app/pages/code/[...path].vue @@ -139,14 +139,12 @@ const { data: fileContent, status: fileStatus } = useFetch { currentHash.value = window.location.hash - window.addEventListener('popstate', () => { - currentHash.value = window.location.hash - }) }) +useEventListener('popstate', () => (currentHash.value = window.location.hash)) + // Also sync when route changes (e.g., navigating to a different file) watch( () => route.hash, diff --git a/nuxt.config.ts b/nuxt.config.ts index a74644486f..746fb22193 100644 --- a/nuxt.config.ts +++ b/nuxt.config.ts @@ -15,6 +15,7 @@ export default defineNuxtConfig({ 'nuxt-og-image', '@nuxt/test-utils', '@vite-pwa/nuxt', + '@vueuse/nuxt', ], devtools: { enabled: true },