---
title: "Types of toolbar buttons"
description: "This section demonstrates different types of toolbar buttons."
canonical_url: "https://www.tiny.cloud/docs/tinymce/5/typesoftoolbarbuttons/"
md_url: "https://www.tiny.cloud/docs/tinymce/5/typesoftoolbarbuttons/index.md"
version: "5"
last_updated: "2024-04-09T09:35:32Z"
tokens: 5441
---
Important This page documents TinyMCE 5. For new projects, Tiny recommends using the latest, most up-to-date version. [See TinyMCE 8 documentation](../../latest/).
# Types of toolbar buttons

There are four types of Toolbar Buttons in TinyMCE 5:

- [Basic button](#basicbutton)
- [Toggle button](#togglebutton)
- [Menu button](#menubutton)
- [Split button](#splitbutton)
- [Group toolbar button](#grouptoolbarbutton)

## Basic button

A basic button triggers its `onAction` function when clicked.

### Config options

| Name | Value | Requirement | Description |
| --- | --- | --- | --- |
| text | string | optional | Text to display if no icon is found. |
| icon | string | optional | Name of the icon to be displayed. Must correspond to an icon: in the [icon pack](../editor-icon-identifiers/), in a [custom icon pack](../creating-an-icon-pack/), or added using the [`addIcon` API](../apis/tinymce.editor.ui.registry/#addIcon). |
| tooltip | string | optional | Text for button tooltip. |
| disabled | boolean | optional | default: false - Represents the button’s state. When true, button is unclickable. Toggled by the button’s API. |
| onSetup | `(api) ⇒ (api) ⇒ void` | optional | default: `() ⇒ () ⇒ {}` - Function invoked when the button is rendered. |
| onAction | `(api) ⇒ void` | required | Function invoked when the button is clicked. |

> **Note:** See [below](#onsetupexplanation) for details on how to configure `onSetup`.

### API

| Name | Value | Description |
| --- | --- | --- |
| isDisabled | `() ⇒ boolean` | Checks if the button is disabled. |
| setDisabled | `(state: boolean) ⇒ void` | Sets the button’s disabled state. |

### Basic button example and explanation

The following example adds two buttons to the toolbar:

**Example**

```js
tinymce.init({
  selector: 'textarea#custom-toolbar-button',
  toolbar: 'customInsertButton customDateButton',
  setup: function (editor) {

    editor.ui.registry.addButton('customInsertButton', {
      text: 'My Button',
      onAction: function (_) {
        editor.insertContent('&nbsp;<strong>It\'s my button!</strong>&nbsp;');
      }
    });

    var toTimeHtml = function (date) {
      return '<time datetime="' + date.toString() + '">' + date.toDateString() + '</time>';
    };

    editor.ui.registry.addButton('customDateButton', {
      icon: 'insert-time',
      tooltip: 'Insert Current Date',
      disabled: true,
      onAction: function (_) {
        editor.insertContent(toTimeHtml(new Date()));
      },
      onSetup: function (buttonApi) {
        var editorEventCallback = function (eventApi) {
          buttonApi.setDisabled(eventApi.element.nodeName.toLowerCase() === 'time');
        };
        editor.on('NodeChange', editorEventCallback);

        /* onSetup should always return the unbind handlers */
        return function (buttonApi) {
          editor.off('NodeChange', editorEventCallback);
        };
      }
    });
  },
  content_style: 'body { font-family:Helvetica,Arial,sans-serif; font-size:14px }'
});
```
The first button inserts "It’s my button!" into the editor when clicked. The second button is an example of how `onSetup` works. This button inserts a `time` element containing the current date into the editor using a `toTimeHtml()` helper function - a simplified version of TinyMCE’s [insertdatetime](../insertdatetime/) plugin.

In this example an icon from the `insertdatetime` plugin is used to demonstrate how to use a registered icon. `disabled` is set to `true` so that the button is disabled when it is first rendered.

`onSetup` is used to listen to the editor’s [`NodeChange` event](../events/#editorcoreevents) to disable the button when the cursor is inside a `time` element (or "node"). This ensures it is not possible to insert a `time` element into another `time` element.

## Toggle button

A toggle button triggers an action when clicked but also has a concept of state. This means it can be toggled `on` and `off`. A toggle button gives the user visual feedback for its state through CSS styling. An example of this behavior is the **Bold** button that is highlighted when the cursor is in a word with bold formatting.

### Config options

| Name | Value | Requirement | Description |
| --- | --- | --- | --- |
| text | string | optional | Text to display if no icon is found. |
| icon | string | optional | Name of the icon to be displayed. Must correspond to an icon: in the [icon pack](../editor-icon-identifiers/), in a [custom icon pack](../creating-an-icon-pack/), or added using the [`addIcon` API](../apis/tinymce.editor.ui.registry/#addIcon). |
| tooltip | string | optional | Text for button tooltip. |
| disabled | boolean | optional | default: false - Represents the button’s state. When true, button is unclickable. Toggled by the button’s API. |
| active | boolean | optional | default: false - Represents the button’s state. When true, button is highlighted. Toggled by the button’s API. |
| onSetup | `(api) ⇒ (api) ⇒ void` | optional | default: `() ⇒ () ⇒ {}` - Function invoked when the button is rendered. |
| onAction | `(api) ⇒ void` | required | Function invoked when the button is clicked. |

> **Note:** See [below](#onsetupexplanation) for details on how to configure `onSetup`.

### API

| Name | Value | Description |
| --- | --- | --- |
| isDisabled | `() ⇒ boolean` | Checks if a button is disabled. |
| setDisabled | `(state: boolean) ⇒ void` | Sets the button’s disabled state. |
| isActive | `() ⇒ boolean` | Checks if the button is `on`. |
| setActive | `(state: boolean) ⇒ void` | Sets the button’s toggle state. |

### Toggle button example and explanation

**Example**

```js
tinymce.init({
  selector: 'textarea#custom-toolbar-toggle-button',
  toolbar: 'customStrikethrough customToggleStrikethrough',
  setup: function (editor) {
    editor.ui.registry.addToggleButton('customStrikethrough', {
      text: 'Strikethrough',
      onAction: function (api) {
        editor.execCommand('mceToggleFormat', false, 'strikethrough');
        api.setActive(!api.isActive());
      }
    });

    editor.ui.registry.addToggleButton('customToggleStrikethrough', {
      icon: 'strike-through',
      onAction: function (_) {
        editor.execCommand('mceToggleFormat', false, 'strikethrough');
      },
      onSetup: function (api) {
        editor.formatter.formatChanged('strikethrough', function (state) {
          api.setActive(state);
        });
      }
    });
  },
  content_style: 'body { font-family:Helvetica,Arial,sans-serif; font-size:14px }'
});
```
The example above adds two custom **strikethrough** buttons with the same `onAction` configuration. The configuration uses `editor.execCommand(command, ui, args)` to execute `mceToggleFormat`. This editor method toggles the specified format on and off, but only works for [formats](../content-formatting/#formats) that are already registered with the editor. In this example, `strikethrough` is the registered format.

The first button applies and removes strikethrough formatting, and its state toggles on click using `api.setActive(!api.isActive())`. However, the expected behaviour is that the button’s state will reflect whether the selected content has strikethrough formatting. For example, if the cursor is moved into editor content that has strikethrough formatting the button will become **active** and if it is moved into content that does not have strikethrough formatting the button will become **inactive**. The first button in the example does not do this, since its state only toggles when the button is clicked.

To achieve this, the second button uses `onSetup` to register a callback for strikethrough content using `editor.formatter.formatChanged(formatName, callback)`. This method executes the specified callback function when the selected content has the specified formatting.

> **Note:** The format name given to `mceToggleFormat` via `editor.execCommand(command, ui, args)` and to `editor.formatter.formatChanged(formatName, callback)` is the same.
The callback given to `editor.formatter.formatChanged` is a function that takes a `state` boolean representing whether the currently selected content contains the applied format. This `state` boolean is used to set the button’s active state to match if the selected content has the specified formatting by using `api.setActive(state)` from the button’s API. This ensures the `customToggleStrikethrough` button is only **active** when the selected content contains the strikethrough formatting.

> **Note:** This feature is only available for TinyMCE 5.9 and later.
For formats that require variables, the `editor.formatter.formatChanged` function takes two extra arguments: `similar` and `vars`.

When the `similar` argument is `true`, similar formats will all be treated as the same by `formatChanged`. Similar formats are those with the same `formatName` but different variables. This argument will default to `false`.

The `vars` argument controls which variables are used to match the content when determining whether to run the callback. This argument is only used when `similar` is `false`.

## Menu button

A toolbar menu button is a toolbar button that opens a menu when clicked. This menu can also contain submenus. This is useful for grouping together actions that would otherwise be several buttons on the toolbar. It can also be used to reduce visual clutter and save UI space, as menubar menu items and some toolbar buttons could be moved into a toolbar menu button. Potentially, all menubar menu items could be moved into toolbar menu buttons, allowing for the editor to be used without a menubar at all.

For example: The table plugin’s `table` toolbar button opens a menu similar to the menubar Table menu.

### Config options

| Name | Value | Requirement | Description |
| --- | --- | --- | --- |
| fetch | `(success: (menu) ⇒ void) ⇒ void` | required | Function that takes a callback which must be passed the list of options for the button’s dropdown. |
| text | string | optional | Text to display if no icon is found. |
| icon | string | optional | Name of the icon to be displayed. Must correspond to an icon: in the [icon pack](../editor-icon-identifiers/), in a [custom icon pack](../creating-an-icon-pack/), or added using the [`addIcon` API](../apis/tinymce.editor.ui.registry/#addIcon). |
| tooltip | string | optional | Text for button tooltip. |
| onSetup | `(api) ⇒ (api) ⇒ void` | optional | default: `() ⇒ () ⇒ {}` - Function that’s invoked when the button is rendered. |

> **Note:** See [below](#onsetupexplanation) for details on how to configure `onSetup`.

### API

| Name | Value | Description |
| --- | --- | --- |
| isDisabled | `() ⇒ boolean` | Checks if the button is disabled. |
| setDisabled | `(state: boolean) ⇒ void` | Sets the button’s disabled state. |

### Menu button example and explanation

The following is a simple toolbar menu button example:

**Example**

```js
tinymce.init({
  selector: 'textarea#custom-toolbar-menu-button',
  height: 500,
  toolbar: 'mybutton',

  setup: function (editor) {
    /* Menu items are recreated when the menu is closed and opened, so we need
       a variable to store the toggle menu item state. */
    var toggleState = false;

    /* example, adding a toolbar menu button */
    editor.ui.registry.addMenuButton('mybutton', {
      text: 'My button',
      fetch: function (callback) {
        var items = [
          {
            type: 'menuitem',
            text: 'Menu item 1',
            onAction: function () {
              editor.insertContent('&nbsp;<em>You clicked menu item 1!</em>');
            }
          },
          {
            type: 'nestedmenuitem',
            text: 'Menu item 2',
            icon: 'user',
            getSubmenuItems: function () {
              return [
                {
                  type: 'menuitem',
                  text: 'Sub menu item 1',
                  icon: 'unlock',
                  onAction: function () {
                    editor.insertContent('&nbsp;<em>You clicked Sub menu item 1!</em>');
                  }
                },
                {
                  type: 'menuitem',
                  text: 'Sub menu item 2',
                  icon: 'lock',
                  onAction: function () {
                    editor.insertContent('&nbsp;<em>You clicked Sub menu item 2!</em>');
                  }
                }
              ];
            }
          },
          {
            type: 'togglemenuitem',
            text: 'Toggle menu item',
            onAction: function () {
              toggleState = !toggleState;
              editor.insertContent('&nbsp;<em>You toggled a menuitem ' + (toggleState ? 'on' : 'off') + '</em>');
            },
            onSetup: function (api) {
              api.setActive(toggleState);
              return function() {};
            }
          }
        ];
        callback(items);
      }
    });

  },
  content_style: 'body { font-family:Helvetica,Arial,sans-serif; font-size:14px }'
});
```
This example configures a toolbar menu button with the label `My Button` that opens the specified menu when clicked. The top-level menu contains two items. The first menu item inserts content when clicked and the second menu item opens a submenu containing two menu items which insert content when clicked.

The `fetch` function is called when the toolbar menu button’s menu is opened. It is a function that takes a callback and passes it an array of menu items to be rendered in the drop-down menu. This allows for asynchronous fetching of the menu items.

Use the following demo [here](../custom-menu-toolbar-button/) for help using the menu toolbar button.

## Split button

A split button contains a basic button and a menu button, wrapped up into one toolbar item. Clicking the menu button section opens a dropdown list. The basic button section and the menu items can be configured to trigger different actions when clicked.

### Config options

| Name | Value | Target component | Requirement | Description |
| --- | --- | --- | --- | --- |
| text | string | Primary button | optional | Text displayed if no icon is found. |
| icon | string | Primary button | optional | Name of the icon to be displayed. Must correspond to an icon: in the [icon pack](../editor-icon-identifiers/), in a [custom icon pack](../creating-an-icon-pack/), or added using the [`addIcon` API](../apis/tinymce.editor.ui.registry/#addIcon). |
| onAction | `(api) ⇒ void` | Primary button | required | Function invoked when the basic button section is clicked. |
| select | `(value: string) ⇒ boolean` | Choice menu items | optional | default: false - Function run on each option when the menu is opened to determine if it should be highlighted as active. |
| columns | number or `'auto'` | Drop-down menu | optional | default: 1 - Number of columns for the list of options. When set to more than 1 column, only the icon for each item will be shown. |
| fetch | `(success: (menu) ⇒ void) ⇒ void` | Drop-down menu | required | A callback function that should be passed a list of [choice menu items](#choicemenuitems) for the dropdown menu. |
| onItemAction | `(api, value) ⇒ void` | Choice menu items | required | Function invoked when a dropdown list option is clicked. The `value` is passed from the selected choice menu item. |
| onSetup | `(api) ⇒ (api) ⇒ void` | All | optional | default: `() ⇒ () ⇒ {}` - Function invoked when the button is rendered. |

> **Note:** See [below](#onsetupexplanation) for details on how to configure `onSetup`.

### API

| Name | Value | Description |
| --- | --- | --- |
| isDisabled | `() ⇒ boolean` | Checks if button is disabled. |
| setDisabled | `(state: boolean) ⇒ void` | Sets the button’s disabled state. |
| isActive | `() ⇒ boolean` | Checks the button’s toggle state. |
| setActive | `(state: boolean) ⇒ void` | Sets the button’s toggle state. |

### Split button example and explanation

The following example sets up a split button with a text label and a static dropdown menu.

**Example**

```js
tinymce.init({
  selector: 'textarea#custom-toolbar-split-button',
  toolbar: 'myButton',
  menubar: false,
  setup: function (editor) {
    editor.ui.registry.addSplitButton('myButton', {
      text: 'My Button',
      icon: 'info',
      tooltip: 'This is an example split-button',
      onAction: function () {
        editor.insertContent('<p>You clicked the main button</p>');
      },
      onItemAction: function (api, value) {
        editor.insertContent(value);
      },
      fetch: function (callback) {
        var items = [
          {
            type: 'choiceitem',
            icon: 'notice',
            text: 'Menu item 1',
            value: '&nbsp;<em>You clicked menu item 1!</em>'
          },
          {
            type: 'choiceitem',
            icon: 'warning',
            text: 'Menu item 2',
            value: '&nbsp;<em>You clicked menu item 2!</em>'
          }
        ];
        callback(items);
      }
    });
  },
  content_style: 'body { font-family:Helvetica,Arial,sans-serif; font-size:14px }'
});
```
A split button is similar to a basic button in that they both require an `onAction` callback. The `onAction` callback function should take the button’s API and return nothing. It is called when the basic button section is clicked. In this example, `onAction` calls `editor.insertContent(value)` which inserts the given content into the editor.

`onItemAction` is called when a menu item is clicked. The callback function is passed the split button’s API and the *value* of the selected menu item. Nothing should be returned. The example calls `editor.insertContent(value)` to insert the *value* into the editor’s content.

The `fetch` function is called whenever the split button’s drop-down menu is opened. It is a function that takes a callback and passes it an array of menu items to be rendered in the button’s drop-down menu. This allows for asynchronous fetching of the menu items.

### Choice menu items

Choice menu items are a special type of menu item used for split toolbar button menu items. For information on split buttons, see: [Split toolbar buttons](#splitbutton).

#### Config options

| Name | Value | Requirement | Description |
| --- | --- | --- | --- |
| value | any | required | A value that is passed to `onItemAction` when the choice menu item is clicked. |
| text | string | optional | Text to display. |
| icon | string | optional | Name of the icon to be displayed. Must correspond to an icon: in the [icon pack](../editor-icon-identifiers/), in a [custom icon pack](../creating-an-icon-pack/), or added using the [`addIcon` API](../apis/tinymce.editor.ui.registry/#addIcon). |
| disabled | boolean | optional | default: false - Represents the menu item’s state. When true, the menu item is unclickable. Toggled by the menu item’s API. |
| shortcut | string | optional | Text to display in the shortcut label. To register a shortcut, see: [Add custom shortcuts to TinyMCE](../keyboard-shortcuts/#addcustomshortcutstotinymce). |

> **Note:** The `icon` option for choice menu items was added in TinyMCE 5.3.
For an example of how choice menu items are used in split toolbar buttons, see: [Split button example and explanation](#splitbuttonexampleandexplanation).

## Group toolbar button

> **Note:** This feature is only available for TinyMCE 5.2 and later.
A group toolbar button is a toolbar button that contains a collection of other toolbar buttons that are displayed in a pop-up when clicked. The style of toolbar shown is based on the current [toolbar mode](../editor-appearance/#toolbar_mode). For example, if `toolbar_mode` is set to `floating`, the toolbar group pop-up will appear in a floating shelf.

> **Note:** The group toolbar button is *only* supported when using the `floating` toolbar mode. If the `toolbar_groups` option is used with other toolbar modes, the toolbar group button will not be displayed and a warning message will be printed in the console.

### Config options

| Name | Value | Requirement | Description |
| --- | --- | --- | --- |
| text | string | optional | Text to display if no icon is found. |
| icon | string | optional | Name of the icon to be displayed. Must correspond to an icon: in the [icon pack](../editor-icon-identifiers/), in a [custom icon pack](../creating-an-icon-pack/), or added using the [`addIcon` API](../apis/tinymce.editor.ui.registry/#addIcon). |
| tooltip | string | optional | Text for button tooltip. |
| items | string or LabelledToolbar[] | required | A string of space separated toolbar button names, or an array of [labelled toolbar buttons](../editor-appearance/#addingtoolbargrouplabels). |
| onSetup | `(api) ⇒ (api) ⇒ void` | optional | default: `() ⇒ () ⇒ {}` - Function that’s invoked when the button is rendered. |

> **Note:** See [below](#onsetupexplanation) for details on how to configure `onSetup`.

### API

| Name | Value | Description |
| --- | --- | --- |
| isDisabled | `() ⇒ boolean` | Checks if the button is disabled. |
| setDisabled | `(state: boolean) ⇒ void` | Sets the button’s disabled state. |

### Group toolbar button example and explanation

The following is a simple group toolbar button example:

**Example**

```js
tinymce.init({
  selector: 'textarea#custom-toolbar-group-button',
  height: 500,
  toolbar_mode: 'floating',
  toolbar: 'alignment',

  setup: function (editor) {

    /* example, adding a group toolbar button */
    editor.ui.registry.addGroupToolbarButton('alignment', {
      icon: 'align-left',
      tooltip: 'Alignment',
      items: 'alignleft aligncenter alignright | alignjustify'
    });

  },
  content_style: 'body { font-family:Helvetica,Arial,sans-serif; font-size:14px }'
});
```
The example above configures a custom **alignment** group toolbar button. When clicked the button will show a floating shelf containing the align left, center, right and justify toolbar buttons.

## `onSetup` explanation

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

To clarify, in code `onSetup` may look like this:

```js
onSetup: function (api) {
  // Do something here on component render, like set component properties or bind an event listener

return function (api) {
    // Do something here on teardown, like unbind an event listener
  };
};
```
To bind a callback function to an editor event use `editor.on(eventName, callback)`. To unbind an event listener use `editor.off(eventName, callback)`. Any event listeners *should* be unbound in the teardown callback. The only editor event which does not need to be unbound is `init` e.g. `editor.on('init', callback)`.

> **Note:**
> - The callback function for `editor.off()` should be the same function passed to `editor.on()`. For example, if a `editorEventCallback` function is bound to the `NodeChange` event when the button is created, `onSetup` should return `function (api) { editor.off('NodeChange', editorEventCallback) }`.
> - If `onSetup` does not have any event listeners or only listens to the `init` event, `onSetup` can return an empty function e.g. `return function () {};`.
