From cec35dcb60fe1ef41a3429972c411853449cc0d7 Mon Sep 17 00:00:00 2001 From: Truman Gao <106889354+tdgao@users.noreply.github.com> Date: Mon, 9 Feb 2026 16:37:58 -0700 Subject: [PATCH] fix: project card preload on hover (#5348) --- .../src/pages/discover/[type]/index.vue | 30 +++++++++++-------- .../components/project/card/ProjectCard.vue | 6 ++-- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/apps/frontend/src/pages/discover/[type]/index.vue b/apps/frontend/src/pages/discover/[type]/index.vue index 56609a384..bf3b4b670 100644 --- a/apps/frontend/src/pages/discover/[type]/index.vue +++ b/apps/frontend/src/pages/discover/[type]/index.vue @@ -37,7 +37,7 @@ import { } from '@modrinth/ui' import { capitalizeString, cycleValue, type Mod as InstallableMod } from '@modrinth/utils' import { useQueryClient } from '@tanstack/vue-query' -import { useThrottleFn } from '@vueuse/core' +import { useThrottleFn, useTimeoutFn } from '@vueuse/core' import { computed, type Reactive, watch } from 'vue' import LogoAnimated from '~/components/brand/LogoAnimated.vue' @@ -63,18 +63,21 @@ const { handleError } = injectNotificationManager() const modrinthClient = injectModrinthClient() const queryClient = useQueryClient() -let prefetchTimeout: ReturnType | null = null +let prefetchTimeout: ReturnType | null = null +const HOVER_DURATION_TO_PREFETCH_MS = 500 -function handleProjectHover(result: Labrinth.Search.v2.ResultSearchProject) { - if (prefetchTimeout) clearTimeout(prefetchTimeout) - prefetchTimeout = setTimeout(() => { - const slug = result.slug || result.project_id - queryClient.prefetchQuery(projectQueryOptions.v2(slug, modrinthClient)) - queryClient.prefetchQuery(projectQueryOptions.v3(result.project_id, modrinthClient)) - queryClient.prefetchQuery(projectQueryOptions.members(result.project_id, modrinthClient)) - queryClient.prefetchQuery(projectQueryOptions.dependencies(result.project_id, modrinthClient)) - queryClient.prefetchQuery(projectQueryOptions.versionsV3(result.project_id, modrinthClient)) - }, 150) +const handleProjectMouseEnter = (result: Labrinth.Search.v2.ResultSearchProject) => { + const slug = result.slug || result.project_id + prefetchTimeout = useTimeoutFn( + () => queryClient.prefetchQuery(projectQueryOptions.v2(slug, modrinthClient)), + HOVER_DURATION_TO_PREFETCH_MS, + { immediate: false }, + ) + prefetchTimeout.start() +} + +const handleProjectHoverEnd = () => { + if (prefetchTimeout) prefetchTimeout.stop() } const currentType = computed(() => @@ -694,7 +697,8 @@ useSeoMeta({ :layout=" resultsDisplayMode === 'grid' || resultsDisplayMode === 'gallery' ? 'grid' : 'list' " - @hover="handleProjectHover(result)" + @mouseenter="handleProjectMouseEnter(result)" + @mouseleave="handleProjectHoverEnd" >