fix: project card preload on hover (#5348)

This commit is contained in:
Truman Gao
2026-02-09 16:37:58 -07:00
committed by GitHub
parent a536d795f3
commit cec35dcb60
2 changed files with 21 additions and 15 deletions

View File

@@ -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<typeof setTimeout> | null = null
let prefetchTimeout: ReturnType<typeof useTimeoutFn> | 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"
>
<template v-if="flags.showDiscoverProjectButtons || server" #actions>
<template v-if="flags.showDiscoverProjectButtons">

View File

@@ -4,7 +4,8 @@
<AutoLink
:to="link"
class="rounded-xl no-outline no-click-animation custom-focus-indicator"
@mouseenter="$emit('hover')"
@mouseenter="$emit('mouseenter')"
@mouseleave="$emit('mouseleave')"
></AutoLink>
</template>
<div v-if="layout === 'grid'" :class="[baseCardStyle, 'flex flex-col']">
@@ -153,7 +154,8 @@ import ProjectCardTags from './ProjectCardTags.vue'
import ProjectCardTitle from './ProjectCardTitle.vue'
defineEmits<{
hover: []
mouseenter: []
mouseleave: []
}>()
const props = defineProps<{