fix animations, replace ugly old mentionlink tooltips with new usercard ones
This commit is contained in:
parent
61d63b0e61
commit
55adcd822e
8 changed files with 140 additions and 90 deletions
|
@ -829,7 +829,7 @@ option {
|
|||
// Vue transitions
|
||||
.fade-enter-active,
|
||||
.fade-leave-active {
|
||||
transition: opacity 0.2s;
|
||||
transition: opacity 0.3s;
|
||||
}
|
||||
|
||||
.fade-enter-from,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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') {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -269,7 +269,7 @@
|
|||
path="mentionLinkShowTooltip"
|
||||
expert="1"
|
||||
>
|
||||
{{ $t('settings.mention_link_show_tooltip') }}
|
||||
{{ $t('settings.mention_link_use_tooltip') }}
|
||||
</BooleanSetting>
|
||||
</li>
|
||||
</ul>
|
||||
|
|
|
@ -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",
|
||||
|
|
Loading…
Reference in a new issue