From 645f991531db6dbb2be9a026e8c8fad17b62d40f Mon Sep 17 00:00:00 2001 From: habibayman Date: Fri, 30 Jan 2026 17:11:12 +0200 Subject: [PATCH 1/6] build: add tiptap text align dependency --- package.json | 1 + pnpm-lock.yaml | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/package.json b/package.json index facf3534ad..2321ec3b49 100644 --- a/package.json +++ b/package.json @@ -59,6 +59,7 @@ "@tiptap/extension-link": "^3.13.0", "@tiptap/extension-subscript": "^3.13.0", "@tiptap/extension-superscript": "^3.13.0", + "@tiptap/extension-text-align": "^3.18.0", "@tiptap/starter-kit": "^3.13.0", "@tiptap/vue-2": "^3.13.0", "ajv": "^8.12.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4ad682ceef..278530c098 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -26,6 +26,9 @@ importers: '@tiptap/extension-superscript': specifier: ^3.13.0 version: 3.13.0(@tiptap/core@3.13.0(@tiptap/pm@3.13.0))(@tiptap/pm@3.13.0) + '@tiptap/extension-text-align': + specifier: ^3.18.0 + version: 3.18.0(@tiptap/core@3.13.0(@tiptap/pm@3.13.0)) '@tiptap/starter-kit': specifier: ^3.13.0 version: 3.13.0 @@ -1597,6 +1600,11 @@ packages: '@tiptap/core': ^3.13.0 '@tiptap/pm': ^3.13.0 + '@tiptap/extension-text-align@3.18.0': + resolution: {integrity: sha512-NEd2IUgOymKPmGOnxum4hLRbdQyBlK1Cmkt8QGIrmatovPrw2PtWmHVZ6foNChsi/r932dKVfqZ/uMUh8QUppQ==} + peerDependencies: + '@tiptap/core': ^3.18.0 + '@tiptap/extension-text@3.13.0': resolution: {integrity: sha512-VcZIna93rixw7hRkHGCxDbL3kvJWi80vIT25a2pXg0WP1e7Pi3nBYvZIL4SQtkbBCji9EHrbZx3p8nNPzfazYw==} peerDependencies: @@ -9282,6 +9290,10 @@ snapshots: '@tiptap/core': 3.13.0(@tiptap/pm@3.13.0) '@tiptap/pm': 3.13.0 + '@tiptap/extension-text-align@3.18.0(@tiptap/core@3.13.0(@tiptap/pm@3.13.0))': + dependencies: + '@tiptap/core': 3.13.0(@tiptap/pm@3.13.0) + '@tiptap/extension-text@3.13.0(@tiptap/core@3.13.0(@tiptap/pm@3.13.0))': dependencies: '@tiptap/core': 3.13.0(@tiptap/pm@3.13.0) From 01f34c47e184fade92ecd1068f4bb8874ef2e2e7 Mon Sep 17 00:00:00 2001 From: habibayman Date: Fri, 30 Jan 2026 19:37:44 +0200 Subject: [PATCH 2/6] feat(texteditor): add basic toggle alignmen functionality --- .../TipTapEditor/TipTapEditorStrings.js | 10 +++++++ .../TipTapEditor/components/EditorToolbar.vue | 15 ++++++++++ .../TipTapEditor/composables/useEditor.js | 4 +++ .../composables/useToolbarActions.js | 28 +++++++++++++++++++ .../TipTapEditor/assets/icon-alignLeft.svg | 3 ++ .../TipTapEditor/assets/icon-alignRight.svg | 3 ++ 6 files changed, 63 insertions(+) create mode 100644 contentcuration/contentcuration/frontend/shared/views/TipTapEditor/assets/icon-alignLeft.svg create mode 100644 contentcuration/contentcuration/frontend/shared/views/TipTapEditor/assets/icon-alignRight.svg diff --git a/contentcuration/contentcuration/frontend/shared/views/TipTapEditor/TipTapEditor/TipTapEditorStrings.js b/contentcuration/contentcuration/frontend/shared/views/TipTapEditor/TipTapEditor/TipTapEditorStrings.js index aeb5ad5cf9..ba1b764548 100644 --- a/contentcuration/contentcuration/frontend/shared/views/TipTapEditor/TipTapEditor/TipTapEditorStrings.js +++ b/contentcuration/contentcuration/frontend/shared/views/TipTapEditor/TipTapEditor/TipTapEditorStrings.js @@ -103,6 +103,16 @@ const MESSAGES = { context: 'Option to set text format to header 3', }, + // Text alignments + alignLeft: { + message: 'Align left', + context: 'Button to align text to the left', + }, + alignRight: { + message: 'Align right', + context: 'Button to align text to the right', + }, + // Accessibility labels textFormattingToolbar: { message: 'Text formatting toolbar', diff --git a/contentcuration/contentcuration/frontend/shared/views/TipTapEditor/TipTapEditor/components/EditorToolbar.vue b/contentcuration/contentcuration/frontend/shared/views/TipTapEditor/TipTapEditor/components/EditorToolbar.vue index f6f095f7a2..a37db6517c 100644 --- a/contentcuration/contentcuration/frontend/shared/views/TipTapEditor/TipTapEditor/components/EditorToolbar.vue +++ b/contentcuration/contentcuration/frontend/shared/views/TipTapEditor/TipTapEditor/components/EditorToolbar.vue @@ -68,6 +68,19 @@ + +
+ +
+

