commit: 7c633aa9525c8a0533281947c587ff1a5ded75ec
parent 3628fb4272c0b9f5a66f0de61e6c4f37f4908fe7
Author: Henry Jameson <me@hjkos.com>
Date: Mon, 13 Jun 2022 13:45:04 +0300
user popovers WIP
Diffstat:
4 files changed, 84 insertions(+), 51 deletions(-)
diff --git a/src/components/popover/popover.js b/src/components/popover/popover.js
@@ -34,7 +34,13 @@ const Popover = {
removePadding: Boolean,
// 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 () {
return {
@@ -73,7 +79,9 @@ const Popover = {
x: anchorScreenBox.left + anchorWidth * 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
const parentScreenBox = this.boundTo &&
@@ -100,44 +108,51 @@ const Popover = {
max: window.innerHeight - (margin.bottom || 5)
}
- let horizOffset = content.offsetWidth * -0.5
- const leftBorder = origin.x + horizOffset
- const rightBorder = origin.x - horizOffset
- // If overflowing from left, move it so that it doesn't
- if (leftBorder < xBounds.min) {
- horizOffset += xBounds.min - leftBorder
- }
+ if (!this.overlayCenters) {
+ let horizOffset = content.offsetWidth * -0.5
+ const leftBorder = origin.x + horizOffset
+ const rightBorder = origin.x - horizOffset
+ // If overflowing from left, move it so that it doesn't
+ if (leftBorder < xBounds.min) {
+ horizOffset += xBounds.min - leftBorder
+ }
- // If overflowing from right, move it so that it doesn't
- if (rightBorder > xBounds.max) {
- horizOffset -= rightBorder - xBounds.max
- }
+ // If overflowing from right, move it so that it doesn't
+ if (rightBorder > xBounds.max) {
+ horizOffset -= rightBorder - xBounds.max
+ }
+
+ // Default to whatever user wished with placement prop
+ let usingTop = this.placement !== 'bottom'
- // Default to whatever user wished with placement prop
- let usingTop = this.placement !== '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
- // force to bottom, again regardless of what placement value was.
- const topBoundary = origin.y - anchorHeight * 0.5 + (this.removePadding ? topPadding : 0)
- const bottomBoundary = origin.y + anchorHeight * 0.5 - (this.removePadding ? bottomPadding : 0)
- if (bottomBoundary + content.offsetHeight > yBounds.max) usingTop = true
- if (topBoundary - content.offsetHeight < yBounds.min) usingTop = false
-
- const yOffset = (this.offset && this.offset.y) || 0
- const translateY = usingTop
- ? topBoundary - yOffset - content.offsetHeight
- : bottomBoundary + yOffset
-
- const xOffset = (this.offset && this.offset.x) || 0
- const translateX = origin.x + horizOffset + xOffset
-
- // Note, separate translateX and translateY avoids blurry text on chromium,
- // single translate or translate3d resulted in blurry text.
- this.styles = {
- left: `${Math.round(translateX)}px`,
- top: `${Math.round(translateY)}px`,
- position: 'fixed'
+ // 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
+ // force to bottom, again regardless of what placement value was.
+ const topBoundary = origin.y - anchorHeight * 0.5 + (this.removePadding ? topPadding : 0)
+ const bottomBoundary = origin.y + anchorHeight * 0.5 - (this.removePadding ? bottomPadding : 0)
+ if (bottomBoundary + content.offsetHeight > yBounds.max) usingTop = true
+ if (topBoundary - content.offsetHeight < yBounds.min) usingTop = false
+
+ const yOffset = (this.offset && this.offset.y) || 0
+ const translateY = usingTop
+ ? topBoundary - yOffset - content.offsetHeight
+ : bottomBoundary + yOffset
+
+ const xOffset = (this.offset && this.offset.x) || 0
+ const translateX = origin.x + horizOffset + xOffset
+
+ this.styles = {
+ left: `${Math.round(translateX)}px`,
+ top: `${Math.round(translateY)}px`
+ }
+ } else {
+ 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) {
diff --git a/src/components/popover/popover.vue b/src/components/popover/popover.vue
@@ -44,7 +44,7 @@
.popover {
z-index: 90000;
- position: absolute;
+ position: fixed;
min-width: 0;
box-shadow: 2px 2px 3px rgba(0, 0, 0, 0.5);
box-shadow: var(--popupShadow);
diff --git a/src/components/status/status.js b/src/components/status/status.js
@@ -11,6 +11,7 @@ import Timeago from '../timeago/timeago.vue'
import StatusContent from '../status_content/status_content.vue'
import RichContent from 'src/components/rich_content/rich_content.jsx'
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 EmojiReactions from '../emoji_reactions/emoji_reactions.vue'
import MentionsLine from 'src/components/mentions_line/mentions_line.vue'
@@ -115,7 +116,8 @@ const Status = {
StatusContent,
RichContent,
MentionLink,
- MentionsLine
+ MentionsLine,
+ Popover
},
props: [
'statusoid',
diff --git a/src/components/status/status.vue b/src/components/status/status.vue
@@ -122,17 +122,33 @@
v-if="!noHeading"
class="left-side"
>
- <a
- :href="$router.resolve(userProfileLink).href"
- @click.stop.prevent.capture="toggleUserExpanded"
- >
- <UserAvatar
- class="post-avatar"
- :bot="botIndicator"
- :compact="compact"
- :better-shadow="betterShadow"
- :user="status.user"
- />
+ <a :href="$router.resolve(userProfileLink).href" @click.prevent>
+ <Popover
+ trigger="click"
+ popover-class="popover-default user-popover"
+ :overlay-centers="true"
+ overlay-centers-selector=".user-info-avatar-link .Avatar"
+ >
+ <template v-slot:trigger>
+ <UserAvatar
+ 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>
</div>
<div class="right-side">