Merge branch 'disjointed-popovers' into shigusegubu-vue3

* disjointed-popovers:
  add stay-on-click prop to solve case of clicking user avatar in status popover
  fix settings tooltips
  vertical nudge for popovers, especially for overlay-centers ones
This commit is contained in:
Henry Jameson 2022-07-31 00:22:30 +03:00
commit 84f2074ea4
5 changed files with 63 additions and 17 deletions

View file

@ -40,7 +40,10 @@ const Popover = {
overlayCenters: Boolean, overlayCenters: Boolean,
// What selector (witin popover!) to use for determining center of popover // What selector (witin popover!) to use for determining center of popover
overlayCentersSelector: String overlayCentersSelector: String,
// Lets hover popover stay when clicking inside of it
stayOnClick: Boolean
}, },
inject: ['popoversZLayer'], // override popover z layer inject: ['popoversZLayer'], // override popover z layer
data () { data () {
@ -50,6 +53,7 @@ const Popover = {
// with popovers refusing to be hidden when user wants to interact with something in below popover // with popovers refusing to be hidden when user wants to interact with something in below popover
lockReEntry: false, lockReEntry: false,
hidden: true, hidden: true,
pinned: false,
styles: {}, styles: {},
oldSize: { width: 0, height: 0 }, oldSize: { width: 0, height: 0 },
scrollable: null, scrollable: null,
@ -124,13 +128,17 @@ const Popover = {
const leftInnerOffset = overlayCenterScreenBox.left - box.left const leftInnerOffset = overlayCenterScreenBox.left - box.left
const topInnerOffset = overlayCenterScreenBox.top - box.top const topInnerOffset = overlayCenterScreenBox.top - box.top
horizOffset = -leftInnerOffset - overlayCenter.offsetWidth * 0.5 horizOffset = -leftInnerOffset - overlayCenter.offsetWidth * 0.5
vertOffset = -topInnerOffset - overlayCenter.offsetWidth * 0.5 vertOffset = -topInnerOffset - overlayCenter.offsetHeight * 0.5
} else { } else {
horizOffset = content.offsetWidth * -0.5 horizOffset = content.offsetWidth * -0.5
vertOffset = content.offsetWidth * -0.5 vertOffset = content.offsetHeight * -0.5
} }
const leftBorder = origin.x + horizOffset const leftBorder = origin.x + horizOffset
const rightBorder = origin.x - horizOffset const rightBorder = leftBorder + content.offsetWidth
const topBorder = origin.y + vertOffset
const bottomBorder = topBorder + content.offsetHeight
// If overflowing from left, move it so that it doesn't // If overflowing from left, move it so that it doesn't
if (leftBorder < xBounds.min) { if (leftBorder < xBounds.min) {
horizOffset += xBounds.min - leftBorder horizOffset += xBounds.min - leftBorder
@ -141,6 +149,16 @@ const Popover = {
horizOffset -= rightBorder - xBounds.max horizOffset -= rightBorder - xBounds.max
} }
// If overflowing from top, move it so that it doesn't
if (topBorder < yBounds.min) {
vertOffset += yBounds.min - topBorder
}
// If overflowing from bottom, move it so that it doesn't
if (bottomBorder > yBounds.max) {
vertOffset -= bottomBorder - yBounds.max
}
let translateX = 0 let translateX = 0
let translateY = 0 let translateY = 0
@ -182,9 +200,10 @@ const Popover = {
}, },
showPopover () { showPopover () {
if (this.disabled) return if (this.disabled) return
this.pinned = false
const wasHidden = this.hidden const wasHidden = this.hidden
this.hidden = false this.hidden = false
if (this.trigger === 'click') { if (this.trigger === 'click' || this.stayOnClick) {
document.addEventListener('click', this.onClickOutside) document.addEventListener('click', this.onClickOutside)
} }
this.scrollable.addEventListener('scroll', this.onScroll) this.scrollable.addEventListener('scroll', this.onScroll)
@ -213,7 +232,7 @@ const Popover = {
} }
}, },
onMouseleave (e) { onMouseleave (e) {
if (this.trigger === 'hover') { if (this.trigger === 'hover' && !this.pinned) {
this.graceTimeout = setTimeout(() => this.hidePopover(), 1) this.graceTimeout = setTimeout(() => this.hidePopover(), 1)
} }
}, },
@ -226,7 +245,7 @@ const Popover = {
} }
}, },
onMouseleaveContent (e) { onMouseleaveContent (e) {
if (this.trigger === 'hover') { if (this.trigger === 'hover' && !this.pinned) {
this.graceTimeout = setTimeout(() => this.hidePopover(), 1) this.graceTimeout = setTimeout(() => this.hidePopover(), 1)
} }
}, },
@ -245,6 +264,11 @@ const Popover = {
if (this.$el.contains(e.target)) return if (this.$el.contains(e.target)) return
this.hidePopover() this.hidePopover()
}, },
onClickContent (e) {
if (this.trigger === 'hover' && this.stayOnClick) {
this.pinned = true
}
},
onScroll (e) { onScroll (e) {
this.updateStyles() this.updateStyles()
}, },

View file

@ -21,12 +21,22 @@
:class="popoverClass || 'popover-default'" :class="popoverClass || 'popover-default'"
@mouseenter="onMouseenterContent" @mouseenter="onMouseenterContent"
@mouseleave="onMouseleaveContent" @mouseleave="onMouseleaveContent"
@click="onClickContent"
> >
<slot <slot
name="content" name="content"
class="popover-inner" class="popover-inner"
:close="hidePopover" :close="hidePopover"
/> />
<div
v-if="stayOnClick && pinned"
class="pinned-tooltip-icon popover popover-default"
>
<FAIcon
icon="thumbtack"
class="faint"
/>
</div>
</div> </div>
</transition> </transition>
</teleport> </teleport>
@ -51,6 +61,17 @@
box-shadow: var(--popupShadow); box-shadow: var(--popupShadow);
} }
.pinned-tooltip-icon {
position: absolute;
top: -1em;
left: -1em;
width: 2em;
height: 2em;
display: flex;
justify-content: center;
align-items: center;
}
.popover-default { .popover-default {
&:after { &:after {
content: ''; content: '';

View file

@ -41,11 +41,11 @@ export default {
.ModifiedIndicator { .ModifiedIndicator {
display: inline-block; display: inline-block;
position: relative; position: relative;
}
.modified-tooltip { .modified-tooltip {
margin: 0.5em 1em; margin: 0.5em 1em;
min-width: 10em; min-width: 10em;
text-align: center; text-align: center;
} }
}
</style> </style>

View file

@ -41,11 +41,11 @@ export default {
.ServerSideIndicator { .ServerSideIndicator {
display: inline-block; display: inline-block;
position: relative; position: relative;
}
.serverside-tooltip { .serverside-tooltip {
margin: 0.5em 1em; margin: 0.5em 1em;
min-width: 10em; min-width: 10em;
text-align: center; text-align: center;
} }
}
</style> </style>

View file

@ -1,6 +1,7 @@
<template> <template>
<Popover <Popover
trigger="hover" trigger="hover"
:stay-on-click="true"
popover-class="popover-default status-popover" popover-class="popover-default status-popover"
:bound-to="{ x: 'container' }" :bound-to="{ x: 'container' }"
@show="enter" @show="enter"