Improve and fix bugs surrounding reactions (#24760)

- Slightly decrease size of reaction buttons
- Remove tooltip inside menu, it's obvious by the picture alone
- Fix top menu triangle
- Use `display: grid` to align icons in menu
- Use regular tooltip for reaction users
- Fix bug that deleted the reaction bar on clicking already reacted
reaction in dropdown

<img width="490" alt="Screenshot 2023-05-17 at 00 03 42"
src="61588b37-facb-4829-b75b-e1cb5dda8ca4">

<img width="67" alt="Screenshot 2023-05-17 at 00 11 14"
src="29605589-3b5f-40c6-8ad4-09923094bb8e">

<img width="211" alt="Screenshot 2023-05-17 at 00 29 30"
src="7d2725da-6a3d-4e42-a351-53647f79f762">
<img width="210" alt="Screenshot 2023-05-17 at 00 29 54"
src="b50f8364-033c-4445-ba25-61a814bb2d92">


<img width="892" alt="Screenshot 2023-05-17 at 00 12 20"
src="30a46424-406a-46e5-b4de-47172eb8679d">

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: Giteabot <teabot@gitea.io>
This commit is contained in:
silverwind 2023-05-28 03:34:18 +02:00 committed by GitHub
parent 2f149c5c9d
commit 595e8abd68
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 117 additions and 113 deletions

View file

@ -1,53 +1,46 @@
import $ from 'jquery';
import {createTippy} from '../../modules/tippy.js';
const {csrfToken} = window.config;
export function initCompReactionSelector(parent) {
let selector = 'a.label';
if (!parent) {
parent = $(document);
selector = `.reactions ${selector}`;
}
for (const el of parent[0].querySelectorAll(selector)) {
createTippy(el, {placement: 'bottom-start', content: el.getAttribute('data-title')});
}
parent.find(`.select-reaction > .menu > .item, ${selector}`).on('click', function (e) {
export function initCompReactionSelector($parent) {
$parent.find(`.select-reaction .item.reaction, .comment-reaction-button`).on('click', async function (e) {
e.preventDefault();
if ($(this).hasClass('disabled')) return;
const actionURL = $(this).hasClass('item') ? $(this).closest('.select-reaction').data('action-url') : $(this).data('action-url');
const url = `${actionURL}/${$(this).hasClass('primary') ? 'unreact' : 'react'}`;
$.ajax({
type: 'POST',
url,
data: {
const actionUrl = $(this).closest('[data-action-url]').attr('data-action-url');
const reactionContent = $(this).attr('data-reaction-content');
const hasReacted = $(this).closest('.ui.segment.reactions').find(`a[data-reaction-content="${reactionContent}"]`).attr('data-has-reacted') === 'true';
const res = await fetch(`${actionUrl}/${hasReacted ? 'unreact' : 'react'}`, {
method: 'POST',
headers: {
'content-type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
_csrf: csrfToken,
content: $(this).attr('data-reaction-content'),
}
}).done((resp) => {
if (resp && (resp.html || resp.empty)) {
const content = $(this).closest('.content');
let react = content.find('.segment.reactions');
if ((!resp.empty || resp.html === '') && react.length > 0) {
react.remove();
}
if (!resp.empty) {
react = $('<div class="ui attached segment reactions"></div>');
const attachments = content.find('.segment.bottom:first');
if (attachments.length > 0) {
react.insertBefore(attachments);
} else {
react.appendTo(content);
}
react.html(resp.html);
react.find('.dropdown').dropdown();
initCompReactionSelector(react);
}
}
content: reactionContent,
}),
});
const data = await res.json();
if (data && (data.html || data.empty)) {
const content = $(this).closest('.content');
let react = content.find('.segment.reactions');
if ((!data.empty || data.html === '') && react.length > 0) {
react.remove();
}
if (!data.empty) {
const attachments = content.find('.segment.bottom:first');
react = $(data.html);
if (attachments.length > 0) {
react.insertBefore(attachments);
} else {
react.appendTo(content);
}
react.find('.dropdown').dropdown();
initCompReactionSelector(react);
}
}
});
}

View file

@ -190,8 +190,6 @@ export function initRepoCodeView() {
currentTarget.closest('tr').outerHTML = blob;
});
$(document).on('click', '.copy-line-permalink', async (e) => {
const success = await clippie(toAbsoluteUrl(e.currentTarget.getAttribute('data-url')));
if (!success) return;
document.querySelector('.code-line-button')?._tippy?.hide();
await clippie(toAbsoluteUrl(e.currentTarget.getAttribute('data-url')));
});
}

View file

@ -76,7 +76,7 @@ function showContentHistoryMenu(issueBaseUrl, $item, commentId) {
const $headerLeft = $item.find('.comment-header-left');
const menuHtml = `
<div class="ui pointing dropdown top left content-history-menu" data-comment-id="${commentId}">
&bull; <a>${i18nTextEdited}${svg('octicon-triangle-down', 14, 'dropdown icon gt-ml-1 gt-mt-1')}</a>
&bull; <a class="muted">${i18nTextEdited}${svg('octicon-triangle-down', 14, 'dropdown icon gt-ml-1 gt-mt-1')}</a>
<div class="menu">
</div>
</div>`;

View file

@ -544,7 +544,7 @@ export function initRepository() {
initRepoIssueDependencyDelete();
initRepoIssueCodeCommentCancel();
initRepoPullRequestUpdate();
initCompReactionSelector();
initCompReactionSelector($(document));
initRepoPullRequestMergeForm();
}

View file

@ -58,10 +58,17 @@ function attachTooltip(target, content = null) {
content = content ?? target.getAttribute('data-tooltip-content');
if (!content) return null;
// when element has a clipboard target, we update the tooltip after copy
// in which case it is undesirable to automatically hide it on click as
// it would momentarily flash the tooltip out and in.
const hasClipboardTarget = target.hasAttribute('data-clipboard-target');
const hideOnClick = !hasClipboardTarget;
const props = {
content,
delay: 100,
role: 'tooltip',
hideOnClick,
placement: target.getAttribute('data-tooltip-placement') || 'top-start',
...(target.getAttribute('data-tooltip-interactive') === 'true' ? {interactive: true, aria: {content: 'describedby', expanded: false}} : {}),
};