Report an issue

guideUsers

# Users API

Users API is used by multiple collaboration plugins. Collaboration consists of working on the same document by multiple users, so information about these users needs to be stored in the editor. The comments feature needs to have comment authors defined and real-time collaborative features require the users plugin to handle collaborative users.

CKEditor 5 provides a special plugin to handle its users. The Users plugin will be provided if you load any plugins that require its API and will be available as:

const usersPlugin = editor.plugins.get( 'Users' );

The Users plugin provides the basic interface for setting and getting users.

/**
 * A reference to the currently connected user.
 *
 * @readonly
 * @type {Object}
 */
me

/**
 * An iterable list of all users added to the editor.
 *
 * @readonly
 * @type {Collection}
 */
users

/**
 * Adds a new user to the list of the editor users.
 *
 * @param userData {Object}
 * @returns {User}
 */
addUser( userData ) {}

/**
 * Returns the user with a given ID.
 *
 * @param {String} id
 * @returns {Object}
 */
getUser( id ) {}

/**
 * Sets the user with a given ID as a Users#me.
 *
 * @param userData {Object}
 * @returns {User}
 */
defineMe( userData ) {}

/**
 * Returns the author of the operation.
 * See the "Operation authors" section below.
 *
 * @public
 * @param operation {Operation}
 *
 * @returns {User|null}
*/
getOperationAuthor( operation ) {}

For instance:

for ( const user of editor.plugins.get( 'Users' ).users ) {
    console.log( user.name );
}

Check the Collection API to see how to use the #users collection.

# Users#me

A reference to the currently connected user. Do not forget to set it using defineMe(), for example:

const usersPlugin = editor.plugins.get( 'Users' );

usersPlugin.addUser( {
    id: 'user-id',
    name: 'John Smith'
} );

usersPlugin.defineMe( 'user-id' );

Most of the collaboration plugins need this property to be defined.

Note that the real-time collaborative editing plugin will define it automatically based on your token data.

# Operation authors

The Users#getOperationAuthor() method gives you an ability to check which user created a given operation. This is useful when creating custom features in integrations using real-time collaboration.

There are two cases when the operation author might be null:

  1. For initial operations (fetched from the server when connecting).
  2. For some automatically created operations which are not meaningful (NoOperations).

Below is an example of using getOperationAuthor() to find out which user was the last to edit the document. Note that in this case you should skip NoOperations and some MarkerOperations since they do not affect the document content.

let lastUser = null;

editor.model.on( 'applyOperation', ( evt, args ) => {
    const users = editor.plugins.get( 'Users' );
    const operation = args[ 0 ];

    if ( operation.isDocumentOperation && affectsData( operation ) ) {
        const user = users.getOperationAuthor( operation );

        if ( user && user != lastUser ) {
            lastUser = user;

            console.log( lastUser.name, lastUser, operation );
        }
    }

    function affectsData( operation ) {
        return operation.type != 'noop' && ( operation.type != 'marker' || operation.affectsData );
    }
} );

# User object

A single user is represented by the following object:

{
    /**
     * The ID of the user.
     *
     * @type {String}
     */
    id

    /**
     * The name of the user.
     *
     * @type {String}
     */
    name

    /**
     * The initials of the user.
     * When the name is `Joe Doe`, the initials are `JD`.
     *
     * @type {String}
     */
    initials

    /**
     * The avatar URL of the user.
     *
     * @type {String|undefined}
     */
    avatar

    /**
     * Is `true` when the user name is not provided and it is
     * automatically set as `Anonymous`, `false` otherwise.
     *
     * @type {Boolean}
     */
    isAnonymous

    /**
     * The color object used to generate specified CSS classes
     * with an individual color number assigned to the user.
     * See the "Theme customization" section to know how to change
     * the user colors.
     */
    color: {
        /**
         * Returns `ck-user__bg-color--${ number }` where the number is
         * an individual color number assigned to the user.
         *
         * @returns {String}
         */
        getBackgroundColorClass() {}

        /**
         * Returns `ck-user__selection--${ number }` where the number is
         * an individual color number assigned to the user.
         *
         * @returns {String}
         */
        getSelectionClass() {}

        /**
         * Returns `ck-user__marker--${ number }` where the number is
         * an individual color number assigned to the user.
         *
         * @returns {String}
         */
        getMarkerClass() {}
    }
}

# Theme customization

It is possible to define colors used to represent the selection of other users.

By default, 8 colors are defined for users. Like in the whole CKEditor 5 Ecosystem PostCSS is used to handle styles with the power of CSS Variables. With Inheritance of CSS Variables you can change the default colors.

A color with an alpha channel (--ck-user-colors--$(number)-alpha) is dedicated for selections (.ck .ck-user__selection--$(number)). The rest of the classes use colors defined as --ck-user-colors--$(number). Feel free to change this color palette to fit your UI.

/* The current color set for users in the collaboration plugins. */
:root {
    --ck-user-colors--0: hsla(235, 73%, 67%, 1);
    --ck-user-colors--0-alpha: hsla(235, 73%, 67%, 0.15);

    --ck-user-colors--1: hsla(173, 100%, 24%, 1);
    --ck-user-colors--1-alpha: hsla(173, 100%, 24%, 0.15);

    --ck-user-colors--2: hsla(0, 46%, 50%, 1);
    --ck-user-colors--2-alpha: hsla(0, 46%, 50%, 0.15);

    --ck-user-colors--3: hsla(256, 54%, 45%, 1);
    --ck-user-colors--3-alpha: hsla(256, 54%, 45%, 0.15);

    --ck-user-colors--4: hsla(95, 50%, 36%, 1);
    --ck-user-colors--4-alpha: hsla(95, 50%, 36%, 0.15);

    --ck-user-colors--5: hsla(336, 78%, 43%, 1);
    --ck-user-colors--5-alpha: hsla(336, 78%, 43%, 0.15);

    --ck-user-colors--6: hsla(0, 80%, 59%, 1);
    --ck-user-colors--6-alpha: hsla(0, 80%, 59%, 0.15);

    --ck-user-colors--7: hsla(184, 90%, 43%, 1);
    --ck-user-colors--7-alpha: hsla(184, 90%, 43%, 0.15);
}

These colors are, among other, used in the users presence list to represent users.

# Adding more user colors

You can define additional colors for users if you find the default set too small.

First, prepare a CSS file with additional color definitions:

// mycolors.css

/* Import the "userColor" mixin to create definitions easily. */
@import "@ckeditor/ckeditor5-collaboration-core/theme/usercolormixin.css";

/**
 * Add some new definitions. The parameters for the "userColor" mixin are:
 *
 * - color without alpha channel (main color),
 * - color with alpha channel (selection marker color),
 * - color ordering number.
 */
@mixin userColor hsla(31, 90%, 43%, 1), hsla(31, 90%, 43%, 0.15), 8;
@mixin userColor hsla(61, 90%, 43%, 1), hsla(61, 90%, 43%, 0.15), 9;

Then, import the above CSS file and specify the colorsCount configuration option:

import './mycolors.css';

ClassicEditor.create( document.querySelector( '#editor' ), {
    // ...
    users: {
        colorsCount: 10
    }
} );