Gutenberg Editor – Add Button to the Toolbar

Today, we are going to create a custom button to the Rich Text Editor using by Gutenberg. By default, it has alignments, bold, italic and link buttons. We are going to add a text highlighter button to the rich text toolbar.

Rich Text Toolbar - Text Highlight

Let’s start by creating a javascript file with the name text-highlight-button.js and load it with wp_enqueue_script() helper function. But we can not use this helper function directly. We have to load our javascript file for the Gutenberg editor. And enqueue_block_editor_assets action hook will help us to achieve that. Open the functions.php file and apply this enqueue_block_editor_assets action hook to register the created javascript file.

add_action('enqueue_block_editor_assets', 'block_editor_text_highlight_button');
function block_editor_text_highlight_button() {

	// Load the compiled blocks into the editor.
	wp_enqueue_script(
		'text-highlight-button-js',
		get_stylesheet_directory_uri().'/dev-src/text-highlight-button.js',
		array( 'wp-blocks', 'wp-element', 'wp-components', 'wp-editor' ),
		'1.0',
		true
	);

        // Load the compiled styles into the editor.
	wp_enqueue_style(
		'text-highlight-button-editor-css',
		get_stylesheet_directory_uri().'/dev-src/text-highlight-button.css',
		array( 'wp-edit-blocks' )
	);
}

We have injected the required dependecies for our script through the 3rd parameter. If you are not familiar with the wp_enqueue_script() function then please take a look on the documentation.

The text-highlight-button.css file should contain the style.

.wo-text-highlight{
    background-color: #fbedb8;
    -webkit-box-shadow: inset 0px -2px 0px 0px rgba(241,196,15,1);
    -moz-box-shadow: inset 0px -2px 0px 0px rgba(241,196,15,1);
    box-shadow: inset 0px -2px 0px 0px rgba(241,196,15,1);
    padding: 0 2px;
}

Now, let’s go back to the created text-highlight-button.js file. First of all, we have to register a new format type with the help of wp.richText.registerFormatType() method.

Register Format Type

( function( wp ) {

    var TextHighlighButton = function( props ) {
       
    }

    wp.richText.unregisterFormatType('core/underline');
    wp.richText.registerFormatType(
        'webomnizz/text-highlight', {
            title: 'Text Highlight',
            tagName: 'span',
            className: 'wo-text-highlight',
            edit: TextHighlighButton,
        }
    );
} )( window.wp );

The wp.richText.registerFormatType() method accepts two parameters. The first parameter is the unique name that we have used webomnizz/text-highlight. The second parameter is the settings object that accepts the title, tagName, className, and edit properties. The edit property accepts a function that returns a component to the user to interact.

Next step is to define the button that should highlight the selected text. To achieve that, we have to extend the existing toolbar with the new button and we have to return the component.

var TextHighlighButton = function( props ) {
    return wp.element.createElement(
        wp.editor.RichTextToolbarButton, {
            icon: 'admin-customizer', 
            title: 'Text Highlight', 
            onClick: function() {
                props.onChange( 
                    wp.richText.toggleFormat(props.value, {
                        type: 'webomnizz/text-highlight'
                    }) 
                );
            }
        }
    );
}

We have extended the RichTextToolbarButton with the help of wp.element.createElement() method. We have attached the object as a second parameter to the createElement with icon, title and the onClick properties.

{
    icon: 'admin-customizer', 
    title: 'Text Highlight', 
    onClick: function() {
        props.onChange( 
            wp.richText.toggleFormat(props.value, {
                type: 'webomnizz/text-highlight'
            }) 
        );
    }
}

We have used the WordPress default dashicon library for the icon. The third property is to notice here. We have used wp.richText.toggleFormat() method. It takes the first parameter as the selected value. And the second parameter as Object to apply a format or remove.

This is how our javascript looks with complete codes.

( function( wp ) {

    var TextHighlighButton = function( props ) {
        return wp.element.createElement(
            wp.editor.RichTextToolbarButton, 
            {
                icon: 'admin-customizer', 
                title: 'Text Highlight', 
                onClick: function() {
                    props.onChange( 
                        wp.richText.toggleFormat(props.value, {
                            type: 'webomnizz/text-highlight'
                        }) 
                    );
                }
            }
        );
    }


    wp.richText.unregisterFormatType('core/underline');
    wp.richText.registerFormatType(
        'webomnizz/text-highlight', {
            title: 'Text Highlight',
            tagName: 'span',
            className: 'wo-text-highlight',
            edit: TextHighlighButton,
        }
    );
} )( window.wp );

Now there is a minor issue with this code, our created text highlight will show to every block. But we want the text highlighter to the paragraph block only. Let’s add some conditional statements so that our button only displays with the paragraph only.

var withSelect  = wp.data.withSelect;
var ifCondition = wp.compose.ifCondition;
var compose     = wp.compose.compose;

We are going to use the compose method. This method takes multiple high order components(HOCs) and composes into single HOC.

In simple words, we are going to check the selected block. And if the selected block is the paragraph block then it will return true and return the TextHighlightButton.

var ConditionalTextHighlighButton = compose(
    withSelect( function( select ) {
        return {
            selectedBlock: select( 'core/editor' ).getSelectedBlock()
        }
    } ),
    ifCondition( function( props ) {
        return (
            props.selectedBlock &&
            props.selectedBlock.name === 'core/paragraph'
        );
    } )
)( TextHighlighButton );

Please take a look at the below codes for complete source code.

( function( wp ) {

    var withSelect  = wp.data.withSelect;
    var ifCondition = wp.compose.ifCondition;
    var compose     = wp.compose.compose;

    var TextHighlighButton = function( props ) {
        return wp.element.createElement(
            wp.editor.RichTextToolbarButton, 
            {
                icon: 'admin-customizer', 
                title: 'Text Highlight', 
                onClick: function() {
                    props.onChange( 
                        wp.richText.toggleFormat(props.value, {
                            type: 'webomnizz/text-highlight'
                        }) 
                    );
                }
            }
        );
    }

    var ConditionalTextHighlighButton = compose(
        withSelect( function( select ) {
            return {
                selectedBlock: select( 'core/editor' ).getSelectedBlock()
            }
        } ),
        ifCondition( function( props ) {
            return (
                props.selectedBlock &&
                props.selectedBlock.name === 'core/paragraph'
            );
        } )
    )( TextHighlighButton );


    wp.richText.unregisterFormatType('core/underline');
    wp.richText.registerFormatType(
        'webomnizz/text-highlight', {
            title: 'Text Highlight',
            tagName: 'span',
            className: 'wo-text-highlight',
            edit: ConditionalTextHighlighButton,
        }
    );
} )( window.wp );

I hope this post helps you to understand to apply custom button on the rich text toolbar. If you stuck somewhere or want to say thanks, please don’t hesitate to post through the comment.