diff --git a/src/components/editor/MentionEditor.tsx b/src/components/editor/MentionEditor.tsx index 976f5f7..a468e7b 100644 --- a/src/components/editor/MentionEditor.tsx +++ b/src/components/editor/MentionEditor.tsx @@ -900,7 +900,15 @@ export const MentionEditor = forwardRef< .run(); }, }, - // Note: renderLabel is not used when nodeView is defined + // Provide renderText option to prevent fallback to '@' character + // TipTap's default renderText uses `suggestion?.char ?? '@'` which + // can produce '@' when suggestion context is unavailable (e.g., during backspace) + renderText({ node }: any) { + if (node.attrs.source === "unicode") { + return node.attrs.url || ""; + } + return `:${node.attrs.id}:`; + }, }), ); } diff --git a/src/components/editor/RichEditor.tsx b/src/components/editor/RichEditor.tsx index ff808bc..115d9d3 100644 --- a/src/components/editor/RichEditor.tsx +++ b/src/components/editor/RichEditor.tsx @@ -507,6 +507,15 @@ export const RichEditor = forwardRef( .run(); }, }, + // Provide renderText option to prevent fallback to '@' character + // TipTap's default renderText uses `suggestion?.char ?? '@'` which + // can produce '@' when suggestion context is unavailable (e.g., during backspace) + renderText({ node }: any) { + if (node.attrs.source === "unicode") { + return node.attrs.url || ""; + } + return `:${node.attrs.id}:`; + }, }), ); }