diff --git a/src/components/emoji_reactions/emoji_reactions.js b/src/components/emoji_reactions/emoji_reactions.js index ae7f53be..bb11b840 100644 --- a/src/components/emoji_reactions/emoji_reactions.js +++ b/src/components/emoji_reactions/emoji_reactions.js @@ -1,5 +1,5 @@ import UserAvatar from '../user_avatar/user_avatar.vue' -import Popover from '../popover/popover.vue' +import UserListPopover from '../user_list_popover/user_list_popover.vue' const EMOJI_REACTION_COUNT_CUTOFF = 12 @@ -7,7 +7,7 @@ const EmojiReactions = { name: 'EmojiReactions', components: { UserAvatar, - Popover + UserListPopover }, props: ['status'], data: () => ({ diff --git a/src/components/emoji_reactions/emoji_reactions.vue b/src/components/emoji_reactions/emoji_reactions.vue index bac4c605..2f14b5b2 100644 --- a/src/components/emoji_reactions/emoji_reactions.vue +++ b/src/components/emoji_reactions/emoji_reactions.vue @@ -1,44 +1,11 @@ <template> <div class="emoji-reactions"> - <Popover + <UserListPopover v-for="(reaction) in emojiReactions" :key="reaction.name" - trigger="hover" - placement="top" - :offset="{ y: 5 }" + :users="accountsForEmoji[reaction.name]" > - <div - slot="content" - class="reacted-users" - > - <div v-if="accountsForEmoji[reaction.name].length"> - <div - v-for="(account) in accountsForEmoji[reaction.name]" - :key="account.id" - class="reacted-user" - > - <UserAvatar - :user="account" - class="avatar-small" - :compact="true" - /> - <div class="reacted-user-names"> - <!-- eslint-disable vue/no-v-html --> - <span - class="reacted-user-name" - v-html="account.name_html" - /> - <!-- eslint-enable vue/no-v-html --> - <span class="reacted-user-screen-name">{{ account.screen_name }}</span> - </div> - </div> - </div> - <div v-else> - <i class="icon-spin4 animate-spin" /> - </div> - </div> <button - slot="trigger" class="emoji-reaction btn btn-default" :class="{ 'picked-reaction': reactedWith(reaction.name), 'not-clickable': !loggedIn }" @click="emojiOnClick(reaction.name, $event)" @@ -47,7 +14,7 @@ <span class="reaction-emoji">{{ reaction.name }}</span> <span>{{ reaction.count }}</span> </button> - </Popover> + </UserListPopover> <a v-if="tooManyReactions" class="emoji-reaction-expand faint" @@ -69,32 +36,6 @@ flex-wrap: wrap; } -.reacted-users { - padding: 0.5em; -} - -.reacted-user { - padding: 0.25em; - display: flex; - flex-direction: row; - - .reacted-user-names { - display: flex; - flex-direction: column; - margin-left: 0.5em; - min-width: 5em; - - img { - width: 1em; - height: 1em; - } - } - - .reacted-user-screen-name { - font-size: 9px; - } -} - .emoji-reaction { padding: 0 0.5em; margin-right: 0.5em; diff --git a/src/components/status/status.js b/src/components/status/status.js index ad0b72a9..d263da68 100644 --- a/src/components/status/status.js +++ b/src/components/status/status.js @@ -9,6 +9,7 @@ import AvatarList from '../avatar_list/avatar_list.vue' import Timeago from '../timeago/timeago.vue' import StatusContent from '../status_content/status_content.vue' import StatusPopover from '../status_popover/status_popover.vue' +import UserListPopover from '../user_list_popover/user_list_popover.vue' import EmojiReactions from '../emoji_reactions/emoji_reactions.vue' import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator' import { highlightClass, highlightStyle } from '../../services/user_highlighter/user_highlighter.js' @@ -18,6 +19,21 @@ import { mapGetters, mapState } from 'vuex' const Status = { name: 'Status', + components: { + FavoriteButton, + ReactButton, + RetweetButton, + ExtraButtons, + PostStatusForm, + UserCard, + UserAvatar, + AvatarList, + Timeago, + StatusPopover, + UserListPopover, + EmojiReactions, + StatusContent + }, props: [ 'statusoid', 'expandable', @@ -197,20 +213,6 @@ const Status = { currentUser: state => state.users.currentUser }) }, - components: { - FavoriteButton, - ReactButton, - RetweetButton, - ExtraButtons, - PostStatusForm, - UserCard, - UserAvatar, - AvatarList, - Timeago, - StatusPopover, - EmojiReactions, - StatusContent - }, methods: { visibilityIcon (visibility) { switch (visibility) { diff --git a/src/components/status/status.vue b/src/components/status/status.vue index f6b5dd6f..4764f467 100644 --- a/src/components/status/status.vue +++ b/src/components/status/status.vue @@ -265,24 +265,30 @@ class="favs-repeated-users" > <div class="stats"> - <div + <UserListPopover v-if="statusFromGlobalRepository.rebloggedBy && statusFromGlobalRepository.rebloggedBy.length > 0" - class="stat-count" + :users="statusFromGlobalRepository.rebloggedBy" > - <a class="stat-title">{{ $t('status.repeats') }}</a> - <div class="stat-number"> - {{ statusFromGlobalRepository.rebloggedBy.length }} + <div class="stat-count"> + <a class="stat-title">{{ $t('status.repeats') }}</a> + <div class="stat-number"> + {{ statusFromGlobalRepository.rebloggedBy.length }} + </div> </div> - </div> - <div + </UserListPopover> + <UserListPopover v-if="statusFromGlobalRepository.favoritedBy && statusFromGlobalRepository.favoritedBy.length > 0" - class="stat-count" + :users="statusFromGlobalRepository.favoritedBy" > - <a class="stat-title">{{ $t('status.favorites') }}</a> - <div class="stat-number"> - {{ statusFromGlobalRepository.favoritedBy.length }} + <div + class="stat-count" + > + <a class="stat-title">{{ $t('status.favorites') }}</a> + <div class="stat-number"> + {{ statusFromGlobalRepository.favoritedBy.length }} + </div> </div> - </div> + </UserListPopover> <div class="avatar-row"> <AvatarList :users="combinedFavsAndRepeatsUsers" /> </div> @@ -722,6 +728,11 @@ $status-margin: 0.75em; .stat-count { margin-right: $status-margin; + user-select: none; + + &:hover .stat-title { + text-decoration: underline; + } .stat-title { color: var(--faint, $fallback--faint); diff --git a/src/components/user_list_popover/user_list_popover.js b/src/components/user_list_popover/user_list_popover.js new file mode 100644 index 00000000..26d2ed1a --- /dev/null +++ b/src/components/user_list_popover/user_list_popover.js @@ -0,0 +1,13 @@ + +const UserListPopover = { + name: 'UserListPopover', + props: [ + 'users' + ], + components: { + Popover: () => import('../popover/popover.vue'), + UserAvatar: () => import('../user_avatar/user_avatar.vue') + } +} + +export default UserListPopover diff --git a/src/components/user_list_popover/user_list_popover.vue b/src/components/user_list_popover/user_list_popover.vue new file mode 100644 index 00000000..b6b7ab95 --- /dev/null +++ b/src/components/user_list_popover/user_list_popover.vue @@ -0,0 +1,74 @@ +<template> + <Popover + trigger="hover" + placement="top" + :offset="{ y: 5 }" + > + <template slot="trigger"> + <slot /> + </template> + <div + slot="content" + class="reacted-users" + > + <div v-if="users.length"> + <div + v-for="(user) in users" + :key="user.id" + class="reacted-user" + > + <UserAvatar + :user="user" + class="avatar-small" + :compact="true" + /> + <div class="reacted-user-names"> + <!-- eslint-disable vue/no-v-html --> + <span + class="reacted-user-name" + v-html="user.name_html" + /> + <!-- eslint-enable vue/no-v-html --> + <span class="reacted-user-screen-name">{{ user.screen_name }}</span> + </div> + </div> + </div> + <div v-else> + <i class="icon-spin4 animate-spin" /> + </div> + </div> + </Popover> +</template> + +<script src="./user_list_popover.js" ></script> + +<style lang="scss"> +@import '../../_variables.scss'; + +.reacted-users { + padding: 0.5em; +} + +.reacted-user { + padding: 0.25em; + display: flex; + flex-direction: row; + + .reacted-user-names { + display: flex; + flex-direction: column; + margin-left: 0.5em; + min-width: 5em; + + img { + width: 1em; + height: 1em; + } + } + + .reacted-user-screen-name { + font-size: 9px; + } +} + +</style>