From 0677eac721963ec5090f9a36e422b8785162437e Mon Sep 17 00:00:00 2001 From: Michael Freno Date: Tue, 23 Dec 2025 17:30:03 -0500 Subject: [PATCH] editor update --- src/components/blog/PostForm.tsx | 2 +- src/components/blog/TextEditor.tsx | 319 +++++++++++++---------------- 2 files changed, 144 insertions(+), 177 deletions(-) diff --git a/src/components/blog/PostForm.tsx b/src/components/blog/PostForm.tsx index 9ccaf05..919e53f 100644 --- a/src/components/blog/PostForm.tsx +++ b/src/components/blog/PostForm.tsx @@ -566,7 +566,7 @@ export default function PostForm(props: PostFormProps) {
Go to Post diff --git a/src/components/blog/TextEditor.tsx b/src/components/blog/TextEditor.tsx index dd39d16..4decbc8 100644 --- a/src/components/blog/TextEditor.tsx +++ b/src/components/blog/TextEditor.tsx @@ -1,5 +1,5 @@ import { Show, untrack, createEffect, on, createSignal, For } from "solid-js"; -import { createTiptapEditor, useEditorHTML } from "solid-tiptap"; +import { createTiptapEditor } from "solid-tiptap"; import StarterKit from "@tiptap/starter-kit"; import Link from "@tiptap/extension-link"; import CodeBlockLowlight from "@tiptap/extension-code-block-lowlight"; @@ -397,6 +397,32 @@ export default function TextEditor(props: TextEditorProps) { const [keyboardVisible, setKeyboardVisible] = createSignal(false); const [keyboardHeight, setKeyboardHeight] = createSignal(0); + // Force reactive updates for button states + const [editorState, setEditorState] = createSignal(0); + + // Helper to check editor active state reactively + const isActive = (type: string, attrs?: Record) => { + editorState(); // Track reactive dependency + const instance = editor(); + return instance ? instance.isActive(type, attrs) : false; + }; + + const isAlignActive = (alignment: string) => { + editorState(); + const instance = editor(); + if (!instance) return false; + + const { $from } = instance.state.selection; + const node = $from.node($from.depth); + const currentAlign = node?.attrs?.textAlign; + + if (currentAlign) { + return currentAlign === alignment; + } + + return alignment === "left"; + }; + const editor = createTiptapEditor(() => ({ element: editorRef, extensions: [ @@ -498,6 +524,9 @@ export default function TextEditor(props: TextEditorProps) { }); }, onSelectionUpdate: ({ editor }) => { + // Force reactive update for button states + setEditorState((prev) => prev + 1); + const { from, to } = editor.state.selection; const hasSelection = from !== to; @@ -1411,7 +1440,7 @@ export default function TextEditor(props: TextEditorProps) { ref={containerRef} class="border-surface2 text-text w-full max-w-full overflow-hidden rounded-md border px-4 py-2" classList={{ - "fixed inset-0 z-[100] m-0 h-screen max-h-screen rounded-none flex flex-col": + "fixed inset-0 z-100 m-0 h-screen max-h-screen rounded-none flex flex-col": isFullscreen(), "bg-base": isFullscreen() }} @@ -1423,7 +1452,7 @@ export default function TextEditor(props: TextEditorProps) {
-
+
@@ -1459,10 +1488,10 @@ export default function TextEditor(props: TextEditorProps) { .run() } class={`${ - instance().isActive("heading", { level: 2 }) + isActive("heading", { level: 2 }) ? "bg-surface2" : "hover:bg-surface1" - } rounded px-2 py-1`} + } touch-manipulation rounded px-2 py-1 select-none`} > H2 @@ -1476,10 +1505,10 @@ export default function TextEditor(props: TextEditorProps) { .run() } class={`${ - instance().isActive("heading", { level: 3 }) + isActive("heading", { level: 3 }) ? "bg-surface2" : "hover:bg-surface1" - } rounded px-2 py-1`} + } touch-manipulation rounded px-2 py-1 select-none`} > H3 @@ -1489,10 +1518,8 @@ export default function TextEditor(props: TextEditorProps) { instance().chain().focus().toggleBold().run() } class={`${ - instance().isActive("bold") - ? "bg-crust" - : "hover:bg-crust" - } bg-opacity-30 hover:bg-opacity-30 rounded px-2 py-1`} + isActive("bold") && "bg-crust" + } bg-opacity-30 hover:bg-opacity-30 touch-manipulation rounded px-2 py-1 select-none`} > B @@ -1502,10 +1529,8 @@ export default function TextEditor(props: TextEditorProps) { instance().chain().focus().toggleItalic().run() } class={`${ - instance().isActive("italic") - ? "bg-crust" - : "hover:bg-crust" - } bg-opacity-30 hover:bg-opacity-30 rounded px-2 py-1`} + isActive("italic") && "bg-crust" + } bg-opacity-30 hover:bg-opacity-30 touch-manipulation rounded px-2 py-1 select-none`} > I @@ -1515,10 +1540,8 @@ export default function TextEditor(props: TextEditorProps) { instance().chain().focus().toggleStrike().run() } class={`${ - instance().isActive("strike") - ? "bg-crust" - : "hover:bg-crust" - } bg-opacity-30 hover:bg-opacity-30 rounded px-2 py-1`} + isActive("strike") && "bg-crust" + } bg-opacity-30 hover:bg-opacity-30 touch-manipulation rounded px-2 py-1 select-none`} > S @@ -1526,36 +1549,19 @@ export default function TextEditor(props: TextEditorProps) { type="button" onClick={setLink} class={`${ - instance().isActive("link") - ? "bg-crust" - : "hover:bg-crust" - } bg-opacity-30 hover:bg-opacity-30 rounded px-2 py-1`} + isActive("link") && "bg-crust" + } bg-opacity-30 hover:bg-opacity-30 touch-manipulation rounded px-2 py-1 select-none`} > Link - - - {/* Table controls in bubble menu */} - +
{/* Table controls - shown when cursor is in a table */} - +