Features
- Text Comments: Add comments as text marks with inline annotations
- Overlapping Comments: Support multiple comments on the same text
- Draft Comments: Create draft comments before finalizing
- State Tracking: Track comment state and user interactions
- Discussion Integration: Works with discussion plugin for complete collaboration
Kit Usage
Installation
The fastest way to add comment functionality is with the CommentKit
, which includes pre-configured commentPlugin
and related components along with their Plate UI components.
CommentLeaf
: Renders comment text marksBlockDiscussion
: Renders discussion UI with comments integration
Add Kit
import { createPlateEditor } from 'platejs/react';
import { CommentKit } from '@/components/editor/plugins/comment-kit';
const editor = createPlateEditor({
plugins: [
// ...otherPlugins,
...CommentKit,
],
});
Manual Usage
Installation
pnpm add @platejs/comment
Extend Comment Plugin
Create the comment plugin with extended configuration for state management:
import {
type ExtendConfig,
type Path,
isSlateString,
} from 'platejs';
import {
type BaseCommentConfig,
BaseCommentPlugin,
getDraftCommentKey,
} from '@platejs/comment';
import { toTPlatePlugin } from 'platejs/react';
import { CommentLeaf } from '@/components/ui/comment-node';
type CommentConfig = ExtendConfig<
BaseCommentConfig,
{
activeId: string | null;
commentingBlock: Path | null;
hoverId: string | null;
uniquePathMap: Map<string, Path>;
}
>;
export const commentPlugin = toTPlatePlugin<CommentConfig>(
BaseCommentPlugin,
({ editor }) => ({
options: {
activeId: null,
commentingBlock: null,
hoverId: null,
uniquePathMap: new Map(),
},
render: {
node: CommentLeaf,
},
})
);
options.activeId
: Currently active comment ID for visual highlightingoptions.commentingBlock
: Path of the block currently being commentedoptions.hoverId
: Currently hovered comment ID for hover effectsoptions.uniquePathMap
: Map tracking unique paths for comment resolutionrender.node
: AssignsCommentLeaf
to render comment text marks
Add Click Handler
Add click handling to manage active comment state:
export const commentPlugin = toTPlatePlugin<CommentConfig>(
BaseCommentPlugin,
({ editor }) => ({
handlers: {
// Set active comment when clicking on comment marks
onClick: ({ api, event, setOption, type }) => {
let leaf = event.target as HTMLElement;
let isSet = false;
const unsetActiveComment = () => {
setOption('activeId', null);
isSet = true;
};
if (!isSlateString(leaf)) unsetActiveComment();
while (leaf.parentElement) {
if (leaf.classList.contains(`slate-${type}`)) {
const commentsEntry = api.comment.node();
if (!commentsEntry) {
unsetActiveComment();
break;
}
const id = api.comment.nodeId(commentsEntry[0]);
setOption('activeId', id ?? null);
isSet = true;
break;
}
leaf = leaf.parentElement;
}
if (!isSet) unsetActiveComment();
},
},
// ... previous options and render
})
);
The click handler tracks which comment is currently active:
- Detects comment clicks: Traverses DOM to find comment elements
- Sets active state: Updates
activeId
when clicking on comments - Clears state: Unsets
activeId
when clicking outside comments - Visual feedback: Enables hover/active styling in comment components
Extend Transforms
Extend the setDraft
transform for enhanced functionality:
export const commentPlugin = toTPlatePlugin<CommentConfig>(
BaseCommentPlugin,
({ editor }) => ({
// ... previous configuration
})
)
.extendTransforms(
({
editor,
setOption,
tf: {
comment: { setDraft },
},
}) => ({
setDraft: () => {
if (editor.api.isCollapsed()) {
editor.tf.select(editor.api.block()![1]);
}
setDraft();
editor.tf.collapse();
setOption('activeId', getDraftCommentKey());
setOption('commentingBlock', editor.selection!.focus.path.slice(0, 1));
},
})
)
.configure({
node: { component: CommentLeaf },
shortcuts: {
setDraft: { keys: 'mod+shift+m' },
},
});
Add Toolbar Button
You can add CommentToolbarButton
to your Toolbar to add comments on selected text.
Add Plugins
import { createPlateEditor } from 'platejs/react';
const editor = createPlateEditor({
plugins: [
// ...otherPlugins,
commentPlugin,
],
});
Discussion Integration
The comment plugin works with the discussion plugin for complete collaboration:
import { discussionPlugin } from '@/components/editor/plugins/discussion-kit';
const editor = createPlateEditor({
plugins: [
// ...otherPlugins,
discussionPlugin,
commentPlugin,
],
});
Keyboard Shortcuts
Key | Description |
---|---|
Cmd + Shift + M | Add a comment on the selected text. |
Plate Plus
Plugins
CommentPlugin
Plugin for creating and managing text comments with state tracking and discussion integration.
activeId string | null
Currently active comment ID for visual highlighting. Used internally to track state.
commentingBlock Path | null
Path of the block currently being commented on.
hoverId string | null
Currently hovered comment ID for hover effects.
uniquePathMap Map<string, Path>
Map tracking unique paths for comment resolution.
API
api.comment.has
Checks if a comment with the given ID exists in the editor.
api.comment.node
Gets a comment node entry.
api.comment.nodeId
Gets the ID of a comment from a leaf node.
api.comment.nodes
Gets all comment node entries matching the options.
Transforms
tf.comment.removeMark
Removes the comment mark from the current selection or a specified location.
tf.comment.setDraft
Sets a draft comment mark at the current selection.
tf.comment.unsetMark
Unsets comment nodes with the specified ID from the editor.
Utilities
getCommentCount
Gets the count of non-draft comments in a comment node.
getCommentKey
Generates a comment key based on the provided ID.
getCommentKeyId
Extracts the comment ID from a comment key.
getCommentKeys
Returns an array of comment keys present in the given node.
getDraftCommentKey
Gets the key used for draft comments.
isCommentKey
Checks if a given key is a comment key.
isCommentNodeById
Checks if a given node is a comment with the specified ID.
Types
TCommentText
Text nodes that can contain comments.
On This Page
FeaturesKit UsageInstallationAdd KitManual UsageInstallationExtend Comment PluginAdd Click HandlerExtend TransformsAdd Toolbar ButtonAdd PluginsDiscussion IntegrationKeyboard ShortcutsPlate PlusPluginsCommentPlugin
APIapi.comment.has
api.comment.node
api.comment.nodeId
api.comment.nodes
Transformstf.comment.removeMark
tf.comment.setDraft
tf.comment.unsetMark
UtilitiesgetCommentCount
getCommentKey
getCommentKeyId
getCommentKeys
getDraftCommentKey
isCommentKey
isCommentNodeById
TypesTCommentText