Adding Align Controls to a Gutenberg Block
Recently I created a section wrapper block, meant to house other blocks. I wanted the block itself to support wide and full alignment but also for the blocks within it to support wide or full layout, similar to the core Group block. (This block could also have been a block pattern using the Group block, but I wanted the ability to define preset Block Styles the editor could use.)
block.json
First, I enabled the layout in the block.json. Note that this is still an experimental feature and subject to change in the future.
"supports": {
"align": ["wide", "full"],
"__experimentalLayout": true
}
Block Edit
Next, within the block’s edit function, I needed to check that the block
supported layouts and pass the __experimentalLayout
prop on to the InnerBlocks.
Much of this came from the core Group block.
Get the Setting
To check whether the block has support for layout enabled (although it’s in
block.json, it could have been modified by another plugin or theme), I used
useSelect
to retrieve the settings from the block-editor store.
import { store } from '@wordpress/block-editor';
import { useSelect } from '@wordpress/data';
function Edit({ clientId }) {
const hasLayoutSupport = useSelect(
(select) => {
const { getSettings } = select(store);
return getSettings()?.supportsLayout;
},
[clientId]
);
}
Get the Default Layout
Next, I defined the default layout using useSetting
to get the current
layout setting from the editor, if defined. (The layout setting controls the max
widths for wide and regular constrains).
import { useSetting } from '@wordpress/block-editor';
...
const defaultLayout = useSetting( 'layout' ) || {};
Get the Block’s Layout Setting
The block can inherit the default layout, define its own max widths, or do neither.
To determine which, I retrieved the layout attribute. If the layout attribute exists
and layout.inherit
is true, the block is inheriting the default layout.
Once I know what layout, if any, is in use, I can determine the type.
const { layout = {} } = attributes;
const layoutInUse = !!layout && layout.inherit
? defaultLayout
: layout;
const { type = 'default' } = layoutInUse;
Determine if InnerBlocks Get Layout Support
With all that in place, I needed to enable layout support on the InnerBlocks if the block supports layout in its settings or if it has a custom layout currently in use. If it does, I needed to tell InnerBlocks what layout to use. If the block didn’t have a layout attribute but has layout support enabled, the default layout is used.
const layoutSupportEnabled = hasLayoutSupport || type !== 'default';
...
<InnerBlocks
__experimentalLayout={
layoutSupportEnabled ? layoutInUse : undefined
}
/>
Altogether, minus the additional block template for the section block, it looks something like this:
import {
useBlockProps,
InnerBlocks,
store,
useSetting,
} from '@wordpress/block-editor';
import { useSelect } from '@wordpress/data';
function Edit({ attributes, clientId }) {
const hasLayoutSupport = useSelect(
(select) => {
const { getSettings } = select(store);
return getSettings()?.supportsLayout;
},
[clientId]
);
const defaultLayout = useSetting('layout') || {};
const { layout = {} } = attributes;
const layoutInUse = !!layout && layout.inherit
? defaultLayout
: layout;
const { type = 'default' } = layoutInUse;
const layoutSupportEnabled
= hasLayoutSupport || type !== 'default';
const blockProps = useBlockProps({
className: classnames('l-section'),
});
return (
<section {...blockProps}>
<InnerBlocks
__experimentalLayout={
layoutSupportEnabled ? layoutInUse : undefined
}
/>
</section>
);
}