Review

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.

Load the bundle

<script src="/assets/redactor/redactor.js"></script>
<script src="/assets/redactor/plugins/review/review.js"></script>

Initialization

const app = Redactor('#entry', {
    plugins: ['review'],
    review: {
        role: 'reviewer',
        user: {
            id: '1',
            name: 'Alex',
            avatar: '/assets/avatar.jpg'
        }
    }
});

Options

  • icon (string)
    • SVG icon for toolbar, context, and control buttons.
  • iconEdit, iconResolve (string)
    • Icons used inside review UI controls.
  • reviews (object | false)
    • default false
    • Initial review store keyed by review id. Loaded on plugin load.
  • role ('reviewer' | 'author')
    • default 'reviewer'
    • Current user role. Reviewers create comments; authors resolve and reopen.
  • user (object | null)
    • default null
    • Current user { id, name, avatar? } attached to new comments.
  • blockUid (boolean)
    • default true
    • When not false, enables blockUid on the editor for stable block references.
  • exportArchived (boolean)
    • default false
    • Include archived reviews in exports when enabled.
  • autoAcceptOnResolve (boolean)
    • default false
    • When true, 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'
                }
            }
        }
    }
});

Language strings

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'
    }
}

Events

review:created

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);
});

review:updated

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);
});

review:resolved

Fired when the author resolves a review.

Payload: id, review.

app.on('review:resolved', ({ id, review }) => {
    console.log('resolved', id, review.versions);
});

review:reopened

Fired when the author reopens a resolved review.

Payload: id, review.

app.on('review:reopened', ({ id, review }) => {
    console.log('reopened', id, review.status);
});

review:accepted

Fired when the reviewer accepts a resolved review.

Payload: id, review.

app.on('review:accepted', ({ id, review }) => {
    console.log('accepted', id, review.status);
});

review:deleted

Fired when a review is deleted.

Payload: id.

app.on('review:deleted', ({ id }) => {
    console.log('review deleted', id);
});

review:role

Fired when the current role changes.

Payload: role ('reviewer' or 'author').

app.on('review:role', ({ role }) => {
    console.log('role switched to', role);
});

reviews:change

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);
});

reviews:load

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);
});

API

getReviews

Returns the review store.

Parameters:

  • includeArchived (boolean) — default true.
const all = app.review.getReviews();
const active = app.review.getReviews({ includeArchived: false });

setReviews

Replaces the review store.

app.review.setReviews({ abc123: { /* … */ } });

getRole

Returns the current role ('reviewer' or 'author').

const role = app.review.getRole();

setRole

Switches between reviewer and author.

app.review.setRole('author');

create

Opens the review creation flow for the current selection or document scope.

app.review.create();