Mention extension for Tiptap rich text editor that enables @-mention functionality with customizable suggestion handling
npx @tessl/cli install tessl/npm-tiptap--extension-mention@3.4.00
# Tiptap Mention Extension
1
2
The @tiptap/extension-mention package provides a mention extension for the Tiptap rich text editor framework. It enables developers to implement @-mention functionality that integrates with Tiptap's suggestion system to provide real-time mention suggestions and rendering.
3
4
## Package Information
5
6
- **Package Name**: @tiptap/extension-mention
7
- **Package Type**: npm
8
- **Language**: TypeScript
9
- **Installation**: `npm install @tiptap/extension-mention @tiptap/core @tiptap/pm @tiptap/suggestion`
10
- **Peer Dependencies**: @tiptap/core, @tiptap/pm, @tiptap/suggestion
11
12
## Core Imports
13
14
```typescript
15
import { Mention } from "@tiptap/extension-mention";
16
```
17
18
For default import:
19
20
```typescript
21
import Mention from "@tiptap/extension-mention";
22
```
23
24
For utility functions:
25
26
```typescript
27
import { getSuggestionOptions } from "@tiptap/extension-mention";
28
```
29
30
## Basic Usage
31
32
```typescript
33
import { Editor } from "@tiptap/core";
34
import { Mention } from "@tiptap/extension-mention";
35
36
const editor = new Editor({
37
extensions: [
38
Mention.configure({
39
HTMLAttributes: {
40
class: "mention",
41
},
42
suggestion: {
43
items: ({ query }) => {
44
return [
45
{ id: 1, label: "Alice" },
46
{ id: 2, label: "Bob" },
47
{ id: 3, label: "Charlie" },
48
].filter(item =>
49
item.label.toLowerCase().startsWith(query.toLowerCase())
50
);
51
},
52
render: () => {
53
// Custom render implementation
54
return {
55
onStart: (props) => {},
56
onUpdate: (props) => {},
57
onKeyDown: (props) => {},
58
onExit: () => {},
59
};
60
},
61
},
62
}),
63
],
64
});
65
```
66
67
## Architecture
68
69
The Mention extension is built around several key components:
70
71
- **Node Extension**: Extends Tiptap's Node class to create inline, atomic mention nodes
72
- **Suggestion Integration**: Seamlessly integrates with @tiptap/suggestion for real-time mention UI
73
- **Multi-trigger Support**: Supports multiple trigger characters (@, #, etc.) simultaneously
74
- **Attribute System**: Stores mention data (id, label, trigger char) as structured node attributes
75
- **Rendering Pipeline**: Flexible text and HTML rendering with customizable templates
76
- **Keyboard Handling**: Smart backspace behavior for mention deletion and navigation
77
78
## Capabilities
79
80
### Main Extension Class
81
82
Core mention extension that creates mention nodes in the editor.
83
84
```typescript { .api }
85
/**
86
* Main mention extension class implementing ProseMirror node functionality
87
*/
88
export const Mention: Node<MentionOptions>;
89
```
90
91
### Utility Functions
92
93
Utility functions for configuring mention suggestions.
94
95
```typescript { .api }
96
/**
97
* Returns the suggestion options for a trigger of the Mention extension
98
* @param options Configuration options for the suggestion
99
* @returns Complete suggestion options for the trigger
100
*/
101
export function getSuggestionOptions(options: GetSuggestionOptionsOptions): SuggestionOptions;
102
```
103
104
### Extension Configuration
105
106
Configure the mention extension with options for rendering, suggestions, and behavior.
107
108
```typescript { .api }
109
interface MentionOptions<SuggestionItem = any, Attrs extends Record<string, any> = MentionNodeAttrs> {
110
/** HTML attributes for mention nodes @default {} */
111
HTMLAttributes: Record<string, any>;
112
113
/** Function to render the text content of a mention */
114
renderText: (props: {
115
options: MentionOptions<SuggestionItem, Attrs>;
116
node: ProseMirrorNode;
117
suggestion: SuggestionOptions | null;
118
}) => string;
119
120
/** Function to render the HTML of a mention */
121
renderHTML: (props: {
122
options: MentionOptions<SuggestionItem, Attrs>;
123
node: ProseMirrorNode;
124
HTMLAttributes: Record<string, any>;
125
suggestion: SuggestionOptions | null;
126
}) => DOMOutputSpec;
127
128
/** Whether to delete the trigger character with backspace @default false */
129
deleteTriggerWithBackspace: boolean;
130
131
/** Multiple trigger configurations for different mention types @default [] */
132
suggestions: Array<Omit<SuggestionOptions<SuggestionItem, Attrs>, 'editor'>>;
133
134
/** Single trigger configuration (use suggestions for multiple triggers) @default {} */
135
suggestion: Omit<SuggestionOptions<SuggestionItem, Attrs>, 'editor'>;
136
137
/** @deprecated Use renderText and renderHTML instead */
138
renderLabel?: (props: {
139
options: MentionOptions<SuggestionItem, Attrs>;
140
node: ProseMirrorNode;
141
suggestion: SuggestionOptions | null;
142
}) => string;
143
}
144
```
145
146
### Mention Node Attributes
147
148
Attributes stored on mention nodes for data persistence and rendering.
149
150
```typescript { .api }
151
interface MentionNodeAttrs {
152
/** Identifier for the mentioned item, stored as data-id attribute */
153
id: string | null;
154
155
/** Display label for the mention, stored as data-label attribute */
156
label?: string | null;
157
158
/** Trigger character that activated this mention, stored as data-mention-suggestion-char @default '@' */
159
mentionSuggestionChar?: string;
160
}
161
162
interface GetSuggestionOptionsOptions {
163
/** The Tiptap editor instance */
164
editor: Editor;
165
166
/** The suggestion options configuration provided to the Mention extension */
167
overrideSuggestionOptions: Omit<SuggestionOptions, 'editor'>;
168
169
/** The name of the Mention extension */
170
extensionName: string;
171
172
/** The character that triggers the suggestion */
173
char?: string;
174
}
175
```
176
177
178
179
## Types
180
181
### External Dependencies
182
183
The extension relies on types from its peer dependencies:
184
185
- `Editor` from `@tiptap/core` - The main Tiptap editor instance
186
- `DOMOutputSpec` from `@tiptap/pm/model` - ProseMirror DOM output specification
187
- `ProseMirrorNode` from `@tiptap/pm/model` - ProseMirror node with attributes
188
- `SuggestionOptions` from `@tiptap/suggestion` - Configuration for suggestion functionality
189
190
**Usage Examples:**
191
192
```typescript
193
import { Editor } from "@tiptap/core";
194
import { Mention } from "@tiptap/extension-mention";
195
196
// Basic mention setup
197
const editor = new Editor({
198
extensions: [
199
Mention.configure({
200
HTMLAttributes: {
201
class: "mention",
202
},
203
suggestion: {
204
items: ({ query }) => {
205
return users.filter(user =>
206
user.name.toLowerCase().includes(query.toLowerCase())
207
);
208
},
209
render: () => ({
210
onStart: (props) => {
211
// Show suggestion popup
212
},
213
onUpdate: (props) => {
214
// Update suggestions
215
},
216
onKeyDown: (props) => {
217
// Handle keyboard navigation
218
if (props.event.key === "Enter") {
219
return true; // Handled
220
}
221
return false;
222
},
223
onExit: () => {
224
// Hide popup
225
},
226
}),
227
},
228
}),
229
],
230
});
231
232
// Multiple trigger characters
233
const editorWithMultipleTriggers = new Editor({
234
extensions: [
235
Mention.configure({
236
suggestions: [
237
{
238
char: "@",
239
items: ({ query }) => getUserSuggestions(query),
240
render: () => createUserMentionRenderer(),
241
},
242
{
243
char: "#",
244
items: ({ query }) => getTagSuggestions(query),
245
render: () => createTagMentionRenderer(),
246
},
247
],
248
}),
249
],
250
});
251
252
// Custom rendering
253
const editorWithCustomRender = new Editor({
254
extensions: [
255
Mention.configure({
256
renderText: ({ node, suggestion }) => {
257
return `${suggestion?.char ?? "@"}${node.attrs.label ?? node.attrs.id}`;
258
},
259
renderHTML: ({ node, HTMLAttributes, suggestion }) => {
260
return [
261
"span",
262
{
263
...HTMLAttributes,
264
"data-type": "mention",
265
"data-id": node.attrs.id,
266
class: "custom-mention",
267
},
268
`${suggestion?.char ?? "@"}${node.attrs.label ?? node.attrs.id}`,
269
];
270
},
271
suggestion: {
272
items: ({ query }) => getMentionItems(query),
273
render: () => createMentionRenderer(),
274
},
275
}),
276
],
277
});
278
```