user popovers WIP
This commit is contained in:
parent
3628fb4272
commit
7c633aa952
|
@ -34,7 +34,13 @@ const Popover = {
|
||||||
removePadding: Boolean,
|
removePadding: Boolean,
|
||||||
|
|
||||||
// self-explanatory (i hope)
|
// self-explanatory (i hope)
|
||||||
disabled: Boolean
|
disabled: Boolean,
|
||||||
|
|
||||||
|
// Instead of putting popover next to anchor, overlay popover's center on top of anchor's center
|
||||||
|
overlayCenters: Boolean,
|
||||||
|
|
||||||
|
// What selector (witin popover!) to use for determining center of popover
|
||||||
|
overlayCentersSelector: String
|
||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
|
@ -73,7 +79,9 @@ const Popover = {
|
||||||
x: anchorScreenBox.left + anchorWidth * 0.5,
|
x: anchorScreenBox.left + anchorWidth * 0.5,
|
||||||
y: anchorScreenBox.top + anchorHeight * 0.5
|
y: anchorScreenBox.top + anchorHeight * 0.5
|
||||||
}
|
}
|
||||||
const content = this.$refs.content
|
const content = this.overlayCentersSelector
|
||||||
|
? this.$refs.content.querySelector(this.overlayCentersSelector)
|
||||||
|
: this.$refs.content
|
||||||
|
|
||||||
// Minor optimization, don't call a slow reflow call if we don't have to
|
// Minor optimization, don't call a slow reflow call if we don't have to
|
||||||
const parentScreenBox = this.boundTo &&
|
const parentScreenBox = this.boundTo &&
|
||||||
|
@ -100,44 +108,51 @@ const Popover = {
|
||||||
max: window.innerHeight - (margin.bottom || 5)
|
max: window.innerHeight - (margin.bottom || 5)
|
||||||
}
|
}
|
||||||
|
|
||||||
let horizOffset = content.offsetWidth * -0.5
|
if (!this.overlayCenters) {
|
||||||
const leftBorder = origin.x + horizOffset
|
let horizOffset = content.offsetWidth * -0.5
|
||||||
const rightBorder = origin.x - horizOffset
|
const leftBorder = origin.x + horizOffset
|
||||||
// If overflowing from left, move it so that it doesn't
|
const rightBorder = origin.x - horizOffset
|
||||||
if (leftBorder < xBounds.min) {
|
// If overflowing from left, move it so that it doesn't
|
||||||
horizOffset += xBounds.min - leftBorder
|
if (leftBorder < xBounds.min) {
|
||||||
}
|
horizOffset += xBounds.min - leftBorder
|
||||||
|
}
|
||||||
|
|
||||||
// If overflowing from right, move it so that it doesn't
|
// If overflowing from right, move it so that it doesn't
|
||||||
if (rightBorder > xBounds.max) {
|
if (rightBorder > xBounds.max) {
|
||||||
horizOffset -= rightBorder - xBounds.max
|
horizOffset -= rightBorder - xBounds.max
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default to whatever user wished with placement prop
|
// Default to whatever user wished with placement prop
|
||||||
let usingTop = this.placement !== 'bottom'
|
let usingTop = this.placement !== 'bottom'
|
||||||
|
|
||||||
// Handle special cases, first force to displaying on top if there's not space on bottom,
|
// Handle special cases, first force to displaying on top if there's not space on bottom,
|
||||||
// regardless of what placement value was. Then check if there's not space on top, and
|
// regardless of what placement value was. Then check if there's not space on top, and
|
||||||
// force to bottom, again regardless of what placement value was.
|
// force to bottom, again regardless of what placement value was.
|
||||||
const topBoundary = origin.y - anchorHeight * 0.5 + (this.removePadding ? topPadding : 0)
|
const topBoundary = origin.y - anchorHeight * 0.5 + (this.removePadding ? topPadding : 0)
|
||||||
const bottomBoundary = origin.y + anchorHeight * 0.5 - (this.removePadding ? bottomPadding : 0)
|
const bottomBoundary = origin.y + anchorHeight * 0.5 - (this.removePadding ? bottomPadding : 0)
|
||||||
if (bottomBoundary + content.offsetHeight > yBounds.max) usingTop = true
|
if (bottomBoundary + content.offsetHeight > yBounds.max) usingTop = true
|
||||||
if (topBoundary - content.offsetHeight < yBounds.min) usingTop = false
|
if (topBoundary - content.offsetHeight < yBounds.min) usingTop = false
|
||||||
|
|
||||||
const yOffset = (this.offset && this.offset.y) || 0
|
const yOffset = (this.offset && this.offset.y) || 0
|
||||||
const translateY = usingTop
|
const translateY = usingTop
|
||||||
? topBoundary - yOffset - content.offsetHeight
|
? topBoundary - yOffset - content.offsetHeight
|
||||||
: bottomBoundary + yOffset
|
: bottomBoundary + yOffset
|
||||||
|
|
||||||
const xOffset = (this.offset && this.offset.x) || 0
|
const xOffset = (this.offset && this.offset.x) || 0
|
||||||
const translateX = origin.x + horizOffset + xOffset
|
const translateX = origin.x + horizOffset + xOffset
|
||||||
|
|
||||||
// Note, separate translateX and translateY avoids blurry text on chromium,
|
this.styles = {
|
||||||
// single translate or translate3d resulted in blurry text.
|
left: `${Math.round(translateX)}px`,
|
||||||
this.styles = {
|
top: `${Math.round(translateY)}px`
|
||||||
left: `${Math.round(translateX)}px`,
|
}
|
||||||
top: `${Math.round(translateY)}px`,
|
} else {
|
||||||
position: 'fixed'
|
const translateY = origin.y - content.offsetHeight
|
||||||
|
const translateX = origin.x - content.offsetWidth
|
||||||
|
|
||||||
|
this.styles = {
|
||||||
|
left: `${Math.round(translateX)}px`,
|
||||||
|
top: `${Math.round(translateY)}px`
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parentScreenBox) {
|
if (parentScreenBox) {
|
||||||
|
|
|
@ -44,7 +44,7 @@
|
||||||
|
|
||||||
.popover {
|
.popover {
|
||||||
z-index: 90000;
|
z-index: 90000;
|
||||||
position: absolute;
|
position: fixed;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
box-shadow: 2px 2px 3px rgba(0, 0, 0, 0.5);
|
box-shadow: 2px 2px 3px rgba(0, 0, 0, 0.5);
|
||||||
box-shadow: var(--popupShadow);
|
box-shadow: var(--popupShadow);
|
||||||
|
|
|
@ -11,6 +11,7 @@ import Timeago from '../timeago/timeago.vue'
|
||||||
import StatusContent from '../status_content/status_content.vue'
|
import StatusContent from '../status_content/status_content.vue'
|
||||||
import RichContent from 'src/components/rich_content/rich_content.jsx'
|
import RichContent from 'src/components/rich_content/rich_content.jsx'
|
||||||
import StatusPopover from '../status_popover/status_popover.vue'
|
import StatusPopover from '../status_popover/status_popover.vue'
|
||||||
|
import Popover from '../popover/popover.vue'
|
||||||
import UserListPopover from '../user_list_popover/user_list_popover.vue'
|
import UserListPopover from '../user_list_popover/user_list_popover.vue'
|
||||||
import EmojiReactions from '../emoji_reactions/emoji_reactions.vue'
|
import EmojiReactions from '../emoji_reactions/emoji_reactions.vue'
|
||||||
import MentionsLine from 'src/components/mentions_line/mentions_line.vue'
|
import MentionsLine from 'src/components/mentions_line/mentions_line.vue'
|
||||||
|
@ -115,7 +116,8 @@ const Status = {
|
||||||
StatusContent,
|
StatusContent,
|
||||||
RichContent,
|
RichContent,
|
||||||
MentionLink,
|
MentionLink,
|
||||||
MentionsLine
|
MentionsLine,
|
||||||
|
Popover
|
||||||
},
|
},
|
||||||
props: [
|
props: [
|
||||||
'statusoid',
|
'statusoid',
|
||||||
|
|
|
@ -122,17 +122,33 @@
|
||||||
v-if="!noHeading"
|
v-if="!noHeading"
|
||||||
class="left-side"
|
class="left-side"
|
||||||
>
|
>
|
||||||
<a
|
<a :href="$router.resolve(userProfileLink).href" @click.prevent>
|
||||||
:href="$router.resolve(userProfileLink).href"
|
<Popover
|
||||||
@click.stop.prevent.capture="toggleUserExpanded"
|
trigger="click"
|
||||||
>
|
popover-class="popover-default user-popover"
|
||||||
<UserAvatar
|
:overlay-centers="true"
|
||||||
class="post-avatar"
|
overlay-centers-selector=".user-info-avatar-link .Avatar"
|
||||||
:bot="botIndicator"
|
>
|
||||||
:compact="compact"
|
<template v-slot:trigger>
|
||||||
:better-shadow="betterShadow"
|
<UserAvatar
|
||||||
:user="status.user"
|
class="post-avatar"
|
||||||
/>
|
:bot="botIndicator"
|
||||||
|
:compact="compact"
|
||||||
|
:better-shadow="betterShadow"
|
||||||
|
:user="status.user"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<template v-slot:content>
|
||||||
|
<UserCard
|
||||||
|
class="mention-link-popover"
|
||||||
|
:user-id="status.user.id"
|
||||||
|
:hide-bio="true"
|
||||||
|
:bordered="false"
|
||||||
|
:allow-zooming-avatar="true"
|
||||||
|
:rounded="true"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</Popover>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="right-side">
|
<div class="right-side">
|
||||||
|
|
Loading…
Reference in New Issue