Add Word-style commenting to documents with threaded discussions, replies, and resolution workflows.
Quick start
const superdoc = new SuperDoc ({
selector: "#editor" ,
document: "contract.docx" ,
user: {
name: "John Smith" ,
email: "john@company.com" ,
},
modules: {
comments: {
allowResolve: true ,
element: "#comments" ,
},
},
onCommentsUpdate : ({ type , comment }) => {
console . log ( "Comment event:" , type );
},
});
The comments module is enabled by default . To disable it entirely, set modules.comments to false: modules : {
comments : false ;
}
Configuration
View-only mode, prevents new comments
Allow marking comments as resolved
Container for comments sidebar
Enable dual internal/external comment system
Hide internal comments from view
Show resolved comments in the comments list
Custom colors for comment highlights. Highlight color for external comments
Highlight color for internal comments
Active highlight color override for external comments
Active highlight color override for internal comments
Opacity values for comment highlights (0–1). Opacity for the active comment highlight
Opacity for inactive comment highlights
Hover highlight color for comment marks
Colors for tracked change highlights. Border color for inserted text
Background color for inserted text
Border color for deleted text
Background color for deleted text
Border color for format changes
Colors for the active tracked change highlight. Same properties as trackChangeHighlightColors. Defaults to trackChangeHighlightColors values when not set.
Viewing mode visibility
Comments are hidden by default when documentMode is viewing. Use the
top-level comments.visible and trackChanges.visible flags to control what
renders in read-only mode.
new SuperDoc ({
selector: "#viewer" ,
document: "contract.docx" ,
documentMode: "viewing" ,
comments: { visible: true }, // Standard comment threads
trackChanges: { visible: false }, // Tracked-change markup + threads
});
During initialization:
modules : {
comments : {
element : "#comments-sidebar" ;
}
}
After initialization:
superdoc . on ( "ready" , () => {
superdoc . addCommentsList ( "#comments-sidebar" );
});
Permission resolver
Customize who can resolve comments or accept tracked changes. The resolver receives the permission type, current user, and any tracked-change metadata. Return false to block the action.
modules : {
comments : {
permissionResolver : ({
permission ,
trackedChange ,
currentUser ,
defaultDecision ,
}) => {
if (
permission === "RESOLVE_OTHER" &&
trackedChange ?. attrs ?. authorEmail !== currentUser ?. email
) {
return false ; // Block accepting suggestions from other authors
}
return defaultDecision ;
},
},
}
You can set a global resolver with the top-level permissionResolver config.
Module-level resolvers take precedence when both are defined.
Word import/export
Word comments are automatically imported with the document and marked with importedId. When exporting, use the commentsType option:
// Include comments in export
const blob = await superdoc . export ({ commentsType: "external" });
// Remove all comments
const cleanBlob = await superdoc . export ({ commentsType: "clean" });
API methods
These methods are available on the active editor’s commands:
Add a comment to the current text selection. Requires a text selection.
// Simple usage
superdoc . activeEditor . commands . addComment ( "Review this section" );
// With options
superdoc . activeEditor . commands . addComment ({
content: "Please clarify this section" ,
author: "John Smith" ,
authorEmail: "john@company.com" ,
isInternal: true ,
});
Comment content as a string, or an options object with: The comment text (text or HTML)
Author name (defaults to user.name from config)
Author email (defaults to user.email from config)
Whether the comment is internal/private
Add a reply to an existing comment or tracked change.
superdoc . activeEditor . commands . addCommentReply ({
parentId: "comment-123" ,
content: "I agree with this suggestion" ,
});
The ID of the parent comment to reply to
Reply content (text or HTML)
Author name (defaults to user.name from config)
Author email (defaults to user.email from config)
superdoc . activeEditor . commands . removeComment ({
commentId: "comment-123" ,
});
Highlight and focus a comment.
superdoc . activeEditor . commands . setActiveComment ({
commentId: "comment-123" ,
});
superdoc . activeEditor . commands . resolveComment ({
commentId: "comment-123" ,
});
Toggle a comment between internal and external visibility.
superdoc . activeEditor . commands . setCommentInternal ({
commentId: "comment-123" ,
isInternal: true ,
});
setCursorById
Navigate the cursor to a comment’s position in the document.
superdoc . activeEditor . commands . setCursorById ( "comment-123" );
Events
Fired for all comment changes.
Event type: pending, add, update, deleted, resolved, selected, change-accepted, or change-rejected
onCommentsUpdate : ({ type , comment , meta }) => {
switch ( type ) {
case 'add' :
await saveComment ( comment );
break ;
case 'resolved' :
await markResolved ( comment . id );
break ;
}
}
Core Parent comment ID for threaded replies
Author Position Position data including selectionBounds, page, and documentId
State Internal/external flag (when dual comments enabled)
Track Changes Whether this is a tracked change comment
'trackInsert', 'trackDelete', 'trackFormat', or 'both'
The text content of the tracked change
The deleted text (for delete tracked changes)
Import Original Word comment ID (from DOCX import)
Original author info (from DOCX import)