From d9593cbd106b05ebd6e45111f19a0fe289bf879d Mon Sep 17 00:00:00 2001 From: aditorito Date: Tue, 7 Apr 2026 18:57:26 +0000 Subject: [PATCH 1/6] Added color picker states --- frontend/src/components/TextBlockBubbleMenu.vue | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/frontend/src/components/TextBlockBubbleMenu.vue b/frontend/src/components/TextBlockBubbleMenu.vue index df44b032c..d7dce091a 100644 --- a/frontend/src/components/TextBlockBubbleMenu.vue +++ b/frontend/src/components/TextBlockBubbleMenu.vue @@ -155,6 +155,15 @@ const textLink = ref(""); const openInNewTab = ref(false); const linkInput = ref(null) as Ref; +const colorSwatchBtn = ref(null); +const colorPickerOpen = ref(false); +const colorPickerWrapper = ref(null); +const colorPickerStyle = ref>({ + position: "fixed", + top: "0px", + left: "0px", +}); + const editorRef = computed(() => props.editor); const isEditableRef = computed(() => props.isEditable); From ee7a8e0ec2e6e04b5f2d5da6dc9c777044695248 Mon Sep 17 00:00:00 2001 From: aditorito Date: Tue, 7 Apr 2026 19:18:07 +0000 Subject: [PATCH 2/6] removed .focus() and added guard --- frontend/src/components/TextBlockBubbleMenu.vue | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/TextBlockBubbleMenu.vue b/frontend/src/components/TextBlockBubbleMenu.vue index d7dce091a..ac15a611e 100644 --- a/frontend/src/components/TextBlockBubbleMenu.vue +++ b/frontend/src/components/TextBlockBubbleMenu.vue @@ -233,16 +233,17 @@ const isEntireTextSelected = () => { }; const setTextColor = debounce((color: string | undefined) => { + if (!props.editor || props.editor.isDestroyed) return; const colorValue = color as string; if (!colorValue) { - props.editor?.chain().focus().setColor(colorValue).run(); + props.editor.chain().setColor("").run(); if (isEntireTextSelected()) { props.block.setStyle("color", ""); } return; } - props.editor?.chain().focus().setColor(colorValue).run(); + props.editor.chain().setColor(colorValue).run(); if (isEntireTextSelected()) { props.block.setStyle("color", colorValue); } From 44cea815bc0534ba9452e9717e16a9e0012a2503 Mon Sep 17 00:00:00 2001 From: aditorito Date: Tue, 7 Apr 2026 19:25:32 +0000 Subject: [PATCH 3/6] feat: Outside Click closes the picker and get correct viewport --- .../src/components/TextBlockBubbleMenu.vue | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/frontend/src/components/TextBlockBubbleMenu.vue b/frontend/src/components/TextBlockBubbleMenu.vue index ac15a611e..7219cb816 100644 --- a/frontend/src/components/TextBlockBubbleMenu.vue +++ b/frontend/src/components/TextBlockBubbleMenu.vue @@ -174,6 +174,38 @@ const selectedColor = computed(() => { return null; }); +const toggleColorPicker = () => { + if (!colorPickerOpen.value) { + const rect = colorSwatchBtn.value?.getBoundingClientRect(); + if (rect) { + colorPickerStyle.value = { + position: "fixed", + top: `${rect.bottom + 8}px`, + left: `${rect.left}px`, + }; + } + } + colorPickerOpen.value = !colorPickerOpen.value; +}; + +const handleOutsideClick = (e: MouseEvent) => { + if ( + colorPickerWrapper.value && + !colorPickerWrapper.value.contains(e.target as Node) && + !colorSwatchBtn.value?.contains(e.target as Node) + ) { + colorPickerOpen.value = false; + } +}; + +watch(colorPickerOpen, (open) => { + if (open) { + document.addEventListener("mousedown", handleOutsideClick); + } else { + document.removeEventListener("mousedown", handleOutsideClick); + } +}); + const enableLinkInput = () => { settingLink.value = true; // check if link is already set on selection From 551cf3abac9fe54a0133ab3936daa1bcd5a65ece Mon Sep 17 00:00:00 2001 From: aditorito Date: Tue, 7 Apr 2026 19:27:52 +0000 Subject: [PATCH 4/6] feat:watcher closes it whenever the block stops being editable --- frontend/src/components/TextBlockBubbleMenu.vue | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/frontend/src/components/TextBlockBubbleMenu.vue b/frontend/src/components/TextBlockBubbleMenu.vue index 7219cb816..625ddc85c 100644 --- a/frontend/src/components/TextBlockBubbleMenu.vue +++ b/frontend/src/components/TextBlockBubbleMenu.vue @@ -206,6 +206,13 @@ watch(colorPickerOpen, (open) => { } }); +watch( + () => props.isEditable, + (editable) => { + if (!editable) colorPickerOpen.value = false; + }, +); + const enableLinkInput = () => { settingLink.value = true; // check if link is already set on selection From 84e622e4853b85eb3ff4278d2bd680a59b98c861 Mon Sep 17 00:00:00 2001 From: aditorito Date: Tue, 7 Apr 2026 19:46:42 +0000 Subject: [PATCH 5/6] refactor:Updated the component with button over colorpicker --- .../src/components/TextBlockBubbleMenu.vue | 63 +++++++++---------- 1 file changed, 29 insertions(+), 34 deletions(-) diff --git a/frontend/src/components/TextBlockBubbleMenu.vue b/frontend/src/components/TextBlockBubbleMenu.vue index 625ddc85c..b27187359 100644 --- a/frontend/src/components/TextBlockBubbleMenu.vue +++ b/frontend/src/components/TextBlockBubbleMenu.vue @@ -91,41 +91,36 @@ :class="{ 'bg-surface-gray-3': editor.isActive('link') }"> -
- - - - + @update:modelValue="setTextColor" + :show-input="true" + render-mode="inline" /> +
+ From d023c4bb4825b89a664586e989b3c047d733dfe0 Mon Sep 17 00:00:00 2001 From: aditorito Date: Tue, 7 Apr 2026 21:17:41 +0000 Subject: [PATCH 6/6] refactor: minor changes --- .../src/components/TextBlockBubbleMenu.vue | 45 ++++++++----------- 1 file changed, 18 insertions(+), 27 deletions(-) diff --git a/frontend/src/components/TextBlockBubbleMenu.vue b/frontend/src/components/TextBlockBubbleMenu.vue index b27187359..080543095 100644 --- a/frontend/src/components/TextBlockBubbleMenu.vue +++ b/frontend/src/components/TextBlockBubbleMenu.vue @@ -78,7 +78,6 @@ :class="{ 'bg-surface-gray-3': editor.isActive('strike') }"> -