Add a button to the toolbar of an existing Gutenberg block

Edit: WordPress 5.9 or above.

WordPress 5.9 moved the slotfill behind the useDisplayBlockControls hook which prevents fills from registering unless they are within the currently selected block’s component. It is no longer possible to use the BlockControls slotfill for adding elements to toolbars of WordPress core blocks.

Original: WordPress 5.8.3 or below.

There is an undocumented slotfill which fills within the block toolbar called BlockControls which allows you to include custom buttons or elements within the block toolbars. The component is documented, but not within slotfills.

The most straight forward way of adding a control within the slot is to use the <ToolbarButton> component and it’s props. You may however put any element you like in the slot.

There is a <ToolbarItem> component which provides to assistance for custom elements.

You can limit which blocks receive the custom button via the useSelect hook and returning null if the correct block is not selected.

Putting it all together.

const Download = () => {
    const selectedBlock = useSelect( select => {
        return select( 'core/block-editor' ).getSelectedBlock();
    }, [] );

    if ( selectedBlock && selectedBlock.name !== 'core/image' ) {
        return null;
    }

    return (
        <BlockControls>
            <ToolbarButton
                icon={'download'}
                label="Download"
                onClick={() => alert( selectedBlock?.attributes?.url )}
            />
        </BlockControls>
    );
};