positioning mention popovers works now

This commit is contained in:
Shpuld Shpuldson 2020-07-21 18:05:57 +03:00
parent cebf4989e7
commit 4545f20f86
5 changed files with 34 additions and 14 deletions

View file

@ -18,8 +18,8 @@ const Popover = {
// Takes a x/y object and tells how many pixels to offset from
// anchor point on either axis
offset: Object,
// Takes an element to use for positioning over this.$el
offsetElement: null,
// Takes a x/y/h object and tells how much to offset the anchor point
anchorOffset: Object,
// Additional styles you may want for the popover container
popoverClass: String,
// Time in milliseconds until the popup appears, default is 100ms
@ -49,11 +49,17 @@ const Popover = {
// Popover will be anchored around this element, trigger ref is the container, so
// its children are what are inside the slot. Expect only one slot="trigger".
const anchorEl = (this.$refs.trigger && this.$refs.trigger.children[0]) || this.$el
const positionElement = this.offsetElement ? this.offsetElement : anchorEl
const screenBox = positionElement.getBoundingClientRect()
console.log(positionElement, screenBox)
const screenBox = anchorEl.getBoundingClientRect()
// Screen position of the origin point for popover
const origin = { x: screenBox.left + screenBox.width * 0.5, y: screenBox.top }
const anchorOffset = {
x: (this.anchorOffset && this.anchorOffset.x) || 0,
y: (this.anchorOffset && this.anchorOffset.y) || 0,
h: (this.anchorOffset && this.anchorOffset.h) || 0
}
const origin = {
x: screenBox.left + screenBox.width * 0.5 + anchorOffset.x,
y: screenBox.top + anchorOffset.y
}
const content = this.$refs.content
// Minor optimization, don't call a slow reflow call if we don't have to
const parentBounds = this.boundTo &&
@ -102,21 +108,23 @@ const Popover = {
if (origin.y - content.offsetHeight < yBounds.min) usingTop = false
const yOffset = (this.offset && this.offset.y) || 0
const anchorHeight = anchorOffset.h || anchorEl.offsetHeight
const translateY = usingTop
? -positionElement.offsetHeight - yOffset - content.offsetHeight
: yOffset
? -anchorEl.offsetHeight - yOffset - content.offsetHeight + anchorOffset.y
: -anchorEl.offsetHeight + anchorHeight + yOffset + anchorOffset.y
const xOffset = (this.offset && this.offset.x) || 0
const translateX = (positionElement.offsetWidth * 0.5) - content.offsetWidth * 0.5 + horizOffset + xOffset
const translateX = (anchorEl.offsetWidth * 0.5) - content.offsetWidth * 0.5 + horizOffset + xOffset + anchorOffset.x
// Note, separate translateX and translateY avoids blurry text on chromium,
// single translate or translate3d resulted in blurry text.
this.styles = {
opacity: 1,
transform: `translateX(${Math.floor(translateX)}px) translateY(${Math.floor(translateY)}px)`
transform: `translateX(${Math.round(translateX)}px) translateY(${Math.round(translateY)}px)`
}
},
showPopover () {
if (!this.$el) return
if (this.trigger === 'hover' && !this.hovered) return
if (this.hidden) this.$emit('show')
this.hidden = false

View file

@ -32,7 +32,7 @@ const StatusContent = {
// not as computed because it sets the initial state which will be changed later
expandingSubject: !this.$store.getters.mergedConfig.collapseMessageWithSubject,
focusedUserId: null,
focusedUserElement: null
userPopoverOffset: { x: 0, y: 0 }
}
},
computed: {
@ -190,7 +190,12 @@ const StatusContent = {
event.stopPropagation()
event.preventDefault()
this.focusedUserId = attn.id
this.focusedUserElement = target
// Give the popover an offset to place it over the hovered element
const containerWidth = this.$refs.userPopover.$el.offsetWidth
const elementWidth = target.offsetWidth
const x = -containerWidth / 2 + target.offsetLeft + elementWidth / 2
const y = target.offsetTop
this.userPopoverOffset = { x, y, h: target.offsetHeight }
}
}
}

View file

@ -29,7 +29,10 @@
</a>
</div>
<UserPopover
ref="userPopover"
class="status-user-popover"
:user-id="focusedUserId"
:anchor-offset="userPopoverOffset"
>
<div
:class="{'tall-status': hideTallStatus}"
@ -142,6 +145,10 @@ $status-margin: 0.75em;
flex: 1;
min-width: 0;
.status-user-popover {
position: relative;
}
.status-content-wrapper {
display: flex;
flex-direction: column;

View file

@ -3,7 +3,7 @@ const UserPopover = {
name: 'UserPopover',
props: [
'userId',
'focusedElement'
'anchorOffset'
],
data () {
return {

View file

@ -6,7 +6,7 @@
popover-class="user-popover"
:bound-to="{ x: 'container' }"
:delay="200"
:offset-element="focusedElement"
:anchor-offset="anchorOffset"
@show="enter"
>
<template slot="trigger">