fix(webapp): fix popover flickering (#8555)

Add boundary to v-popover to avoid random flickering when hovering a user teaser
Preload user data to avoid resizing (and sometimes repositioning) of popover after data has been loaded
This commit is contained in:
Max 2025-05-20 09:21:22 +02:00 committed by GitHub
parent 35729dfb6a
commit 7ea8107ed0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 80 additions and 9 deletions

View File

@ -4,6 +4,7 @@ exports[`GroupContentMenu renders as groupProfile when I am the owner 1`] = `
<div>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="group-content-menu"
container="body"
delay="0"
@ -121,6 +122,7 @@ exports[`GroupContentMenu renders as groupProfile, muted 1`] = `
<div>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="group-content-menu"
container="body"
delay="0"
@ -196,6 +198,7 @@ exports[`GroupContentMenu renders as groupProfile, not muted 1`] = `
<div>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="group-content-menu"
container="body"
delay="0"
@ -271,6 +274,7 @@ exports[`GroupContentMenu renders as groupTeaser 1`] = `
<div>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="group-content-menu"
container="body"
delay="0"

View File

@ -6,6 +6,7 @@
:disabled="disabled"
trigger="manual"
:offset="offset"
boundaries-element="body"
>
<slot :toggleMenu="toggleMenu" :openMenu="openMenu" :closeMenu="closeMenu" :isOpen="isOpen" />
<div slot="popover" @mouseover="popoverMouseEnter" @mouseleave="popoverMouseLeave">
@ -72,7 +73,7 @@ export default {
}
},
closeMenu(useTimeout) {
if (this.disabled) {
if (this.noMouseLeaveClosing || this.disabled) {
return
}
this.clearTimeouts()

View File

@ -86,6 +86,12 @@ describe('UserTeaser', () => {
},
mocks: {
$t: jest.fn((t) => t),
$i18n: {
locale: jest.fn(() => 'en'),
},
$apollo: {
query: jest.fn(() => Promise.resolve({ data: { user } })),
},
},
})
}

View File

@ -6,7 +6,7 @@
:link-to-profile="linkToProfile"
:show-popover="showPopover"
:user-link="userLink"
@open-menu="openMenu(false)"
@open-menu="loadPopover(openMenu)"
@close-menu="closeMenu(false)"
data-test="avatarUserLink"
>
@ -18,7 +18,7 @@
:link-to-profile="linkToProfile"
:show-popover="showPopover"
:user-link="userLink"
@open-menu="openMenu(false)"
@open-menu="loadPopover(openMenu)"
@close-menu="closeMenu(false)"
>
<span class="slug">{{ userSlug }}</span>
@ -57,6 +57,7 @@
<script>
import { mapGetters } from 'vuex'
import { userTeaserQuery } from '~/graphql/User.js'
import DateTime from '~/components/DateTime'
import Dropdown from '~/components/Dropdown'
import ProfileAvatar from '~/components/_new/generic/ProfileAvatar/ProfileAvatar'
@ -119,5 +120,15 @@ export default {
return name || this.$t('profile.userAnonym')
},
},
methods: {
async loadPopover(openMenu) {
// Load user data if not already loaded, to avoid flickering
await this.$apollo.query({
query: userTeaserQuery(this.$i18n),
variables: { id: this.user.id },
})
openMenu(false)
},
},
}
</script>

View File

