---
title: "Creating custom Split toolbar buttons"
description: "Creating custom Split toolbar buttons for TinyMCE"
canonical_url: "https://www.tiny.cloud/docs/tinymce/latest/custom-split-toolbar-button/"
md_url: "https://www.tiny.cloud/docs/tinymce/latest/custom-split-toolbar-button/index.md"
version: "latest"
last_updated: "2026-09-24T22:40:35Z"
tokens: 1851
---
# Creating custom Split toolbar buttons

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.

## 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). |
| tooltip | string | Primary button | optional | Text displayed when hovering over the main button. |
| chevronTooltip | string | Chevron button | optional | Text displayed when hovering over the chevron button. If not provided, it will be generated using the tooltip of the main button. ie: `"{tooltip} menu"`. |
| 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](#choice-menu-items) 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. For details, see: [Using `onSetup`](#using-onsetup). |
| context | string | All | optional | default: `mode:design` - The context property dynamically enables or disables the button based on the editor’s current state. For details, see: [Context](../context/). |

## API

| Name | Value | Description |
| --- | --- | --- |
| isEnabled | `() => boolean` | Checks if the button is enabled. |
| setEnabled | `(state: boolean) => void` | Sets the button’s enabled state. |
| isActive | `() => boolean` | Checks the button’s toggle state. |
| setActive | `(state: boolean) => void` | Sets the button’s toggle state. |
| setText | `(text: string) => void` | Sets the text label to display. |
| setIcon | `(icon: string) => void` | Sets the icon of the button. |
| setTooltip | `(tooltip: string) => void` | Sets the main button tooltip. |

## 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: (editor) => {
    editor.ui.registry.addSplitButton('myButton', {
      text: 'My Button',
      icon: 'info',
      tooltip: 'Execute my action',
      chevronTooltip: 'My Button menu options',
      onAction: () => editor.insertContent('<p>You clicked the main button</p>'),
      onItemAction: (api, value) => editor.insertContent(value),
      fetch: (callback) => {
        const 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:16px }'
});
```
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](#).

### 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). |
| enabled | boolean | optional | default: `true` - Represents the menu item’s state. When `false`, 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](../shortcuts/). |
For an example of how choice menu items are used in split toolbar buttons, see: [Split button example and explanation](#split-button-example-and-explanation).

## Using `onSetup`

`onSetup` accepts a function that receives the component’s API. This function should return a callback that returns nothing after being passed the component’s API. This occurs because `onSetup` runs whenever the component is rendered, and the callback returned by `onSetup` is executed when the component is destroyed. The function returned from `onSetup` 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: (api) => {
  // Runs when the component is created
  // Configure the component or bind event listeners

  return (api) => {
    // Runs when the component is destroyed
    // Unbind event listeners or clean up resources
  };
};
```
To bind a callback function to an editor event use [`editor.on(eventName, callback)`](../apis/tinymce.editor/#on). To unbind an event listener use [`editor.off(eventName, callback)`](../apis/tinymce.editor/#off). 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 passed to `editor.off()` should be the same function passed to `editor.on()`. For example, if an `editorEventCallback` function is bound to the `NodeChange` event when the button is created, `onSetup` should return `(api) => editor.off('NodeChange', editorEventCallback)`.
> - If `onSetup` does not register any event listeners or only listens to the `init` event, `onSetup` can return an empty function e.g. `return () => {};`.
