From 52a7097c039c2c4ea238040a0e7e8398a1ca9ffd Mon Sep 17 00:00:00 2001 From: Carlos Santos Date: Fri, 5 Apr 2024 16:53:11 -0300 Subject: [PATCH] fix: comment ellipsis and close/open in large texts --- .../comments/components/annotation-item.ts | 2 +- .../comments/components/comment-item.test.ts | 41 +++++---- .../comments/components/comment-item.ts | 84 ++++++++++++------- 3 files changed, 82 insertions(+), 45 deletions(-) diff --git a/src/web-components/comments/components/annotation-item.ts b/src/web-components/comments/components/annotation-item.ts index f758e21d..a1ac6a1f 100644 --- a/src/web-components/comments/components/annotation-item.ts +++ b/src/web-components/comments/components/annotation-item.ts @@ -131,7 +131,7 @@ export class CommentsAnnotationItem extends WebComponentsBaseElement { } } - private selectAnnotation = () => { + private selectAnnotation = (event: PointerEvent): void => { const { uuid } = this.annotation; document.body.dispatchEvent(new CustomEvent('select-annotation', { detail: { uuid } })); }; diff --git a/src/web-components/comments/components/comment-item.test.ts b/src/web-components/comments/components/comment-item.test.ts index 6edd0c37..7562063a 100644 --- a/src/web-components/comments/components/comment-item.test.ts +++ b/src/web-components/comments/components/comment-item.test.ts @@ -35,9 +35,9 @@ const createElement = async (options = DEFAULT_ELEMENT_OPTIONS) => { }; describe('CommentsCommentItem', () => { - afterEach(() => { - document.body.removeChild(element); - }); + // afterEach(() => { + // document.body.removeChild(element); + // }); test('renders the comment item with correct properties', async () => { element = await createElement(); @@ -50,11 +50,11 @@ describe('CommentsCommentItem', () => { const createdAt = element.shadowRoot!.querySelector( '.comments__comment-item__date', ) as HTMLSpanElement; - expect(createdAt.textContent).toEqual(DateTime.now().toFormat('yyyy-dd-MM')); + expect(createdAt.innerText).toEqual(DateTime.now().toFormat('yyyy-dd-MM')); const text = element.shadowRoot!.querySelector( '.comments__comment-item__content', - ) as HTMLSpanElement; + ) as HTMLParagraphElement; expect(text.innerText).toEqual('This is a comment'); }); @@ -209,7 +209,7 @@ describe('CommentsCommentItem', () => { expect(element.dispatchEvent).toHaveBeenCalledWith(new CustomEvent('delete-annotation')); }); - test('when click in text should expand elipis when text is bigger than 120', async () => { + test('when text is bigger than 120 and annotation is not selected should add line-clamp class to text', async () => { element = await createElement({ ...DEFAULT_ELEMENT_OPTIONS, text: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec auctor, nisl eget aliquam lacinia, nisl nisl aliquet nisl, eget aliquam nisl nisl eget.', @@ -217,27 +217,36 @@ describe('CommentsCommentItem', () => { await element['updateComplete']; - const text = element.shadowRoot!.querySelector('.annotation-content') as HTMLElement; - text.click(); - - await element['updateComplete']; + const paragraph = element.shadowRoot!.getElementById('comment-text') as HTMLParagraphElement; - expect(element['expandElipsis']).toBeTruthy(); + expect(paragraph.classList.contains('line-clamp')).toBeTruthy(); }); - test('when click in text should not expand elipis when text is smaller than 120', async () => { + test('when text is bigger than 120 and annotation is selected should not have line-clamp to text', async () => { element = await createElement({ ...DEFAULT_ELEMENT_OPTIONS, - text: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', + text: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec auctor, nisl eget aliquam lacinia, nisl nisl aliquet nisl, eget aliquam nisl nisl eget.', }); await element['updateComplete']; - const text = element.shadowRoot!.querySelector('.annotation-content') as HTMLElement; - text.click(); + const paragraph = element.shadowRoot!.getElementById('comment-text') as HTMLParagraphElement; + paragraph.click(); + + element['isSelected'] = true; + await element['updateComplete']; + + expect(paragraph.classList.contains('line-clamp')).toBeFalsy(); + }); + + test('should not add line-clamp class when text is smaller than 120', async () => { + element = await createElement({ + ...DEFAULT_ELEMENT_OPTIONS, + text: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', + }); await element['updateComplete']; - expect(element['expandElipsis']).toBeFalsy(); + expect(element['line-clamp']).toBeFalsy(); }); }); diff --git a/src/web-components/comments/components/comment-item.ts b/src/web-components/comments/components/comment-item.ts index c4cf2771..1da6250d 100644 --- a/src/web-components/comments/components/comment-item.ts +++ b/src/web-components/comments/components/comment-item.ts @@ -32,7 +32,7 @@ export class CommentsCommentItem extends WebComponentsBaseElement { declare mode: CommentMode; declare deleteCommentModalOpen: boolean; declare primaryComment: boolean; - declare expandElipsis: boolean; + declare isSelected: boolean; declare annotationFilter: string; declare participantsList: ParticipantByGroupApi[]; declare mentions: ParticipantByGroupApi[]; @@ -51,7 +51,7 @@ export class CommentsCommentItem extends WebComponentsBaseElement { mode: { type: String }, deleteCommentModalOpen: { type: Boolean }, primaryComment: { type: Boolean }, - expandElipsis: { type: Boolean }, + isSelected: { type: Boolean }, annotationFilter: { type: String }, participantsList: { type: Object }, mentions: { type: Array }, @@ -65,8 +65,47 @@ export class CommentsCommentItem extends WebComponentsBaseElement { this.updateComplete.then(() => { importStyle.call(this, ['comments']); }); + + document.body.addEventListener('select-annotation', this.selectAnnotation); + } + + connectedCallback(): void { + super.connectedCallback(); + + window.document.body.addEventListener('select-annotation', this.selectAnnotation); + window.document.body.addEventListener('keyup', this.unselectAnnotationEsc); + window.document.body.addEventListener('unselect-annotation', this.unselectAnnotation); + } + + disconnectedCallback(): void { + super.disconnectedCallback(); + + window.document.body.removeEventListener('select-annotation', this.selectAnnotation); + window.document.body.removeEventListener('keyup', this.unselectAnnotationEsc); + window.document.body.removeEventListener('unselect-annotation', this.unselectAnnotation); } + private unselectAnnotationEsc = (event: KeyboardEvent) => { + if (event.key === 'Escape') { + this.isSelected = false; + } + }; + + private unselectAnnotation = () => { + this.isSelected = false; + }; + + private selectAnnotation = ({ detail }: CustomEvent) => { + const { uuid } = detail; + + if (this.isSelected) { + this.isSelected = false; + return; + } + + this.isSelected = uuid === this.annotationId; + }; + private updateComment = ({ detail }: CustomEvent) => { const { text, mentions } = detail; this.text = text; @@ -159,12 +198,6 @@ export class CommentsCommentItem extends WebComponentsBaseElement { } }; - const expandElipsis = () => { - if (this.text.length < 120) return; - - this.expandElipsis = true; - }; - const textareaHtml = () => { const classes = { 'comments__comment-item--editable': true, @@ -189,20 +222,16 @@ export class CommentsCommentItem extends WebComponentsBaseElement { const commentText = () => { const textClasses = { - editing: this.mode === CommentMode.EDITABLE, - 'annotation-content': true, text: true, 'text-big': true, 'sv-gray-700': true, + 'annotation-content': true, [this.getClasses('content')]: true, - 'line-clamp': !this.expandElipsis && this.text.length > 120, + editing: this.mode === CommentMode.EDITABLE, + 'line-clamp': !this.isSelected && this.text.length > 120, }; - return html` - ${this.text} - `; + return html`

${this.text}

`; }; const closeModal = () => { @@ -225,12 +254,12 @@ export class CommentsCommentItem extends WebComponentsBaseElement {
${this.getAvatar()} - ${this.username} - ${humanizeDate(this.createdAt)} + + ${this.username} + + + ${humanizeDate(this.createdAt)} +
event.stopPropagation()} + @click=${(event: Event) => { + event.stopPropagation(); + }} classesPrefix="comments__dropdown" parentComponent="comments" >