Custom sidebar

TinyMCE allows developers to create sidebars and add custom UI widgets inside a constrained and easily accessible area of the editor. The sidebar is designed to allow administrators and plugin developers to provide additional tools that can be accessed by TinyMCE users.

This feature is only supported when TinyMCE is run in classic mode. It is not supported in inline mode. For more information on the differences between the editing modes, see Classic editing mode.

Editor sidebar API

The sidebar API allows developers to add sidebars on editor instances in a similar way as adding buttons or menu items. Developers can either add sidebars directly in the tinymce.init using the setup callback or inside your plugin.

This is the syntax for the addSidebar function: editor.ui.registry.addSidebar(name:String, spec:Object)

When a new sidebar is registered, a corresponding toolbar button for toggling the sidebar open and close is also created using the same name. This button can then be included in the toolbar by adding the sidebar name to the toolbar option.

Specification object

tooltip

The tooltip specifies a tooltip to be displayed when hovering over the sidebar toggle button.

Type: String

icon

The icon specifies an icon for the sidebar toggle button. The icon should be the name of an icon provided by the TinyMCE skin or a custom icon.

Type: String

resizable

The resizable specifies whether a user can resize the sidebar by dragging the edge of the sidebar. The default is false.

This feature is only available for TinyMCE 8.9 and later.

When set to true, TinyMCE renders a resize handle and controls the width of the sidebar using the sidebar_width, sidebar_min_width, and sidebar_max_width options. The content of a sidebar registered with resizable set to true needs to follow the width of the parent element. For information, see: Styling a resizable sidebar.

When resizable is omitted or set to false, TinyMCE does not render a resize handle, ignores the three sidebar width options, and renders the sidebar at the width defined by the content styles of that sidebar.

Type: Boolean

onSetup

The onSetup specifies a function to be called when the panel is first created. It passes in an API object and should return a callback that takes an API. The default is (api) => (api) => {}.

onSetup is a complex property. It requires a function that takes the sidebar’s API and should return a callback that takes the sidebar’s API and returns nothing. This occurs because onSetup runs whenever the sidebar is rendered, and the returned callback is executed when the sidebar is destroyed. Therefore the returned function is essentially an onTeardown handler, and can be used to unbind events and callbacks.

Type: Function

onShow

The onShow specifies a function to be called when the panel displayed. It passes in an API object.

Type: Function

onHide

The onHide specifies a function to be called when the panel is hidden. It passes in an API object.

Type: Function

API Object

element():HTMLElement

The element():HTMLElement function returns the root element of the sidebar panel.

Resizable sidebars

This feature is only available for TinyMCE 8.9 and later.

A user can resize a sidebar by dragging the edge of the sidebar toward or away from the editable area. TinyMCE renders a resize handle only for sidebars registered with the resizable property set to true.

The sidebars registered by the Comments and TinyMCE AI plugins are resizable by default. Sidebars registered through addSidebar are not resizable by default, so a custom sidebar created before TinyMCE 8.9 renders as it did previously.

The sidebar_width, sidebar_min_width, and sidebar_max_width options apply to every resizable sidebar in an editor. TinyMCE cannot set a separate width for an individual sidebar.

Styling a resizable sidebar

The content styles of a sidebar that is not resizable determine how wide the sidebar renders.

tinymce.init({
  selector: 'textarea', // change this value according to your HTML
  sidebar_show: 'mysidebar',
  setup: (editor) => {
    editor.ui.registry.addSidebar('mysidebar', {
      tooltip: 'My sidebar',
      icon: 'comment',
      onShow: (api) => {
        const container = document.createElement('div');
        container.style.width = '600px';
        api.element().appendChild(container);
      },
    });
  }
});

TinyMCE sets the width of a resizable sidebar, so the content styles need to follow the width of the parent element rather than set a width. Set the width of the content to 100% so that the content inherits the width from api.element().

tinymce.init({
  selector: 'textarea', // change this value according to your HTML
  sidebar_show: 'mysidebar',
  sidebar_width: 500,
  setup: (editor) => {
    editor.ui.registry.addSidebar('mysidebar', {
      tooltip: 'My sidebar',
      icon: 'comment',
      resizable: true,
      onShow: (api) => {
        const container = document.createElement('div');
        container.style.width = '100%';
        api.element().appendChild(container);
      },
    });
  }
});
A sidebar whose content styles set a fixed width does not render correctly when resizable is set to true. Update the content styles to 100% before enabling the property.

Persisting the sidebar width

TinyMCE does not store the width a user drags a sidebar to. To keep a width between editor loads, store the width reported by the SidebarResized event and pass the stored value to sidebar_width when the editor is next created.

const storedWidth = window.localStorage.getItem('sidebar-width');

tinymce.init({
  selector: 'textarea', // change this value according to your HTML
  sidebar_show: 'mysidebar',
  sidebar_width: storedWidth ? parseInt(storedWidth, 10) : 440,
  setup: (editor) => {
    editor.ui.registry.addSidebar('mysidebar', {
      tooltip: 'My sidebar',
      icon: 'comment',
      resizable: true,
      onShow: (api) => {
        const container = document.createElement('div');
        container.style.width = '100%';
        api.element().appendChild(container);
      },
    });

    editor.on('SidebarResized', (e) => {
      window.localStorage.setItem('sidebar-width', e.width);
    });
  }
});

Options

This option sets the largest width, in pixels, that a user can drag the sidebar to.

The option applies only to sidebars registered with the resizable property set to true. A user cannot resize a sidebar registered without that property, and TinyMCE ignores this option.

This option restricts dragging only. This option does not restrict the width set by sidebar_width, so a sidebar can open wider than the value set here.

This feature is only supported when TinyMCE is run in classic mode. It is not supported in inline mode. For more information on the differences between the editing modes, see Classic editing mode.

