0

I had special requirements for a Button-Block for the Gutenberg-Editor, so I built a custom block "myproject/button".

Now I try to use the core/buttons block with this new button block, but I can't find a way to tell the core/buttons block to use and allow only my new custom block instead of the core/button block.

In the source code of the core/buttons block, it sets an allowed block list like this: https://github.com/WordPress/gutenberg/blob/trunk/packages/block-library/src/buttons/edit.js#L22

And it is being used when rendering the innerblocks like this: https://github.com/WordPress/gutenberg/blob/trunk/packages/block-library/src/buttons/edit.js#L62

I did not find a way to manipulate this. My best gues was using the blocks.registerBlockType hook to get the settings, add/manipulate a "allowdBlocks" setting or so and returning the settings again. But that did not work and I even can't find any information about the allowed blocks in that hook (or in the settings parameter the callback functions provides).

Any help is appreciated!

5
  • can you provide context for why this requirement you're trying to implement is needed? There may be other options you hadn't considered that give you what you want but don't involve this particular approach of limiting inner blocks that you hadn't considered, but more context is needed to figure that out (or just to eliminate that and make it clearer it isn't an option)
    – Tom J Nowell
    Oct 12, 2023 at 14:13
  • It is basically a customer requirement. The core button block does not offer the features the customer wants, like being able to set customized icons to the button, having a certain degree of accessibility etc.
    – FbnKlmn
    Oct 12, 2023 at 15:07
  • in that case, maybe a fork of the core/buttons block might be better? If it was just icons then block styles/variants of core/block might be able to provide you with the core block plus extra icons/styling, but if you want to change the markup of the block then perhaps a new set of blocks would be best rather than trying to fit it into core/buttons
    – Tom J Nowell
    Oct 12, 2023 at 16:07
  • Thats unfortunate because the core/buttons is exactly what we need for our custom button :( So ... do you know there is no way to do the manipulation I tried to achieve? Or are you not sure?
    – FbnKlmn
    Oct 12, 2023 at 16:32
  • the solution is extreme and carries heavy downsides, given that you've already abandoned the core/button block it would be easier to replace the core/buttons block with your own new custom block that only accepts your new button block than it would be to achieve what you wanted via the method you asked. Even with the solution, you should still look at other options, this is not going to save you time and effort, or make your life easier, quite the opposite
    – Tom J Nowell
    Oct 12, 2023 at 17:52

1 Answer 1

0

WARNING: There be dragons ahead

Changing the allowed innerblocks of the core/buttons block can be done, but it will make your life harder and introduce lots of new problems.

Note that it would be faster, easier, and safer to implement a new buttons block that only accepts your custom block.

To do this you would need to:

  • wait until the editor is ready using the editor promise on the window object that it uses to initialise things
    • this also means that when your code loads is important.
  • filter all blocks and check their registration settings to see if they require a core/buttons block as their parent. wp.blocks.getBlockTypes() or import { getBlockTypes } from '@wordpress/blocks'; will be useful here
    • if one is found, take it's settings and re-register that block minus core/buttons as a parent using registerBlockType from import { registerBlockType } from '@wordpress/blocks'; or wp.blocks
    • if it's the core/button block, modify its settings so that it does not support the inserter. Unregistering it can cause the editor to crash ( see below point ).
      • the only way you can unregister a block safely is before the editor is initialised, ideally in PHP by declaring it is not allowed via filters.
    • WARNING: Do not try to unregister the block type!! You cannot safely unregister blocks after the editor has been initialised, if you do this and there is an instance of that block in the editor the block editor will crash and require a hard refresh to recover.

You will need to use the main window.wp object to interact with the block registry, or use the equivalents from the respective packages in your bundle. The readme's for each package should help indicate this. See https://developer.wordpress.org/block-editor/reference-guides/packages/packages-blocks/, and inspect window.wp.blocks

Caveats:

  • existing button blocks inside core button blocks will not be removed
  • block patterns that use core/button with core/buttons will sidestep all of this
  • nothing stops them from copy pasting a core/button and core/buttons combination into your editor
  • other plugins that add their own blocks or variations will either be broken, or break your setup
  • doing this will slow down your editor, and may be a fragile operation.
  • There is a high chance this will break in the future as the block editor improves and new features are added. E.g. the upcoming block hooks feature may cause problems here

There is also an option where you can use a filter to replace the edit component, enabling you to use the allowed blocks attribute to force only yours to be selectable, but this too has similar caveats, can fail catastrophically if not done correctly, and requires you to fork the majority of the core/buttons block anyway defeating the point.


Note that of all the options and methods to satisfy your clients requirement, this route is the most difficult, extreme, and least robust/reliable option. It should be considered as an extreme last resort, not a time/effort saving measure (it will save neither).

Other options included:

  • A block style for the core/buttons block that hides all core/button blocks using CSS
    • A PHP render filter could also have removed them so they never appeared in the HTML at all
  • Forking core/buttons
  • Creating your own FbnKlmn/buttons block
  • Adding an icons attribute to core/button instead of creating a new block
  • Asking how to make the core version of the button block meet the requirements instead of creating a brand new block

What You Should Do Instead

Literally anything else.

Trying to enforce up the chain what children a parent block can choose is a mistake. Instead:

  • Register a block variation for core/buttons
    • Given it a name that matches your requirements
    • Use the Innerblocks parameter to include one of your custom buttons by default, note that this doesn't prevent core/button being added.
    • Set it to the default variation so that core/buttons are this variation by default
    • Hide child blocks that don't meet your criteria when they are children of this variation using the classnames WP adds to the markup.

Likewise, a block variation of core/button would be the way to customize the core block without creating a brand new block. There are other ways of doing this without doing what you asked for that are easier than what you asked for, but this would be my approach.

E.g. for icons, filter the core/button block to add an icon attribute, either a string from a predefined list or an attachment ID, then filter the edit component to add a control for it. The icon can then be added via an :after or :before pseudo-element on the frontend, or if you're feeling adventurous via a PHP render filter that modifies the markup. If the client ever migrated the content, or imported it from elsewhere then everything would fallback gracefully or be migrated across without transforms for free

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.