Adds collaborative review comments on blocks or the whole document. Reviewers leave feedback; authors resolve or reopen threads. Integrates with history, versions, and the minimap.
Use the toolbar, context, or control bar button to add a comment on the current selection or document. Set role to reviewer or author to control who can create and resolve comments.
<script src="/assets/redactor/redactor.js"></script>
<script src="/assets/redactor/plugins/review/review.js"></script>
const app = Redactor('#entry', {
plugins: ['review'],
review: {
role: 'reviewer',
user: {
id: '1',
name: 'Alex',
avatar: '/assets/avatar.jpg'
}
}
});
string)
string)
object | false)
falseload.'reviewer' | 'author')
'reviewer'object | null)
null{ id, name, avatar? } attached to new comments.boolean)
truefalse, enables blockUid on the editor for stable block references.boolean)
falseboolean)
falsetrue, author Resolve immediately accepts and archives (skips reviewer approval).Redactor('#entry', {
plugins: ['review'],
blockUid: true,
review: {
role: 'author',
user: { id: '2', name: 'Kate' },
reviews: {
abc123: {
id: 'abc123',
scope: 'blocks',
status: 'open',
blockUids: ['blk001'],
comment: {
text: 'Please clarify this paragraph.',
author: { id: '1', name: 'Alex' },
createdAt: '2026-06-10T09:00:00.000Z'
}
}
}
}
});
en: {
review: {
comment: 'Review comment',
'add-comment': 'Add review comment',
'comment-placeholder': 'Write a comment for the author…',
save: 'Save',
cancel: 'Cancel',
delete: 'Delete comment',
edit: 'Edit',
resolve: 'Resolve',
reopen: 'Reopen',
accept: 'Accept',
resolved: 'Resolved',
original: 'Original'
}
}
Fired when a new review comment is saved.
Payload: id, review.
app.on('review:created', ({ id, review }) => {
console.log('review created', id, review.status, review.blockUids);
});
Fired when an existing review comment is updated.
Payload: id, review.
app.on('review:updated', ({ id, review }) => {
console.log('comment updated', id, review.comment.text);
});
Fired when the author resolves a review.
Payload: id, review.
app.on('review:resolved', ({ id, review }) => {
console.log('resolved', id, review.versions);
});
Fired when the author reopens a resolved review.
Payload: id, review.
app.on('review:reopened', ({ id, review }) => {
console.log('reopened', id, review.status);
});
Fired when the reviewer accepts a resolved review.
Payload: id, review.
app.on('review:accepted', ({ id, review }) => {
console.log('accepted', id, review.status);
});
Fired when a review is deleted.
Payload: id.
app.on('review:deleted', ({ id }) => {
console.log('review deleted', id);
});
Fired when the current role changes.
Payload: role ('reviewer' or 'author').
app.on('review:role', ({ role }) => {
console.log('role switched to', role);
});
Fired after any review mutation (create, update, delete, resolve, accept, reopen).
Payload: reviews — full store snapshot (includes archived).
app.on('reviews:change', ({ reviews }) => {
const open = Object.values(reviews).filter((r) => r.status === 'open');
console.log('open reviews', open.length);
});
Fired when reviews are loaded into the store (initial reviews option or setReviews with merge: true).
Payload: reviews.
app.on('reviews:load', ({ reviews }) => {
console.log('reviews loaded', Object.keys(reviews).length);
});
Returns the review store.
Parameters:
includeArchived (boolean) — default true.const all = app.review.getReviews();
const active = app.review.getReviews({ includeArchived: false });
Replaces the review store.
app.review.setReviews({ abc123: { /* … */ } });
Returns the current role ('reviewer' or 'author').
const role = app.review.getRole();
Switches between reviewer and author.
app.review.setRole('author');
Opens the review creation flow for the current selection or document scope.
app.review.create();