I can write @hans, then select a person, then when i try to write @ someone else and it won't work until i create a new paragraph. I believe this used to work, any ideas?
Illustrated on the example page here:
https://tiptap.dev/suggestions
Even if you add a few paragraphs, When you write a second mention the entire dropdown goes buggy and moves to the top left of corner of the browser.
Thanks for reporting! This is an issue with tippy.js, not with tiptap. So I’m not sure we can do something about that.
@hanspagel what a pain. Funnily enough, with some mucking around, i duplicated the Suggestions Plugin and Mention extension myself and was able to get it working. But i'm not sure exactly what i did or how.
Thanks for an awesome editor
@hanspagel regarding the first line of this issue, I'm not sure this is an issue with tippy.js. The onEnter/onChange callbacks are not called regardless of whether tippy is used or not.
I don't have an issue with positioning when adding a second mention in a future paragraph. I'm just completely unable to add two mentions in the same paragraph using @.
@hanspagel I agree with @axwalker. I'm not using tippy.js in my implementation at all and handle dropdowns with Vuetify. For me onEnter event doesn't fire too when I already have another mention in the line.
I'm sure it was working before and problem arrived after updating tiptap-extensions from 1.33.0 to 1.33.2
Okay, I don’t have time to look at it now, but I’ll reopen the issue.
As a current workaround fixating tiptap-extensions to 1.33.0 works 👌
@hanspagel I can confirm that the bug doesn't appear in 1.33.0. Deleting content: 'inline*' from schema in Mention.js fixes the issue, but I can't say for sure whether that breaks anything else
@greghub If current content: 'inline*' in schema is correct, then must be some bugs in SuggestionsPlugin.
It can not find a valid match, because the from, to can not pass the condition below, so not tigger the suggestions popup.
// line 59
// If the $position is located within the matched substring, return that range
if (from < $position.pos && to >= $position.pos) {
position = {
range: {
from,
to,
},
query: match[0].slice(char.length),
text: match[0],
}
}
I think the problems maybe the mention is a document node, when use regex match the text content, the matched index is not the same index in prosemirror.
The truth is, you can write a second mention, just make sure your new mention come first.

