Hey visitors! If you’re a beginner in WordPress and WP-CLI development, then you should check out my dear friend Bhargav’s Youtube channel! @BuntyWP

Adding buttons to the Image, Audio or Video block in Gutenberg

The Image block from the Gutenberg editor.

The title is kind of incomplete. Look at the image above, especially at the Media Library button. This button is implemented using the MediaUpload component. This article will help you to add React elements or components around the MediaUpload component which is also used in the core/video and core/audio blocks.

This article requires basic knowledge of Higher-Order components, also known as HOCs.

The code below is documented and explains a few concepts to get started.

import { addFilter } from "@wordpress/hooks";

/**
 * Adds some useless elements around the MediaUpload component.
 * @param {React.ComponentType} Component The MediaUpload component.
 * @returns {React.FC} Returns the Wrapped component.
 * 
 * The `addHtmlAround` function is a Higher Order Component
 * that accepts a Component as argument and returns a Component
 * as well. In our case, the Component passed is the
 * MediaUpload component.
 */
function addHtmlAround( Component ) {

    /**
     * Notice that this function returns a function.
     * The `props` are the same props that are passed to
     * the MediaUpload component.
     */
    return ( props ) => {
        return <Component { ...props } />
    };
}

addFilter(
    'editor.MediaUpload',
    'the-wordpress-voyage/do-nothing-button',
    addHtmlAround
);Code language: JavaScript (javascript)

The hook we are using to add elements/components is editor.MediaUpload.

Understanding the code above

The code is in its most minimal form. It does absolutely nothing. It accepts the MediaUpload component and returns it as it is. It is as good as not running the code above.

Let’s experiment with it to add some <div /> elements around the <Component />.

function addHtmlAround( Component ) {

    /**
     * Notice that this function returns a function.
     * The `props` are the same props that are passed to
     * the MediaUpload component.
     */
    return ( props ) => {
        return (
            <>
                <div>Before</div>
                <Component { ...props } />
                <div>After</div>
            </>
        )
    };
}
Code language: JavaScript (javascript)

With the code above, if you add an Image, Audio or a Video block, you’ll see the following:

To keep the example simple, we did not add any functionality. But you can add a <Button /> instead which can perform a specific task.

Excluding specific blocks

Suppose if you want to add buttons to only the image block. You can do that by adding the following:

function addHtmlAround( Component ) {

    /**
     * Notice that this function returns a function.
     * The `props` are the same props that are passed to
     * the MediaUpload component.
     */
    return ( props ) => {
        let blockProps;

        try {
            /**
             * The try-catch is important, because the
             * `MediaUpload` component can be used outside
             * the block context as well. For example, the
             * Featured Image button is not a block, and using
             * the `useBlockProps()` function will throw an
             * exception which we catch here.
             */
            blockProps = useBlockProps();
        } catch ( e ) {
            /**
             * Return the original component as it is if
             * `useBlockProps()` throws an exception when
             * this code runs outside of the Block context.
             */
            return <Component { ...props } />;
        }

        const { 'data-type': blockName } = blockProps;

        if ( 'core/image' !== blockName ) {
            return <Component { ...props } />;
        }

        return (
            <>
                <div>Before</div>
                <Component { ...props } />
                <div>After</div>
            </>
        )
    };
}
Code language: JavaScript (javascript)

That’s all! Hope you had fun reading, thank you!



Leave a Reply

Your email address will not be published. Required fields are marked *

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

The reCAPTCHA verification period has expired. Please reload the page.

Powered by WordPress