From 91d2b5ed814e34a0b8db80659b97b6a4e78a92ed Mon Sep 17 00:00:00 2001 From: Daniil Fadeev Date: Fri, 15 Sep 2023 13:59:38 +0400 Subject: [PATCH] user_group_popover: Migrate popover to Tippy. Fixes part of #23632. --- web/src/user_group_popover.js | 110 +++++++++--------- web/styles/popovers.css | 18 ++- web/templates/user_group_info_popover.hbs | 33 +++++- .../user_group_info_popover_content.hbs | 31 ----- 4 files changed, 104 insertions(+), 88 deletions(-) delete mode 100644 web/templates/user_group_info_popover_content.hbs diff --git a/web/src/user_group_popover.js b/web/src/user_group_popover.js index d8c98125ba..405d3d19d6 100644 --- a/web/src/user_group_popover.js +++ b/web/src/user_group_popover.js @@ -1,44 +1,46 @@ import $ from "jquery"; import render_user_group_info_popover from "../templates/user_group_info_popover.hbs"; -import render_user_group_info_popover_content from "../templates/user_group_info_popover_content.hbs"; import * as blueslip from "./blueslip"; import * as buddy_data from "./buddy_data"; +import {media_breakpoints_num} from "./css_variables"; import * as message_lists from "./message_lists"; -import * as message_viewport from "./message_viewport"; import * as people from "./people"; -import {hide_all, popover_items_handle_keyboard} from "./popovers"; +import * as popover_menus from "./popover_menus"; +import * as popovers from "./popovers"; +import {popover_items_handle_keyboard} from "./popovers"; import * as rows from "./rows"; +import * as ui_util from "./ui_util"; import * as user_groups from "./user_groups"; import * as util from "./util"; -let $current_user_group_popover_elem; +let user_group_popover_instance; export function hide() { if (is_open()) { - $current_user_group_popover_elem.popover("destroy"); - $current_user_group_popover_elem = undefined; + user_group_popover_instance.destroy(); + user_group_popover_instance = undefined; } } export function is_open() { - return $current_user_group_popover_elem !== undefined; + return Boolean(user_group_popover_instance); } function get_user_group_popover_items() { - if (!$current_user_group_popover_elem) { + if (!is_open()) { blueslip.error("Trying to get menu items when user group popover is closed."); return undefined; } - const popover_data = $current_user_group_popover_elem.data("popover"); - if (!popover_data) { + const $popover = $(user_group_popover_instance.popper); + if (!$popover) { blueslip.error("Cannot find user group popover data"); return undefined; } - return $("li:not(.divider):visible a", popover_data.$tip); + return $("li:not(.divider):visible a", $popover); } export function handle_keyboard(key) { @@ -49,40 +51,58 @@ export function handle_keyboard(key) { // element is the target element to pop off of; // message_id is the message id containing it, which should be selected; export function toggle_user_group_info_popover(element, message_id) { - const $last_popover_elem = $current_user_group_popover_elem; - hide_all(); - if ($last_popover_elem !== undefined && $last_popover_elem.get()[0] === element) { - // We want it to be the case that a user can dismiss a popover - // by clicking on the same element that caused the popover. + if (is_open()) { + hide(); return; } - - // hardcoded pixel height of the popover - // note that the actual size varies (in group size), but this is about as big as it gets - const popover_size = 390; const $elt = $(element); const user_group_id = Number.parseInt($elt.attr("data-user-group-id"), 10); const group = user_groups.get_user_group_from_id(user_group_id); - message_lists.current.select_id(message_id); + let show_as_overlay = false; - if ($elt.data("popover") === undefined) { - const args = { - group_name: group.name, - group_description: group.description, - members: sort_group_members(fetch_group_members([...group.members])), - }; - $elt.popover({ - placement: calculate_info_popover_placement(popover_size, $elt), - template: render_user_group_info_popover(), - content: render_user_group_info_popover_content(args), - html: true, - trigger: "manual", - fixed: true, - }); - $elt.popover("show"); - $current_user_group_popover_elem = $elt; + // If the window is mobile-sized, we will render the + // user group popover centered on the screen with the overlay. + if (window.innerWidth <= media_breakpoints_num.md) { + show_as_overlay = true; } + + popover_menus.toggle_popover_menu( + element, + { + placement: "right", + arrow: false, + popperOptions: { + modifiers: [ + { + name: "flip", + options: { + fallbackPlacements: ["left", "top", "bottom"], + }, + }, + ], + }, + onCreate(instance) { + popovers.hide_all_except_sidebars(); + if (message_id) { + message_lists.current.select_id(message_id); + } + user_group_popover_instance = instance; + const $popover = $(instance.popper); + $popover.addClass("user-group-popover-root"); + const args = { + group_name: group.name, + group_description: group.description, + members: sort_group_members(fetch_group_members([...group.members])), + }; + instance.setContent(ui_util.parse_html(render_user_group_info_popover(args))); + }, + onHidden() { + hide(); + }, + }, + {show_as_overlay}, + ); } export function register_click_handlers() { @@ -118,27 +138,11 @@ function sort_group_members(members) { return members.sort((a, b) => util.strcmp(a.full_name, b.fullname)); } -function calculate_info_popover_placement(size, $elt) { - const ypos = $elt.get_offset_to_window().top; - - if (!(ypos + size / 2 < message_viewport.height() && ypos > size / 2)) { - if (ypos + size < message_viewport.height()) { - return "bottom"; - } else if (ypos > size) { - return "top"; - } - } - - return undefined; -} - // exporting these functions for testing purposes export const _test_fetch_group_members = fetch_group_members; export const _test_sort_group_members = sort_group_members; -export const _test_calculate_info_popover_placement = calculate_info_popover_placement; - export function initialize() { register_click_handlers(); } diff --git a/web/styles/popovers.css b/web/styles/popovers.css index dd0352b5d6..1cf89b9cd1 100644 --- a/web/styles/popovers.css +++ b/web/styles/popovers.css @@ -303,6 +303,7 @@ ul { } } +.group-info-popover, .message-user-card-popover, .user-card-popover { width: 240px; @@ -669,7 +670,6 @@ ul { } @media (width < $md_min) { - .message-user-card-popover, .user-card-popover { display: flex !important; justify-content: center; @@ -787,7 +787,8 @@ ul { } .giphy-popover, -.emoji-popover-root { +.emoji-popover-root, +.user-group-popover-root { .tippy-content { /* We remove the default padding from this container as it is not necessary for the Giphy popover. */ @@ -799,6 +800,19 @@ ul { } } +.user-group-popover-root { + & .popover-content ul.nav { + /* TODO: Clean this logic up after drop Bootstrap styling */ + margin: 0; + } + + & .tippy-box { + box-shadow: 0 5px 10px hsl(0deg 0% 0% / 20%); + /* User group popover has a bigger border-radius than our usual popovers. */ + border-radius: 6px; + } +} + .emoji-popover-root { /* The emoji popover has a different background color for the header and footer, so we customize the arrow to match this color. */ diff --git a/web/templates/user_group_info_popover.hbs b/web/templates/user_group_info_popover.hbs index 47b291e86f..1e224423fd 100644 --- a/web/templates/user_group_info_popover.hbs +++ b/web/templates/user_group_info_popover.hbs @@ -1,7 +1,36 @@ -
+
-
+
+
{{group_name}}
+
+ {{group_description}} +
+
+
+ +
+
diff --git a/web/templates/user_group_info_popover_content.hbs b/web/templates/user_group_info_popover_content.hbs deleted file mode 100644 index b2cdc75c6e..0000000000 --- a/web/templates/user_group_info_popover_content.hbs +++ /dev/null @@ -1,31 +0,0 @@ -{{! Contents of the "user group info" popup }} -
-
{{group_name}}
-
- {{group_description}} -
-
-
- -
-