@ -1,6 +1,5 @@
<template>
<div class="placeholder" v-if="!user" />
<div class="user-teaser-popover" v-else>
<div class="user-teaser-popover">
<badges
v-if="$env.BADGES_ENABLED && user.badgeVerification"
:badges="[user.badgeVerification, ...user.badgeTrophiesSelected]"
@ -67,10 +66,6 @@ export default {
</script>
<style scoped>
.placeholder {
height: 200px;
width: 200px;
}
.user-teaser-popover {
display: flex;
flex-direction: column;

View File

@ -9,6 +9,7 @@ exports[`UserTeaser given an user avatar is disabled does not render the avatar
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="user-teaser"
container="body"
delay="0"
@ -135,6 +136,7 @@ exports[`UserTeaser given an user user is disabled current user is a moderator r
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="user-teaser"
container="body"
delay="0"
@ -250,6 +252,7 @@ exports[`UserTeaser given an user with linkToProfile, on desktop renders 1`] = `
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="user-teaser"
container="body"
delay="0"
@ -333,6 +336,7 @@ exports[`UserTeaser given an user with linkToProfile, on desktop when hovering t
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="user-teaser"
container="body"
delay="0"
@ -422,6 +426,7 @@ exports[`UserTeaser given an user with linkToProfile, on touch screen renders 1`
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="user-teaser"
container="body"
delay="0"
@ -505,6 +510,7 @@ exports[`UserTeaser given an user with linkToProfile, on touch screen when click
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="user-teaser"
container="body"
delay="0"
@ -594,6 +600,7 @@ exports[`UserTeaser given an user without linkToProfile, on desktop renders 1`]
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="user-teaser"
container="body"
delay="0"
@ -677,6 +684,7 @@ exports[`UserTeaser given an user without linkToProfile, on desktop when hoverin
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="user-teaser"
container="body"
delay="0"
@ -765,6 +773,7 @@ exports[`UserTeaser given an user without linkToProfile, on desktop when hoverin
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="user-teaser"
container="body"
delay="0"
@ -853,6 +862,7 @@ exports[`UserTeaser given an user without linkToProfile, on touch screen renders
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="user-teaser"
container="body"
delay="0"
@ -936,6 +946,7 @@ exports[`UserTeaser given an user without linkToProfile, on touch screen when cl
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="user-teaser"
container="body"
delay="0"
@ -1024,6 +1035,7 @@ exports[`UserTeaser given an user without linkToProfile, on touch screen when cl
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="user-teaser"
container="body"
delay="0"

View File

@ -67,6 +67,7 @@ exports[`GroupProfileSlug given a puplic group "yoga-practice" given a close
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="group-content-menu group-profile-content-menu"
container="body"
delay="0"
@ -517,6 +518,7 @@ exports[`GroupProfileSlug given a puplic group "yoga-practice" given a close
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="user-teaser"
container="body"
delay="0"
@ -597,6 +599,7 @@ exports[`GroupProfileSlug given a puplic group "yoga-practice" given a close
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="user-teaser"
container="body"
delay="0"
@ -677,6 +680,7 @@ exports[`GroupProfileSlug given a puplic group "yoga-practice" given a close
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="user-teaser"
container="body"
delay="0"
@ -757,6 +761,7 @@ exports[`GroupProfileSlug given a puplic group "yoga-practice" given a close
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="user-teaser"
container="body"
delay="0"
@ -1981,6 +1986,7 @@ exports[`GroupProfileSlug given a puplic group "yoga-practice" given a close
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="group-content-menu group-profile-content-menu"
container="body"
delay="0"
@ -2388,6 +2394,7 @@ exports[`GroupProfileSlug given a puplic group "yoga-practice" given a close
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="user-teaser"
container="body"
delay="0"
@ -2468,6 +2475,7 @@ exports[`GroupProfileSlug given a puplic group "yoga-practice" given a close
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="user-teaser"
container="body"
delay="0"
@ -2548,6 +2556,7 @@ exports[`GroupProfileSlug given a puplic group "yoga-practice" given a close
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="user-teaser"
container="body"
delay="0"
@ -2628,6 +2637,7 @@ exports[`GroupProfileSlug given a puplic group "yoga-practice" given a close
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="user-teaser"
container="body"
delay="0"
@ -2946,6 +2956,7 @@ exports[`GroupProfileSlug given a puplic group "yoga-practice" given a curre
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="group-content-menu group-profile-content-menu"
container="body"
delay="0"
@ -3362,6 +3373,7 @@ exports[`GroupProfileSlug given a puplic group "yoga-practice" given a curre
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="user-teaser"
container="body"
delay="0"
@ -3442,6 +3454,7 @@ exports[`GroupProfileSlug given a puplic group "yoga-practice" given a curre
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="user-teaser"
container="body"
delay="0"
@ -3522,6 +3535,7 @@ exports[`GroupProfileSlug given a puplic group "yoga-practice" given a curre
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="user-teaser"
container="body"
delay="0"
@ -3602,6 +3616,7 @@ exports[`GroupProfileSlug given a puplic group "yoga-practice" given a curre
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="user-teaser"
container="body"
delay="0"
@ -4181,6 +4196,7 @@ exports[`GroupProfileSlug given a puplic group "yoga-practice" given a curre
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="user-teaser"
container="body"
delay="0"
@ -4261,6 +4277,7 @@ exports[`GroupProfileSlug given a puplic group "yoga-practice" given a curre
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="user-teaser"
container="body"
delay="0"
@ -4341,6 +4358,7 @@ exports[`GroupProfileSlug given a puplic group "yoga-practice" given a curre
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="user-teaser"
container="body"
delay="0"
@ -4421,6 +4439,7 @@ exports[`GroupProfileSlug given a puplic group "yoga-practice" given a curre
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="user-teaser"
container="body"
delay="0"
@ -4998,6 +5017,7 @@ exports[`GroupProfileSlug given a puplic group "yoga-practice" given a curre
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="user-teaser"
container="body"
delay="0"
@ -5078,6 +5098,7 @@ exports[`GroupProfileSlug given a puplic group "yoga-practice" given a curre
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="user-teaser"
container="body"
delay="0"
@ -5158,6 +5179,7 @@ exports[`GroupProfileSlug given a puplic group "yoga-practice" given a curre
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="user-teaser"
container="body"
delay="0"
@ -5238,6 +5260,7 @@ exports[`GroupProfileSlug given a puplic group "yoga-practice" given a curre
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="user-teaser"
container="body"
delay="0"
@ -5511,6 +5534,7 @@ exports[`GroupProfileSlug given a puplic group "yoga-practice" given a curre
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="group-content-menu group-profile-content-menu"
container="body"
delay="0"
@ -5884,6 +5908,7 @@ exports[`GroupProfileSlug given a puplic group "yoga-practice" given a curre
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="user-teaser"
container="body"
delay="0"
@ -5964,6 +5989,7 @@ exports[`GroupProfileSlug given a puplic group "yoga-practice" given a curre
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="user-teaser"
container="body"
delay="0"
@ -6044,6 +6070,7 @@ exports[`GroupProfileSlug given a puplic group "yoga-practice" given a curre
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="user-teaser"
container="body"
delay="0"
@ -6124,6 +6151,7 @@ exports[`GroupProfileSlug given a puplic group "yoga-practice" given a curre
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="user-teaser"
container="body"
delay="0"
@ -6447,6 +6475,7 @@ exports[`GroupProfileSlug given a puplic group "yoga-practice" given a hidde
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="group-content-menu group-profile-content-menu"
container="body"
delay="0"
@ -6905,6 +6934,7 @@ exports[`GroupProfileSlug given a puplic group "yoga-practice" given a hidde
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="user-teaser"
container="body"
delay="0"
@ -6985,6 +7015,7 @@ exports[`GroupProfileSlug given a puplic group "yoga-practice" given a hidde
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="user-teaser"
container="body"
delay="0"
@ -7065,6 +7096,7 @@ exports[`GroupProfileSlug given a puplic group "yoga-practice" given a hidde
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="user-teaser"
container="body"
delay="0"
@ -7145,6 +7177,7 @@ exports[`GroupProfileSlug given a puplic group "yoga-practice" given a hidde
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="user-teaser"
container="body"
delay="0"
@ -7464,6 +7497,7 @@ exports[`GroupProfileSlug given a puplic group "yoga-practice" given a hidde
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="group-content-menu group-profile-content-menu"
container="body"
delay="0"
@ -7879,6 +7913,7 @@ exports[`GroupProfileSlug given a puplic group "yoga-practice" given a hidde
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="user-teaser"
container="body"
delay="0"
@ -7959,6 +7994,7 @@ exports[`GroupProfileSlug given a puplic group "yoga-practice" given a hidde
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="user-teaser"
container="body"
delay="0"
@ -8039,6 +8075,7 @@ exports[`GroupProfileSlug given a puplic group "yoga-practice" given a hidde
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="user-teaser"
container="body"
delay="0"
@ -8119,6 +8156,7 @@ exports[`GroupProfileSlug given a puplic group "yoga-practice" given a hidde
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="user-teaser"
container="body"
delay="0"

View File

@ -37,6 +37,7 @@ exports[`ProfileSlug given an authenticated user given another profile user and
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="content-menu user-content-menu"
container="body"
delay="0"
@ -655,6 +656,7 @@ exports[`ProfileSlug given an authenticated user given another profile user and
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="content-menu user-content-menu"
container="body"
delay="0"
@ -1338,6 +1340,7 @@ exports[`ProfileSlug given an authenticated user given the logged in user as pro
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="content-menu user-content-menu"
container="body"
delay="0"
@ -1901,6 +1904,7 @@ exports[`ProfileSlug given an authenticated user given the logged in user as pro
<client-only-stub>
<v-popover-stub
autohide="true"
boundarieselement="body"
class="content-menu user-content-menu"
container="body"
delay="0"