Configure comments
Comments are embedded within documents in the Collaboration Cloud. To enable comments, integrate the TiptapCollabProvider and configure your setup to support comment functionality.
Provider
The TiptapCollabProvider instance
Default: null
const tiptapCollabProvider = new TiptapCollabProvider({
// your provider options
})
Comments.configure({
provider: tiptapCollabProvider,
})Classes
The classes used for the threads.
Default:
{
thread: 'tiptap-thread',
threadInline: 'tiptap-thread--inline',
threadBlock: 'tiptap-thread--block',
threadHovered: 'tiptap-thread--hovered',
threadSelected: 'tiptap-thread--selected',
threadResolved: 'tiptap-thread--resolved',
threadUnresolved: 'tiptap-thread--unresolved',
}Comments.configure({
classes: {
thread: 'my-thread',
threadInline: 'my-thread-inline',
threadBlock: 'my-thread-block',
threadHovered: 'my-thread-hovered',
threadSelected: 'my-thread-selected',
threadResolved: 'my-thread-resolved',
threadUnresolved: 'my-thread-unresolved',
},
})onClickThread
A callback that is called when a thread is clicked. If the thread is clicked, the thread ID is passed to the callback. If no thread is clicked, null is passed.
Default: undefined
Comments.configure({
// ID can be a string or null
onClickThread: (id) => console.log('Thread clicked', id),
})deleteUnreferencedThreads
A boolean option that controls whether to delete threads not referenced in the document. By default, threads are marked as deleted when they are not referenced in a document anymore. This is useful for cleaning up threads that are no longer needed.
However, if you want to keep the threads even if they are not referenced in the document, you can set this option to false.
Default:: true
Comments.configure({
// keep threads even if they are not referenced in the document
deleteUnreferencedThreads: false,
})If you configure onThreadAnchorRemoved, that option replaces automatic cleanup. Its defaultHandler() still respects deleteUnreferencedThreads.
onThreadAnchorRemoved
A callback that runs when a local edit removes a thread's last document anchor. An anchor is an inline thread mark or a block thread node. The callback runs after edits settle, before cleanup changes the thread data. It runs only on the editing client, not on clients receiving the change remotely.
Default: undefined, which keeps automatic cleanup controlled by deleteUnreferencedThreads.
Set this option to false to disable automatic cleanup when anchors disappear. A callback replaces cleanup unless it calls defaultHandler(). The default handler soft-deletes the unreferenced thread when deleteUnreferencedThreads is true.
For example, resolve the thread and keep its comments when its anchor disappears:
CommentsKit.configure({
onThreadAnchorRemoved: ({ editor, threadId }) => {
editor.commands.resolveThread({ id: threadId })
},
})The callback receives these arguments:
| Argument | Description |
|---|---|
editor | The editor whose last anchor for the thread was removed. |
threadId | The thread ID. |
thread | The current thread data, including its comments. |
field | The collaboration field containing the thread. |
removedBy | 'edit', 'command', or 'undoRedo'. |
defaultHandler | Runs the configured default cleanup. |
Explicit anchor removal with removeThread({ id }) reports 'command'. Calling removeThread({ id, deleteThread: true }) deletes the thread directly and skips this callback. Threads created for Tracked Changes suggestions are handled by that integration and also skip this callback.
Call defaultHandler() synchronously inside the callback. It runs at most once, and calls made after the callback returns have no effect. For example, log the removal and keep default cleanup:
CommentsKit.configure({
onThreadAnchorRemoved: ({ threadId, removedBy, defaultHandler }) => {
console.log('Thread anchor removed', threadId, removedBy)
defaultHandler()
},
})onThreadStateChanged
A callback that runs after a Yjs transaction changes an existing thread's state in the editor's collaboration field. It handles both local and remote changes. Creating a thread, adding a comment, or updating thread metadata does not trigger it.
Default: undefined, which keeps default document handling. Permanent thread deletion removes its anchors and preserves their text. Resolving, reopening, soft-deleting, or restoring a thread keeps its anchors.
Set this option to false to disable automatic document handling for thread state changes. A callback replaces that handling unless it calls defaultHandler().
CommentsKit.configure({
onThreadStateChanged: ({ event, threadId, origin, defaultHandler }) => {
console.log('Thread state changed', event, threadId, origin)
defaultHandler()
},
})The callback receives these arguments:
| Argument | Description |
|---|---|
editor | The editor handling the state change. |
threadId | The thread ID. |
event | 'resolved', 'unresolved', 'deleted', or 'restored'. |
previousThread | The thread data before the change. |
thread | The thread data after the change. This is undefined after permanent deletion. |
field | The collaboration field containing the thread. |
origin | 'local' or 'remote', based on the Yjs transaction. |
defaultHandler | Runs default document handling. Call it synchronously inside the callback, at most once. Calls after the callback returns have no effect. |
The 'deleted' event covers both soft deletion and permanent deletion. The 'restored' event means a soft-deleted thread was restored, not that its document anchor was restored.
For example, remove the anchor when a thread is resolved while keeping the thread and its comments:
CommentsKit.configure({
onThreadStateChanged: ({ editor, threadId, event, defaultHandler }) => {
if (event === 'resolved') {
editor.commands.removeThread({ id: threadId, deleteThread: false })
}
defaultHandler()
},
})Anchor removal inside this callback does not trigger onThreadAnchorRemoved or automatic deletion of the detached thread. Thread state changes made inside this callback do not trigger another local state callback. Reopening the thread does not recreate an anchor removed by custom handling.
trackedChangesIntegration
A boolean option that controls whether to enable the automatic Track Changes integration. When enabled, threads are automatically created, updated, resolved, or deleted in response to Track Changes suggestion lifecycle events.
Set this to false if you do not use the Track Changes extension and want to prevent any related event listeners and ProseMirror plugins from being registered.
Default: true
Comments.configure({
// disable Track Changes integration if you don't use that extension
trackedChangesIntegration: false,
})respectParentSchema
With respectParentSchema: true, local edits inside a block thread must follow the parent node's content rules. For example, a block thread in a section that allows paragraphs but not lists cannot contain a list. The extension converts a single invalid text block when it can preserve its text. It rejects edits it cannot repair.
Existing invalid block threads are not migrated. Their text remains editable as long as their child block types do not change. Enable this option on every collaborating client.
Default: false
CommentsKit.configure({
respectParentSchema: true,
})useLegacyWrapping
Warning
The new wrapping mechanism uses a different schema for threads on block nodes, which is not
compatible with the previous wrapping behavior. If this is set to false without mapping existing
thread nodes to the new schema, the threads content will be stripped from the document.
A boolean option that controls whether to use the legacy wrapping mechanism for multi-line comments. We suggest for new implementations to set this to false, and existing integrations can stay on the previous behavior. This is only required for backwards compatibility with existing comments, and it will
be removed in the future.
The new wrapping mechanism is more flexible, allowing to wrap content more precise and supports mixed wrapping of inline and block nodes.
Default: true
Comments.configure({
// enable new flexible block wrapping
useLegacyWrapping: false,
})