@Priestch is exactly right. All mentions that use tiptao-extensions/src/plugins/Suggestions.js fail to trigger in a paragraph that contains one or more inline nodes before the cursor position.
"tiptap": "^1.30.0",
"tiptap-commands": "^1.15.0",
"tiptap-extensions": "^1.33.2",
<div class="ProseMirror" contenteditable="true" tabindex="0">
<p><a href="https://example.com" rel="noopener noreferrer nofollow">https://example.com</a> is an example.</p>
</div>
(Trying to start a suggestion using matcher char / at the end, like example. /)
get schema() {
return {
content: "text*",
group: "inline",
inline: true,
attrs: {
href: {
default: "",
},
},
parseDOM: [
{
tag: "a[href]",
getAttrs: (dom) => ({
href: dom.getAttribute("href"),
}),
},
],
toDOM: (node) => [
"a",
{
...node.attrs,
rel: "noopener noreferrer nofollow",
},
0,
],
};
}
SuggestionsPlugin({
matcher: '/',
items: [],
// event handlers ...
suggestionClass: "slash-command-suggestion",
})
At If the $position is located within the matched substring, return that range. See https://github.com/ueberdosis/tiptap/blob/94d7a480d8d5630a0e0f7942b5e7565fa8700386/packages/tiptap-extensions/src/plugins/Suggestions.js#L51
The position is out by two. I'm assuming this has to do with the edges of the inline node each counting as 1 extra position in Prosemirror. See https://prosemirror.net/docs/guide/#doc.indexing
It'd make sense to remove the content: 'inline*' expression, since that seems to allow child nodes, but I can't imagine a scenario where a Mention could have a child node 🤔
https://prosemirror.net/docs/guide/#schema.content_expressions
@andreasvirkus Content in schema has nothing to do with issue, it was added to fix copy issue in #860
I feel the progress here has stagnated. @Priestch can you think of another way to solve the copy issue perhaps? Or help us discover another way to make multiple Mention nodes work in the same paragraph?
There are other fixes in the newer versions of tiptap-extensions, like the HardBreak command (#846), that we'd like to get back, but we can't update because of this bug. Same goes for the fix https://github.com/ueberdosis/tiptap/pull/860, since it was also released in 1.33.2
@andreasvirkus I think maybe you can custom clipboardSerializer or clipboardTextSerializer to make copy work.
But I do not think this is the right way to solve the problem. @rudolfbyker give the logic reason why second mention do not work now, Because content: 'inline*' makes the mention not a leaf node any more, so code below
https://github.com/ueberdosis/tiptap/blob/b2394ffa99ae7ca5213f3f5c85f1700e56fd63c6/packages/tiptap-extensions/src/plugins/Suggestions.js#L29
which finally call function below
https://github.com/ProseMirror/prosemirror-model/blob/5564b0e966bf49648bc98b28b0055996447dafaa/src/fragment.js#L43
// : (number, number, ?string, ?string) → string
textBetween(from, to, blockSeparator, leafText) {
let text = "", separated = true
this.nodesBetween(from, to, (node, pos) => {
if (node.isText) {
text += node.text.slice(Math.max(from, pos) - pos, to - pos)
separated = !blockSeparator
} else if (node.isLeaf && leafText) {
text += leafText
separated = !blockSeparator
} else if (!separated && node.isBlock) {
text += blockSeparator
separated = true
}
}, 0)
return text
}
Whether node is leaf or not will make the text result different. I think the mention node does has the content, maybe content: 'inline*' is not as precise as content: 'text*', but is the right way to make copy work.
@andreasvirkus I think maybe you can custom clipboardSerializer or clipboardTextSerializer to make copy work.
But I do not think this is the right way to solve the problem. @rudolfbyker give the logic reason why second mention do not work now, Because
content: 'inline*'makes the mention not a leaf node any more, so code below
https://github.com/ueberdosis/tiptap/blob/b2394ffa99ae7ca5213f3f5c85f1700e56fd63c6/packages/tiptap-extensions/src/plugins/Suggestions.js#L29which finally call function below
https://github.com/ProseMirror/prosemirror-model/blob/5564b0e966bf49648bc98b28b0055996447dafaa/src/fragment.js#L43// : (number, number, ?string, ?string) → string textBetween(from, to, blockSeparator, leafText) { let text = "", separated = true this.nodesBetween(from, to, (node, pos) => { if (node.isText) { text += node.text.slice(Math.max(from, pos) - pos, to - pos) separated = !blockSeparator } else if (node.isLeaf && leafText) { text += leafText separated = !blockSeparator } else if (!separated && node.isBlock) { text += blockSeparator separated = true } }, 0) return text }Whether node is leaf or not will make the text result different. I think the mention node does has the content, maybe
content: 'inline*'is not as precise ascontent: 'text*', but is the right way to make copy work.
If I remove the content: 'inline*', will it have any side effect?
If I remove the
content: 'inline*', will it have any side effect?
I checked the old codebase from version 1.33.0 the only difference is the property content, and after i removed content: 'inline*' it works like a charm
The only currently known side effect is that it will break copy-paste (Suggestions are not included into the clipboard), so
This text mentions
@John Smithand his children@Lisaand@Jason
gets transformed into
This text mentions and his children and
It was added with https://github.com/ueberdosis/tiptap/pull/860
Is there any update on this problem? Currently, I am using tiptap for my product but for client requirements, I need the mentions feature. Any help would be appreciated please @hanspagel
@Hyperblaster @andreasvirkus @Draccano @joseederangojr @USasikumar
I submitted a new commit in #861 to fix this issue, seems work!
Thank you all for your work on this! 👏 Thanks @Priestch @andreasvirkus @Hyperblaster and all others!
The PR has been merged and we plan to release a version in the first two weeks of January, maybe earlier - but we want to make sure not to introduce new bugs (like we did with the recent versions).
Most helpful comment
@hanspagel regarding the first line of this issue, I'm not sure this is an issue with tippy.js. The
onEnter/onChangecallbacks are not called regardless of whether tippy is used or not.I don't have an issue with positioning when adding a second mention in a future paragraph. I'm just completely unable to add two mentions in the same paragraph using
@.