Skip to content

Commit f656a82

Browse files
committed
Comments: Styled content comments & improved interaction
1 parent 5bfba28 commit f656a82

File tree

6 files changed

+98
-15
lines changed

6 files changed

+98
-15
lines changed

lang/en/entities.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,7 @@
403403
'comment_created_success' => 'Comment added',
404404
'comment_updated_success' => 'Comment updated',
405405
'comment_view' => 'View comment',
406+
'comment_jump_to_thread' => 'Jump to thread',
406407
'comment_delete_confirm' => 'Are you sure you want to delete this comment?',
407408
'comment_in_reply_to' => 'In reply to :commentId',
408409
'comment_editor_explain' => 'Here are the comments that have been left on this page. Comments can be added & managed when viewing the saved page.',

resources/js/components/page-comment.ts

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@ import {buildForInput} from '../wysiwyg-tinymce/config';
44
import {el} from "../wysiwyg/utils/dom";
55

66
import commentIcon from "@icons/comment.svg"
7+
import closeIcon from "@icons/close.svg"
8+
9+
/**
10+
* Track the close function for the current open marker so it can be closed
11+
* when another is opened so we only show one marker comment thread at one time.
12+
*/
13+
let openMarkerClose: Function|null = null;
714

815
export class PageComment extends Component {
916

@@ -13,6 +20,8 @@ export class PageComment extends Component {
1320
protected deletedText: string;
1421
protected updatedText: string;
1522
protected viewCommentText: string;
23+
protected jumpToThreadText: string;
24+
protected closeText: string;
1625

1726
protected wysiwygEditor: any = null;
1827
protected wysiwygLanguage: string;
@@ -35,6 +44,8 @@ export class PageComment extends Component {
3544
this.deletedText = this.$opts.deletedText;
3645
this.updatedText = this.$opts.updatedText;
3746
this.viewCommentText = this.$opts.viewCommentText;
47+
this.jumpToThreadText = this.$opts.jumpToThreadText;
48+
this.closeText = this.$opts.closeText;
3849

3950
// Editor reference and text options
4051
this.wysiwygLanguage = this.$opts.wysiwygLanguage;
@@ -130,7 +141,7 @@ export class PageComment extends Component {
130141

131142
await window.$http.delete(`/comment/${this.commentId}`);
132143
this.$emit('delete');
133-
this.container.closest('.comment-branch').remove();
144+
this.container.closest('.comment-branch')?.remove();
134145
window.$events.success(this.deletedText);
135146
}
136147

@@ -196,16 +207,22 @@ export class PageComment extends Component {
196207
}
197208

198209
protected showCommentAtMarker(marker: HTMLElement): void {
199-
210+
// Hide marker and close existing marker windows
211+
if (openMarkerClose) {
212+
openMarkerClose();
213+
}
200214
marker.hidden = true;
201-
const readClone = this.container.closest('.comment-branch').cloneNode(true) as HTMLElement;
215+
216+
// Build comment window
217+
const readClone = (this.container.closest('.comment-branch') as HTMLElement).cloneNode(true) as HTMLElement;
202218
const toRemove = readClone.querySelectorAll('.actions, form');
203219
for (const el of toRemove) {
204220
el.remove();
205221
}
206222

207-
const close = el('button', {type: 'button'}, ['x']);
208-
const jump = el('button', {type: 'button'}, ['Jump to thread']);
223+
const close = el('button', {type: 'button', title: this.closeText});
224+
close.innerHTML = (closeIcon as string);
225+
const jump = el('button', {type: 'button', 'data-action': 'jump'}, [this.jumpToThreadText]);
209226

210227
const commentWindow = el('div', {
211228
class: 'content-comment-window'
@@ -214,19 +231,29 @@ export class PageComment extends Component {
214231
class: 'content-comment-window-actions',
215232
}, [jump, close]),
216233
el('div', {
217-
class: 'content-comment-window-content',
234+
class: 'content-comment-window-content comment-container-compact comment-container-super-compact',
218235
}, [readClone]),
219236
]);
220237

221-
marker.parentElement.append(commentWindow);
238+
marker.parentElement?.append(commentWindow);
222239

240+
// Handle interaction within window
223241
const closeAction = () => {
224242
commentWindow.remove();
225243
marker.hidden = false;
244+
window.removeEventListener('click', windowCloseAction);
245+
openMarkerClose = null;
226246
};
227247

228-
close.addEventListener('click', closeAction.bind(this));
248+
const windowCloseAction = (event: MouseEvent) => {
249+
if (!(marker.parentElement as HTMLElement).contains(event.target as HTMLElement)) {
250+
closeAction();
251+
}
252+
};
253+
window.addEventListener('click', windowCloseAction);
229254

255+
openMarkerClose = closeAction;
256+
close.addEventListener('click', closeAction.bind(this));
230257
jump.addEventListener('click', () => {
231258
closeAction();
232259
this.container.scrollIntoView({behavior: 'smooth'});
@@ -235,7 +262,12 @@ export class PageComment extends Component {
235262
highlightTarget.addEventListener('animationend', () => highlightTarget.classList.remove('anim-highlight'))
236263
});
237264

238-
// TODO - Position wrapper sensibly
239-
// TODO - Movement control?
265+
// Position window within bounds
266+
const commentWindowBounds = commentWindow.getBoundingClientRect();
267+
const contentBounds = document.querySelector('.page-content')?.getBoundingClientRect();
268+
if (contentBounds && commentWindowBounds.right > contentBounds.right) {
269+
const diff = commentWindowBounds.right - contentBounds.right;
270+
commentWindow.style.left = `-${diff}px`;
271+
}
240272
}
241273
}

resources/sass/_components.scss

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -746,6 +746,10 @@ body.flexbox-support #entity-selector-wrap .popup-body .form-group {
746746
height: calc(100% - vars.$m);
747747
}
748748

749+
.comment-branch .comment-box {
750+
margin-bottom: vars.$m;
751+
}
752+
749753
.comment-branch .comment-branch .comment-branch .comment-branch .comment-thread-indicator {
750754
display: none;
751755
}
@@ -761,6 +765,7 @@ body.flexbox-support #entity-selector-wrap .popup-body .form-group {
761765
}
762766

