Mention extension
Honestly, the mention node is amazing. It adds support for @mentions, for example to ping users, and provides full control over the rendering.
Literally everything can be customized. You can pass a custom component for the rendering. All examples use .filter() to search through items, but feel free to send async queries to an API or add a more advanced library like fuse.js to your project.
Install
npm install @tiptap/extension-mentionDependencies
Since 2.0.0-beta.193 we marked the @tiptap/suggestion as a peer dependency. That means, you will need to install it manually.
npm install @tiptap/suggestionSettings
HTMLAttributes
Custom HTML attributes that should be added to the rendered HTML tag.
Mention.configure({
HTMLAttributes: {
class: 'my-custom-class',
},
})renderText
Define how a mention text should be rendered.
Mention.configure({
renderText({ options, node }) {
return `${options.suggestion.char}${node.attrs.label ?? node.attrs.id}`
},
})renderHTML
Define how a mention html element should be rendered, this is useful if you want to render an element other than span (e.g a)
Mention.configure({
renderHTML({ options, node }) {
return [
'a',
mergeAttributes({ href: '/profile/1' }, options.HTMLAttributes),
`${options.suggestion.char}${node.attrs.label ?? node.attrs.id}`,
]
},
})deleteTriggerWithBackspace
Toggle whether the suggestion character(s) should also be deleted on deletion of a mention node. Default is false.
Mention.configure({
deleteTriggerWithBackspace: true,
})suggestion
Options for the Suggestion utility. Used to define what character triggers the suggestion popup, among other parameters. Read more.
Mention.configure({
suggestion: {
// …
},
})suggestions
Allows you to define multiple types of mentions within the same editor. For example, define a mention for people with the @ trigger and one for movies with the # trigger. Read more about the Suggestion utility.
Mention.configure({
suggestions: [
{
char: '@',
// Other options of the Suggestion utility
},
{
char: '#',
// Other options of the Suggestion utility
},
],
})Below is an example demo:
Collaboration
When working with Tiptap Collaboration, suggestions can sometimes "pop open" for remote users when someone else is typing a mention. To prevent this, you can configure the shouldShow option:
import { Mention } from '@tiptap/extension-mention'
import { isChangeOrigin } from '@tiptap/extension-collaboration'
const Editor = new Editor({
extensions: [
Mention.configure({
suggestion: {
shouldShow: ({ transaction }) => isChangeOrigin(transaction),
},
}),
],
})This ensures that the suggestion menu only opens for the user who actually typed the trigger character.
Use in Vanilla JavaScript
Here is a complete example that sets up a mention with a suggestion list:
import { Editor } from '@tiptap/core'
import Mention from '@tiptap/extension-mention'
new Editor({
element: document.querySelector('#editor'),
extensions: [
StarterKit,
Mention.configure({
HTMLAttributes: {
class: 'mention',
},
suggestion: {
char: '@',
items: ({ query }) => {
return ['Alice', 'Bob', 'Carol'].filter((name) =>
name.toLowerCase().includes(query.toLowerCase())
)
},
render: () => {
let popup
return {
onStart: (props) => {
popup = document.createElement('div')
popup.classList.add('suggestion-popup')
props.items.forEach((item) => {
const button = document.createElement('button')
button.textContent = item
button.addEventListener('click', () => props.command({ id: item }))
popup.appendChild(button)
})
document.body.appendChild(popup)
},
onUpdate: (props) => {
popup.innerHTML = ''
props.items.forEach((item) => {
const button = document.createElement('button')
button.textContent = item
button.addEventListener('click', () => props.command({ id: item }))
popup.appendChild(button)
})
},
onHide: () => {
popup?.remove()
},
}
},
},
}),
],
content: '<p>Type @ to mention someone.</p>',
})You can also pass a custom React or Vue component for rendering. See the Suggestion utility for details.