', editorProps: { diff --git a/contentcuration/contentcuration/frontend/shared/views/TipTapEditor/TipTapEditor/composables/useToolbarActions.js b/contentcuration/contentcuration/frontend/shared/views/TipTapEditor/TipTapEditor/composables/useToolbarActions.js index 58f10bbd94..e1d1158cf2 100644 --- a/contentcuration/contentcuration/frontend/shared/views/TipTapEditor/TipTapEditor/composables/useToolbarActions.js +++ b/contentcuration/contentcuration/frontend/shared/views/TipTapEditor/TipTapEditor/composables/useToolbarActions.js @@ -21,6 +21,8 @@ export function useToolbarActions(emit) { mathFormula$, codeBlock$, clipboardAccessFailed$, + alignLeft$, + alignRight$, } = getTipTapEditorStrings(); // Action handlers @@ -181,6 +183,17 @@ export function useToolbarActions(emit) { } }; + const handleToggleAlign = () => { + if (editor?.value) { + const isRightAligned = editor.value.isActive({ textAlign: 'right' }); + if (isRightAligned) { + editor.value.chain().focus().setTextAlign('left').run(); + } else { + editor.value.chain().focus().setTextAlign('right').run(); + } + } + }; + const handleBulletList = () => { if (editor?.value) { editor.value.chain().focus().toggleBulletList().run(); @@ -418,6 +431,19 @@ export function useToolbarActions(emit) { handler: handleMinimize, }; + const alignAction = computed(() => { + const isRightAligned = editor?.value?.isActive({ textAlign: 'right' }) || false; + return { + name: 'toggleAlign', + title: isRightAligned ? alignLeft$() : alignRight$(), + icon: isRightAligned + ? require('../../assets/icon-alignLeft.svg') + : require('../../assets/icon-alignRight.svg'), + handler: handleToggleAlign, + isActive: false, + }; + }); + return { // Individual handlers handleUndo, @@ -429,6 +455,7 @@ export function useToolbarActions(emit) { handleCopy, handlePaste, handlePasteNoFormat, + handleToggleAlign, handleBulletList, handleNumberList, handleSubscript, @@ -444,6 +471,7 @@ export function useToolbarActions(emit) { // Action arrays historyActions, textActions, + alignAction, listActions, scriptActions, insertTools, diff --git a/contentcuration/contentcuration/frontend/shared/views/TipTapEditor/assets/icon-alignLeft.svg b/contentcuration/contentcuration/frontend/shared/views/TipTapEditor/assets/icon-alignLeft.svg new file mode 100644 index 0000000000..e0de070ed0 --- /dev/null +++ b/contentcuration/contentcuration/frontend/shared/views/TipTapEditor/assets/icon-alignLeft.svg @@ -0,0 +1,3 @@ + + + diff --git a/contentcuration/contentcuration/frontend/shared/views/TipTapEditor/assets/icon-alignRight.svg b/contentcuration/contentcuration/frontend/shared/views/TipTapEditor/assets/icon-alignRight.svg new file mode 100644 index 0000000000..8ae6fa53fd --- /dev/null +++ b/contentcuration/contentcuration/frontend/shared/views/TipTapEditor/assets/icon-alignRight.svg @@ -0,0 +1,3 @@ + + + From 0e3912fd2fece35580f4e3d5ff24a425f476a2bf Mon Sep 17 00:00:00 2001 From: habibayman Date: Fri, 30 Jan 2026 19:51:32 +0200 Subject: [PATCH 3/6] fix(texteditor): toolbar overflow logic after adding alignment button --- .../TipTapEditor/components/EditorToolbar.vue | 40 ++++++++++++++----- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/contentcuration/contentcuration/frontend/shared/views/TipTapEditor/TipTapEditor/components/EditorToolbar.vue b/contentcuration/contentcuration/frontend/shared/views/TipTapEditor/TipTapEditor/components/EditorToolbar.vue index a37db6517c..ab2de767ef 100644 --- a/contentcuration/contentcuration/frontend/shared/views/TipTapEditor/TipTapEditor/components/EditorToolbar.vue +++ b/contentcuration/contentcuration/frontend/shared/views/TipTapEditor/TipTapEditor/components/EditorToolbar.vue @@ -69,17 +69,15 @@ -
- -
+ + + + + +