763767
.comment-container-compact .comment-box {
768+
margin-bottom: vars.$xs;
764769
.meta {
765770
font-size: 0.8rem;
766771
}
@@ -778,6 +783,28 @@ body.flexbox-support #entity-selector-wrap .popup-body .form-group {
778783
width: vars.$m;
779784
}
780785

786+
.comment-container-super-compact .comment-box {
787+
.meta {
788+
font-size: 12px;
789+
}
790+
.avatar {
791+
width: 18px;
792+
margin-inline-end: 2px !important;
793+
}
794+
.content {
795+
padding: vars.$xxs vars.$s;
796+
line-height: 1.2;
797+
}
798+
.content p {
799+
font-size: 12px;
800+
}
801+
}
802+
803+
.comment-container-super-compact .comment-thread-indicator {
804+
width: (vars.$xs + 3px);
805+
margin-inline-start: 3px;
806+
}
807+
781808
#tag-manager .drag-card {
782809
max-width: 500px;
783810
}

resources/sass/_pages.scss

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -242,12 +242,13 @@ body.tox-fullscreen, body.markdown-fullscreen {
242242
.content-comment-window {
243243
font-size: vars.$fs-m;
244244
line-height: 1.4;
245-
position: relative;
246-
z-index: 90;
245+
position: absolute;
246+
top: calc(100% + 3px);
247+
left: 0;
248+
z-index: 92;
247249
pointer-events: all;
248250
min-width: min(340px, 80vw);
249251
background-color: #FFF;
250-
//border: 1px solid var(--color-primary);
251252
box-shadow: vars.$bs-hover;
252253
border-radius: 4px;
253254
overflow: hidden;
@@ -258,9 +259,24 @@ body.tox-fullscreen, body.markdown-fullscreen {
258259
display: flex;
259260
align-items: center;
260261
justify-content: end;
262+
gap: vars.$xs;
263+
button {
264+
color: #FFF;
265+
font-size: 12px;
266+
padding: vars.$xs;
267+
line-height: 1;
268+
cursor: pointer;
269+
}
270+
button[data-action="jump"] {
271+
text-decoration: underline;
272+
}
273+
svg {
274+
fill: currentColor;
275+
width: 12px;
276+
}
261277
}
262278
.content-comment-window-content {
263-
padding: vars.$xs;
279+
padding: vars.$xs vars.$s vars.$xs vars.$xs;
264280
max-height: 200px;
265281
overflow-y: scroll;
266282
}
@@ -280,11 +296,16 @@ body.tox-fullscreen, body.markdown-fullscreen {
280296
color: #FFF;
281297
cursor: pointer;
282298
z-index: 90;
299+
transform: scale(1);
300+
transition: transform ease-in-out 120ms;
283301
svg {
284302
fill: #FFF;
285303
width: 80%;
286304
}
287305
}
306+
.page-content [id^="bkmrk-"]:hover .content-comment-marker {
307+
transform: scale(1.15);
308+
}
288309

289310
// Page editor sidebar toolbox
290311
.floating-toolbox {

resources/views/comments/comment-branch.blade.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<div class="comment-branch">
2-
<div class="mb-m">
2+
<div>
33
@include('comments.comment', ['comment' => $branch['comment']])
44
</div>
55
<div class="flex-container-row">

resources/views/comments/comment.blade.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
option:page-comment:updated-text="{{ trans('entities.comment_updated_success') }}"
99
option:page-comment:deleted-text="{{ trans('entities.comment_deleted_success') }}"
1010
option:page-comment:view-comment-text="{{ trans('entities.comment_view') }}"
11+
option:page-comment:jump-to-thread-text="{{ trans('entities.comment_jump_to_thread') }}"
12+
option:page-comment:close-text="{{ trans('common.close') }}"
1113
option:page-comment:wysiwyg-language="{{ $locale->htmlLang() }}"
1214
option:page-comment:wysiwyg-text-direction="{{ $locale->htmlDirection() }}"
1315
id="comment{{$comment->local_id}}"

0 commit comments

Comments
 (0)