gutenberg
gutenberg copied to clipboard
Transforms: Allow multiple transforms per block type
What?
This PR enables the transform menu/command to offer multiple transformations for the same block, either eligible variations (via a new "switcher" scope), or named transforms that suit more niche use cases.
Why?
-
Transforming directly into a desired block variation can be considered a QoL enhancement, but also because some custom block variations may be too specific to count as the active one compared to other variations. For example, a custom Group block variation may apply alignment/style changes, and be independent of the layout settings. At best you can transform it to the desired layout, then select the variation from the transform menu, only for the original to show as still active.
-
Some more complex blocks could warrant offering multiple transformation results regardless of the source block, particularly if they split/wrap the source block in other blocks. For example, a custom List Grid block that offers transforming the selection into a grid of either Snippet Item blocks or Profile Item blocks.
How?
The getBlockTransformItems
selector now returns items based on valid block transformations, not block types with valid transformations, and includes the specific transformation to use. By default, the results will be the same; however, additional items can be listed by one of two means:
- A block variation specifies the new "switcher" scope; it will be added if the default transformation option for a block is present.
- A block transformation is given a
name
attribute (and optional title/icon overrides), and will be listed alongside the default one.
The "default" transformation is, as before, the highest priority valid transformation candidate (named ones are not considered).
When selected, the transformation is applied via the new getBlockTransformationResults()
utility, which abstracts the results half of switchToBlockType()
.
In addition, switchToBlockType()
now supports a variation argument; it will apply the variation to the transformation results if it exists.
Testing Instructions
- Add the following code to your test theme. This registers a Quote block variation using the Plain style, and patches in a alternate columns transformation that takes a heading + any other blocks, and puts them in a 25/75 column layout.
function demo_multiple_transforms_per_block_type() {
$script = <<<JS
const { addFilter } = wp.hooks;
const { registerBlockVariation, createBlock } = wp.blocks;
registerBlockVariation( 'core/quote', {
name: 'plain',
title: 'Plain Quote',
attributes: {
className: 'is-style-plain',
},
scope: [ 'inserter', 'switcher' ],
isActive: attributes => attributes.className?.includes( 'is-style-plain' ),
} );
const headingContentColumnsTransform = {
name: 'heading-and-content',
title: 'Heading + Content Columns',
type: 'block',
isMultiBlock: true,
blocks: [ 'core/heading', '*' ],
__experimentalConvert: ( blocks ) => {
const [ heading, ...content ] = blocks;
return createBlock( 'core/columns', {}, [
createBlock( 'core/column', { width: '25%' }, [
createBlock( heading.name, heading.attributes ),
] ),
createBlock(
'core/column',
{ width: '75%' },
content.map( ( block ) =>
createBlock(
block.name,
block.attributes,
block.innerBlocks
)
)
),
] );
},
isMatch( blockAttributes, blocks ) {
return blocks.length > 1 && blocks[ 0 ].name === 'core/heading';
},
};
addFilter(
'blocks.registerBlockType',
'named-transforms/heading-and-content-columns',
( settings ) => {
if ( settings.name !== 'core/columns' ) {
return settings;
}
return {
...settings,
transforms: {
from: [
...settings.transforms.from,
headingContentColumnsTransform,
],
to: settings.transforms.to,
},
};
},
);
JS;
wp_add_inline_script( 'wp-edit-post', $script );
}
add_action( 'enqueue_block_editor_assets', 'demo_multiple_transforms_per_block_type' );
-
Open the editor to a page.
-
Select a paragraph block and open the block switcher. The block variation "Plain Quote" will appear as an option. Selecting it should wrap it in a Quote block with the Plain style already applied.
-
Insert a heading above the paragraph, then select it plus any number of blocks after it. Open the block switcher, the "Columns" transform will appear, but also the "Heading + Content Columns" transform as well. Selecting the latter should create a 2 column layout with the heading in the first and the remaining blocks in the second.
Screenshots or screencast
The Plain Quote variation transform in action.
https://github.com/user-attachments/assets/1e96149f-8872-4c28-bc28-60b4ec96424b
The Heading + Content Columns alternative transform in action.
https://github.com/user-attachments/assets/8a7f3d80-c839-48ac-8b81-5015cf00a224