feat: closes #13484, post preview changes

don't close preview when mouse leaves the anchor
close preview on click outside
close preview when mouseleaves preview
open the preview to the top if there isn't enough space
add scrollbar to post preview
This commit is contained in:
Barış Soner Uşaklı
2025-06-10 10:47:14 -04:00
parent 0c9297f81c
commit 14e30c4bf8
2 changed files with 34 additions and 9 deletions

View File

@@ -312,12 +312,27 @@ define('forum/topic', [
const postCache = {};
function destroyTooltip() {
clearTimeout(timeoutId);
timeoutId = 0;
$('#post-tooltip').remove();
destroyed = true;
}
function onClickOutside(ev) {
// If the click is outside the tooltip, destroy it
if (!$(ev.target).closest('#post-tooltip').length) {
destroyTooltip();
}
}
$(window).one('action:ajaxify.start', destroyTooltip);
$('[component="topic"]').on('mouseenter', 'a[component="post/parent"], [component="post/content"] a, [component="topic/event"] a', async function () {
$('[component="topic"]').on('mouseenter', 'a[component="post/parent"], [component="post/parent/content"] a,[component="post/content"] a, [component="topic/event"] a', async function () {
const link = $(this);
link.one('mouseleave', function() {
if (timeoutId > 0) {
clearTimeout(timeoutId);
timeoutId = 0;
}
});
destroyed = false;
async function renderPost(pid) {
@@ -335,8 +350,13 @@ define('forum/topic', [
const postRect = postContent.offset();
const postWidth = postContent.width();
const linkRect = link.offset();
const { top } = link.get(0).getBoundingClientRect();
const dropup = top > window.innerHeight / 2;
tooltip.one('mouseleave', destroyTooltip);
$(window).off('click', onClickOutside).one('click', onClickOutside);
tooltip.css({
top: linkRect.top + 30,
top: dropup ? linkRect.top - tooltip.outerHeight() : linkRect.top + 30,
left: postRect.left,
width: postWidth,
});
@@ -357,16 +377,18 @@ define('forum/topic', [
}
timeoutId = setTimeout(async () => {
timeoutId = 0;
renderPost(pid);
}, 300);
} else if (topicMatch) {
timeoutId = setTimeout(async () => {
timeoutId = 0;
const tid = topicMatch[1];
const topicData = await api.get('/topics/' + tid, {});
renderPost(topicData.mainPid);
}, 300);
}
}).on('mouseleave', '[component="post"] a, [component="topic/event"] a', destroyTooltip);
});
}
function setupQuickReply() {

View File

@@ -1,11 +1,14 @@
<div id="post-tooltip" class="card card-body shadow bg-body text-body z-1 position-absolute">
<div class="d-flex flex-column gap-2">
<div class="d-flex gap-1 align-items-center">
<a href="{{{ if post.user.userslug }}}{config.relative_path}/user/{post.user.userslug}{{{ else }}}#{{{ end }}}">
{buildAvatar(post.user, "24px", true, "", "user/picture")} {post.user.username}
</a>
<span class="timeago text-xs" title="{post.timestampISO}"></span>
<div class="d-flex gap-2 align-items-center">
<div>
<a href="{{{ if post.user.userslug }}}{config.relative_path}/user/{post.user.userslug}{{{ else }}}#{{{ end }}}">{buildAvatar(post.user, "20px", true, "", "user/picture")}</a>
<a href="{{{ if post.user.userslug }}}{config.relative_path}/user/{post.user.userslug}{{{ else }}}#{{{ end }}}">{post.user.username}</a>
</div>
<div>
<span class="timeago text-xs text-secondary lh-1" style="vertical-align: middle;" title="{post.timestampISO}"></span>
</div>
</div>
<div class="content">{post.content}</div>
<div class="content ghost-scrollbar" style="max-height: 300px; overflow-y:auto;">{post.content}</div>
</div>
</div>