Type: Number

Default value: 800

Example: using sidebar_max_width

tinymce.init({
  selector: 'textarea', // change this value according to your HTML
  sidebar_show: 'mysidebar',
  sidebar_max_width: 600,
  setup: (editor) => {
    editor.ui.registry.addSidebar('mysidebar', {
      tooltip: 'My sidebar',
      icon: 'comment',
      resizable: true,
      onShow: (api) => {
        api.element().innerHTML = 'Hello world!';
      },
    });
  }
});

Limitations of the sidebar_max_width option

The editable area cannot shrink below 280 pixels, and this limit takes precedence over sidebar_max_width. For information on this restriction, see: Limitations of the sidebar_width option.

In a narrow editor, the width that remains beside a 280-pixel editable area can be smaller than the value set by sidebar_max_width. In that case, the remaining width becomes the effective maximum, and a user cannot drag the sidebar beyond that width.

This option sets the smallest width, in pixels, that a user can drag the sidebar to.

The option applies only to sidebars registered with the resizable property set to true. A user cannot resize a sidebar registered without that property, and TinyMCE ignores this option.

This option restricts dragging only. This option does not restrict the width set by sidebar_width, so a sidebar can open narrower than the value set here.

This feature is only supported when TinyMCE is run in classic mode. It is not supported in inline mode. For more information on the differences between the editing modes, see Classic editing mode.

Type: Number

Default value: 300

Example: using sidebar_min_width

tinymce.init({
  selector: 'textarea', // change this value according to your HTML
  sidebar_show: 'mysidebar',
  sidebar_min_width: 400,
  setup: (editor) => {
    editor.ui.registry.addSidebar('mysidebar', {
      tooltip: 'My sidebar',
      icon: 'comment',
      resizable: true,
      onShow: (api) => {
        api.element().innerHTML = 'Hello world!';
      },
    });
  }
});

Limitations of the sidebar_min_width option

The editable area cannot shrink below 280 pixels, and this limit takes precedence over sidebar_min_width. For information on this restriction, see: Limitations of the sidebar_width option.

When the editor is too narrow to provide the width set by sidebar_min_width alongside a 280-pixel editable area, TinyMCE does not resize the sidebar on drag, and the sidebar keeps the current width.

This option allows the specified sidebar to be shown on editor initialization.

This feature is only supported when TinyMCE is run in classic mode. It is not supported in inline mode. For more information on the differences between the editing modes, see Classic editing mode.

Type: String

Example: using sidebar_show

tinymce.init({
  selector: 'textarea', // change this value according to your HTML
  sidebar_show: 'mysidebar',
  setup: (editor) => {
    editor.ui.registry.addSidebar('mysidebar', {
      tooltip: 'My sidebar',
      icon: 'comment',
      onShow: (api) => {
        api.element().innerHTML = 'Hello world!';
      },
    });
  }
});

This option sets the width, in pixels, that the sidebar opens at on editor initialization.

The option applies only to sidebars registered with the resizable property set to true. A sidebar registered without that property keeps the width defined by the content styles of that sidebar, and TinyMCE ignores this option.

The sidebar_min_width and sidebar_max_width options do not restrict the width set by this option. Those options restrict only the widths a user can drag the sidebar to. The minimum width of the editable area does restrict this width. For information on this restriction, see: Limitations of the sidebar_width option.

This feature is only supported when TinyMCE is run in classic mode. It is not supported in inline mode. For more information on the differences between the editing modes, see Classic editing mode.

Type: Number

Default value: 440

Example: using sidebar_width

tinymce.init({
  selector: 'textarea', // change this value according to your HTML
  sidebar_show: 'mysidebar',
  sidebar_width: 500,
  setup: (editor) => {
    editor.ui.registry.addSidebar('mysidebar', {
      tooltip: 'My sidebar',
      icon: 'comment',
      resizable: true,
      onShow: (api) => {
        api.element().innerHTML = 'Hello world!';
      },
    });
  }
});

Limitations of the sidebar_width option

The editable area and the sidebar share the same container. To keep the editable area usable, TinyMCE does not allow the editable area to shrink below 280 pixels. This limit is fixed and takes precedence over sidebar_width, sidebar_min_width, and sidebar_max_width.

When the editor is too narrow to provide the requested width alongside a 280-pixel editable area, TinyMCE reduces the sidebar to the width that remains. For example, in an editor 1000 pixels wide, a sidebar_width of 2000 results in a sidebar approximately 716 pixels wide, because the editable area reserves 280 pixels and the editor border occupies the remaining pixels.

Example inside the tinymce.init

tinymce.init({
  ...
  toolbar: 'mysidebar',
  setup: (editor) => {
    editor.ui.registry.addSidebar('mysidebar', {
      tooltip: 'My sidebar',
      icon: 'comment',
      onSetup: (api) => {
        console.log('Render panel', api.element());
        return () => {
          console.log('Removing sidebar');
        };
      },
      onShow: (api) => {
        console.log('Show panel', api.element());
        api.element().innerHTML = 'Hello world!';
      },
      onHide: (api) => {
        console.log('Hide panel', api.element());
      }
    });
  }
});

Example inside a TinyMCE plugin

tinymce.PluginManager.add('myplugin', (editor) => {
  editor.ui.registry.addSidebar('mysidebar', {
    tooltip: 'My sidebar',
    icon: 'comment',
    onSetup: (api) => {
      console.log('Render panel', api.element());
      return () => {
        console.log('Removing sidebar');
      };
    },
    onShow: (api) => {
      console.log('Show panel', api.element());
      api.element().innerHTML = 'Hello world!';
    },
    onHide: (api) => {
      console.log('Hide panel', api.element());
    }
  });
});