From 58b712a1de034fa59408a1ab7e74538c4a6eafdb Mon Sep 17 00:00:00 2001 From: Anthony LC Date: Sat, 8 Feb 2025 23:24:31 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B(frontend)=20fix=20cursor=20breakli?= =?UTF-8?q?ne?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We had breakline issues with the initial cursor because of some css properties. We changed the cursor css to not take any space in the lines, avoiding the breakline issues. We keep the new cursor visibility feature (always, activity). --- .../doc-editor/components/BlockNoteEditor.tsx | 78 +++++++++++++++---- 1 file changed, 65 insertions(+), 13 deletions(-) diff --git a/src/frontend/apps/impress/src/features/docs/doc-editor/components/BlockNoteEditor.tsx b/src/frontend/apps/impress/src/features/docs/doc-editor/components/BlockNoteEditor.tsx index 976aa680..af4694c7 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-editor/components/BlockNoteEditor.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-editor/components/BlockNoteEditor.tsx @@ -27,6 +27,41 @@ const cssEditor = (readonly: boolean) => css` & .ProseMirror { height: 100%; + .collaboration-cursor-custom__base { + position: relative; + } + .collaboration-cursor-custom__caret { + position: absolute; + height: 85%; + width: 2px; + bottom: 4%; + left: -1px; + } + + .collaboration-cursor-custom__label { + color: #0d0d0d; + font-size: 12px; + font-weight: 600; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + position: absolute; + top: -17px; + padding: 0px 6px; + border-radius: 0px; + white-space: nowrap; + transition: clip-path 0.3s ease-in-out; + border-radius: 4px 4px 4px 0; + box-shadow: inset -2px 2px 6px #ffffff88; + clip-path: polygon(0 100%, 0 100%, 0 100%, 0% 100%); + } + + .collaboration-cursor-custom__base[data-active] + .collaboration-cursor-custom__label { + pointer-events: none; + clip-path: polygon(0 0, 100% 0%, 100% 100%, 0% 100%); + } + .bn-side-menu[data-block-type='heading'][data-level='1'] { height: 50px; } @@ -127,6 +162,7 @@ export const BlockNoteEditor = ({ doc, provider }: BlockNoteEditorProps) => { const collabName = readOnly ? 'Reader' : user?.full_name || user?.email || t('Anonymous'); + const showCursorLabels: 'always' | 'activity' | (string & {}) = 'activity'; const editor = useCreateBlockNote( { @@ -138,30 +174,46 @@ export const BlockNoteEditor = ({ doc, provider }: BlockNoteEditorProps) => { color: randomColor(), }, /** - * We re-use the blocknote code to render the cursor but we: - * - fix rendering issue with Firefox - * - We don't want to show the cursor when anonymous users + * We render the cursor with a custom element to: + * - fix rendering issue with the default cursor + * - hide the cursor when anonymous users */ renderCursor: (user: { color: string; name: string }) => { - const cursor = document.createElement('span'); + const cursorElement = document.createElement('span'); if (user.name === 'Reader') { - return cursor; + return cursorElement; } - cursor.classList.add('collaboration-cursor__caret'); - cursor.setAttribute('style', `border-color: ${user.color}`); + cursorElement.classList.add('collaboration-cursor-custom__base'); + const caretElement = document.createElement('span'); + caretElement.classList.add('collaboration-cursor-custom__caret'); + caretElement.setAttribute('spellcheck', `false`); + caretElement.setAttribute('style', `background-color: ${user.color}`); - const label = document.createElement('span'); + if (showCursorLabels === 'always') { + cursorElement.setAttribute('data-active', ''); + } - label.classList.add('collaboration-cursor__label'); - label.setAttribute('style', `background-color: ${user.color}`); - label.insertBefore(document.createTextNode(user.name), null); + const labelElement = document.createElement('span'); - cursor.insertBefore(label, null); + labelElement.classList.add('collaboration-cursor-custom__label'); + labelElement.setAttribute('spellcheck', `false`); + labelElement.setAttribute( + 'style', + `background-color: ${user.color};border: 1px solid ${user.color};`, + ); + labelElement.insertBefore(document.createTextNode(user.name), null); - return cursor; + caretElement.insertBefore(labelElement, null); + + cursorElement.insertBefore(document.createTextNode('\u2060'), null); // Non-breaking space + cursorElement.insertBefore(caretElement, null); + cursorElement.insertBefore(document.createTextNode('\u2060'), null); // Non-breaking space + + return cursorElement; }, + showCursorLabels: showCursorLabels as 'always' | 'activity', }, dictionary: locales[lang as keyof typeof locales] as Dictionary, uploadFile,