fix animations, replace ugly old mentionlink tooltips with new usercard ones

This commit is contained in:
Henry Jameson 2022-06-12 16:31:56 +03:00
parent 61d63b0e61
commit 55adcd822e
8 changed files with 140 additions and 90 deletions

View file

@ -829,7 +829,7 @@ option {
// Vue transitions
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.2s;
transition: opacity 0.3s;
}
.fade-enter-from,

View file

@ -2,6 +2,7 @@ import generateProfileLink from 'src/services/user_profile_link_generator/user_p
import { mapGetters, mapState } from 'vuex'
import { highlightClass, highlightStyle } from '../../services/user_highlighter/user_highlighter.js'
import UserAvatar from '../user_avatar/user_avatar.vue'
import { defineAsyncComponent } from 'vue'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
faAt
@ -14,7 +15,9 @@ library.add(
const MentionLink = {
name: 'MentionLink',
components: {
UserAvatar
UserAvatar,
Popover: defineAsyncComponent(() => import('../popover/popover.vue')),
UserCard: defineAsyncComponent(() => import('../user_card/user_card.vue'))
},
props: {
url: {
@ -36,6 +39,7 @@ const MentionLink = {
},
methods: {
onClick () {
if (this.shouldShowTooltip) return
const link = generateProfileLink(
this.userId || this.user.id,
this.userScreenName || this.user.screen_name
@ -110,7 +114,7 @@ const MentionLink = {
}
},
shouldShowTooltip () {
return this.mergedConfig.mentionLinkShowTooltip && this.mergedConfig.mentionLinkDisplay === 'short' && this.isRemote
return this.mergedConfig.mentionLinkShowTooltip
},
shouldShowAvatar () {
return this.mergedConfig.mentionLinkShowAvatar

View file

@ -101,7 +101,6 @@
}
&:hover .new .full {
opacity: 1;
pointer-events: initial;
}
@ -113,3 +112,9 @@
color: var(--faint, $fallback--faint);
}
}
.mention-link-popover {
max-width: 70ch;
max-height: 20rem;
overflow: hidden;
}

View file

@ -9,66 +9,85 @@
class="original"
target="_blank"
v-html="content"
/><!-- eslint-enable vue/no-v-html --><span
v-if="user"
class="new"
:style="style"
:class="classnames"
/><!-- eslint-enable vue/no-v-html -->
<Popover
trigger="click"
:bound-to="{ x: 'container'}"
bound-to-selector=".column"
popover-class="popover-default mention-popover"
:disabled="!shouldShowTooltip"
>
<a
class="short button-unstyled"
:class="{ '-with-tooltip': shouldShowTooltip }"
:href="url"
@click.prevent="onClick"
>
<!-- eslint-disable vue/no-v-html -->
<UserAvatar
v-if="shouldShowAvatar"
class="mention-avatar"
:user="user"
/><span
class="shortName"
><FAIcon
v-if="useAtIcon"
size="sm"
icon="at"
class="at"
/>{{ !useAtIcon ? '@' : '' }}<span
class="userName"
v-html="userName"
/><span
v-if="shouldShowFullUserName"
class="serverName"
:class="{ '-faded': shouldFadeDomain }"
v-html="'@' + serverName"
/>
</span>
<template v-slot:trigger>
<span
v-if="isYou && shouldShowYous"
:class="{ '-you': shouldBoldenYou }"
> {{ ' ' + $t('status.you') }}</span>
<!-- eslint-enable vue/no-v-html -->
</a><span
v-if="shouldShowTooltip"
class="full popover-default"
:class="[highlightType]"
>
<span
class="userNameFull"
v-if="user"
class="new"
:style="style"
:class="classnames"
>
<!-- eslint-disable vue/no-v-html -->
@<span
class="userName"
v-html="userName"
/><span
class="serverName"
:class="{ '-faded': shouldFadeDomain }"
v-html="'@' + serverName"
/>
<!-- eslint-enable vue/no-v-html -->
</span>
</span>
</span>
<a
class="short button-unstyled"
:class="{ '-with-tooltip': shouldShowTooltip }"
:href="url"
@click.prevent="onClick"
>
<!-- eslint-disable vue/no-v-html -->
<UserAvatar
v-if="shouldShowAvatar"
class="mention-avatar"
:user="user"
/><span
class="shortName"
><FAIcon
v-if="useAtIcon"
size="sm"
icon="at"
class="at"
/>{{ !useAtIcon ? '@' : '' }}<span
class="userName"
v-html="userName"
/><span
v-if="shouldShowFullUserName"
class="serverName"
:class="{ '-faded': shouldFadeDomain }"
v-html="'@' + serverName"
/>
</span>
<span
v-if="isYou && shouldShowYous"
:class="{ '-you': shouldBoldenYou }"
> {{ ' ' + $t('status.you') }}</span>
<!-- eslint-enable vue/no-v-html -->
</a><span
v-if="shouldShowTooltip"
class="full"
>
<span
class="userNameFull"
>
<!-- eslint-disable vue/no-v-html -->
@<span
class="userName"
v-html="userName"
/><span
class="serverName"
:class="{ '-faded': shouldFadeDomain }"
v-html="'@' + serverName"
/>
<!-- eslint-enable vue/no-v-html -->
</span>
</span>
</span></template>
<template v-slot:content>
<UserCard
class="mention-link-popover"
:user-id="user.id"
:hide-bio="true"
:bordered="false"
:allow-zooming-avatar="true"
:rounded="true"
/>
</template>
</Popover>
</span>
</template>

View file

@ -31,13 +31,18 @@ const Popover = {
// If true, subtract padding when calculating position for the popover,
// use it when popover offset looks to be different on top vs bottom.
removePadding: Boolean
removePadding: Boolean,
// self-explanatory (i hope)
disabled: Boolean
},
data () {
return {
hidden: true,
styles: { opacity: 0 },
oldSize: { width: 0, height: 0 }
styles: {},
oldSize: { width: 0, height: 0 },
// used to avoid blinking if hovered onto popover
graceTimeout: null
}
},
methods: {
@ -47,9 +52,7 @@ const Popover = {
},
updateStyles () {
if (this.hidden) {
this.styles = {
opacity: 0
}
this.styles = {}
return
}
@ -132,7 +135,6 @@ const Popover = {
// Note, separate translateX and translateY avoids blurry text on chromium,
// single translate or translate3d resulted in blurry text.
this.styles = {
opacity: 1,
left: `${Math.round(translateX)}px`,
top: `${Math.round(translateY)}px`,
position: 'fixed'
@ -143,6 +145,7 @@ const Popover = {
}
},
showPopover () {
if (this.disabled) return
const wasHidden = this.hidden
this.hidden = false
this.$nextTick(() => {
@ -153,13 +156,30 @@ const Popover = {
hidePopover () {
if (!this.hidden) this.$emit('close')
this.hidden = true
this.styles = { opacity: 0 }
},
onMouseenter (e) {
if (this.trigger === 'hover') this.showPopover()
if (this.trigger === 'hover') {
clearTimeout(this.graceTimeout)
this.graceTimeout = null
this.showPopover()
}
},
onMouseleave (e) {
if (this.trigger === 'hover') this.hidePopover()
if (this.trigger === 'hover') {
this.graceTimeout = setTimeout(() => this.hidePopover(), 1)
}
},
onMouseenterContent (e) {
if (this.trigger === 'hover') {
clearTimeout(this.graceTimeout)
this.graceTimeout = null
this.showPopover()
}
},
onMouseleaveContent (e) {
if (this.trigger === 'hover') {
this.graceTimeout = setTimeout(() => this.hidePopover(), 1)
}
},
onClick (e) {
if (this.trigger === 'click') {

View file

@ -1,5 +1,5 @@
<template>
<div
<span
@mouseenter="onMouseenter"
@mouseleave="onMouseleave"
>
@ -12,21 +12,25 @@
<slot name="trigger" />
</button>
<teleport to="#popovers">
<div
v-if="!hidden"
ref="content"
:style="styles"
class="popover"
:class="popoverClass || 'popover-default'"
>
<slot
name="content"
class="popover-inner"
:close="hidePopover"
/>
</div>
<transition name="fade">
<div
v-if="!hidden"
ref="content"
:style="styles"
class="popover"
:class="popoverClass || 'popover-default'"
@mouseenter="onMouseenterContent"
@mouseleave="onMouseleaveContent"
>
<slot
name="content"
class="popover-inner"
:close="hidePopover"
/>
</div>
</transition>
</teleport>
</div>
</span>
</template>
<script src="./popover.js" />
@ -47,8 +51,6 @@
}
.popover-default {
transition: opacity 0.3s;
&:after {
content: '';
position: absolute;

View file

@ -269,7 +269,7 @@
path="mentionLinkShowTooltip"
expert="1"
>
{{ $t('settings.mention_link_show_tooltip') }}
{{ $t('settings.mention_link_use_tooltip') }}
</BooleanSetting>
</li>
</ul>

View file

@ -523,7 +523,7 @@
"mention_link_display_short": "always as short names (e.g. {'@'}foo)",
"mention_link_display_full_for_remote": "as full names only for remote users (e.g. {'@'}foo{'@'}example.org)",
"mention_link_display_full": "always as full names (e.g. {'@'}foo{'@'}example.org)",
"mention_link_show_tooltip": "Show full user names as tooltip for remote users",
"mention_link_use_tooltip": "Show user card when clicking mention links",
"mention_link_show_avatar": "Show user avatar beside the link",
"mention_link_fade_domain": "Fade domains (e.g. {'@'}example.org in {'@'}foo{'@'}example.org)",
"mention_link_bolden_you": "Highlight mention of you when you are mentioned",