diff --git a/src/components/blog/TextEditor.tsx b/src/components/blog/TextEditor.tsx index fabd582..3a89917 100644 --- a/src/components/blog/TextEditor.tsx +++ b/src/components/blog/TextEditor.tsx @@ -1,4 +1,4 @@ -import { Show, untrack, createEffect, on } from "solid-js"; +import { Show, untrack, createEffect, on, createSignal } from "solid-js"; import { createTiptapEditor, useEditorHTML } from "solid-tiptap"; import StarterKit from "@tiptap/starter-kit"; import Link from "@tiptap/extension-link"; @@ -104,6 +104,13 @@ export interface TextEditorProps { export default function TextEditor(props: TextEditorProps) { let editorRef!: HTMLDivElement; + let bubbleMenuRef!: HTMLDivElement; + + const [showBubbleMenu, setShowBubbleMenu] = createSignal(false); + const [bubbleMenuPosition, setBubbleMenuPosition] = createSignal({ + top: 0, + left: 0 + }); const editor = createTiptapEditor(() => ({ element: editorRef, @@ -126,6 +133,26 @@ export default function TextEditor(props: TextEditorProps) { untrack(() => { props.updateContent(editor.getHTML()); }); + }, + onSelectionUpdate: ({ editor }) => { + const { from, to } = editor.state.selection; + const hasSelection = from !== to; + + if (hasSelection && !editor.state.selection.empty) { + setShowBubbleMenu(true); + + // Position the bubble menu + const { view } = editor; + const start = view.coordsAtPos(from); + const end = view.coordsAtPos(to); + + const left = Math.max((start.left + end.left) / 2, 0); + const top = Math.max(start.top - 10, 0); + + setBubbleMenuPosition({ top, left }); + } else { + setShowBubbleMenu(false); + } } })); @@ -191,13 +218,17 @@ export default function TextEditor(props: TextEditorProps) { {(instance) => ( <> {/* Bubble Menu - appears when text is selected */} -
-
+ +
-
+ - {/* Toolbar - always visible */}