Skip to main content

11. Block Extensions: Extending Core Blocks

Sometimes you'll find you need more control of a block to meet the needs of your design (think of an icon picker). In this scenario, you extend a core block instead of replacing it. This lesson walks through extending the core Group block with a "separator" toggle using registerBlockExtension from @10up/block-components.

Learning Outcomes

  1. Know how to extend a core block with custom attributes and controls using registerBlockExtension.
  2. Understand the three underlying WordPress block filters that registerBlockExtension wraps.
  3. Be able to conditionally show controls based on block attributes (e.g., layout type).
  4. Know when to build a custom block vs extend a core one.

Tasks

1. Create the Group block extension

Create assets/js/block-filters/group.js:

assets/js/block-filters/group.js
import { __ } from '@wordpress/i18n';
import { InspectorControls } from '@wordpress/block-editor';
import { ToggleControl, PanelBody } from '@wordpress/components';
import { registerBlockExtension } from '@10up/block-components';

registerBlockExtension('core/group', {
extensionName: 'group-has-separator',
attributes: {
hasSeparator: { type: 'boolean', default: false },
},
classNameGenerator: (attributes) => {
const { hasSeparator, layout } = attributes;
if (hasSeparator && layout?.type === 'flex' && layout?.orientation !== 'vertical') {
return 'has-separator';
}
return '';
},
Edit: (props) => {
const { attributes, setAttributes } = props;
const { hasSeparator, layout } = attributes;
if (layout?.type !== 'flex' || layout?.orientation === 'vertical') return null;

return (
<InspectorControls group="settings">
<PanelBody title={__('Separator', 'tenup')}>
<ToggleControl
label={__('Add Separator', 'tenup')}
help={__('Creates a middot between each innerblock.', 'tenup')}
checked={hasSeparator}
onChange={(value) => setAttributes({ hasSeparator: value })}
/>
</PanelBody>
</InspectorControls>
);
},
});

registerBlockExtension from @10up/block-components wraps the three WordPress block filters into a cleaner API:

  1. Add attribute: blocks.registerBlockType adds the hasSeparator boolean
  2. Add editor control: editor.BlockEdit renders the toggle conditionally in the inspector
  3. Add class output: blocks.getSaveContent.extraProps adds the has-separator class

Our separator styles are designed to add a middot between items in a row so the classNameGenerator only returns the class when the layout is horizontal flex, ensuring the dots only appear on inline groups.

The editor view of the Group block extension for &quot;Add separator&quot; The toggle should only display when using the Row Group variation

2. Create the barrel file and update the entry point

Create assets/js/block-filters/index.js:

assets/js/block-filters/index.js
import './group';

Add the import to assets/js/block-extensions.js:

import './block-filters';

4. Verify in the editor

Rebuild with npm run build. Open the editor and insert a Group block set to "Row" layout (horizontal flex). The "Add Separator" toggle should appear in the inspector under a "Separator" panel.

The CSS for .has-separator was already created in Lesson 5 (assets/css/blocks/core/group.css):

assets/css/blocks/core/group.css
.wp-block-group.has-separator {
gap: 0;

& > * {
align-items: center;
display: flex;
}

& > *:not(:first-child)::before {
background-color: currentcolor;
block-size: 4px;
border-radius: 999px;
content: "";
display: inline-flex;
inline-size: 4px;
margin-inline: var(--wp--custom--spacing--8);
}
}

5. Verify on the single movie template

The single movie template we copied from the fueled-movies theme already has "hasSeparator":true on the metadata row Group. After rebuilding, visit a single movie page on the frontend and confirm you see the dot separators between the release year, MPA rating, and other metadata items.

If the dots aren't showing, open templates/single-tenup-movie.html in the Site Editor and find the metadata row Group (the horizontal flex group containing release year, MPA rating, etc.). Enable the "Add Separator" toggle in the inspector and export the updated markup back to the theme file.

The frontend view of the Group block extension for &quot;Add separator&quot;

When to build vs extend

SituationApproach
Need entirely new markup and behaviorBuild a custom block
Need to add a feature to an existing blockExtend with block filters
Need a dynamic display of post metaUse block bindings (Lesson 10) first
Need structured nested contentBuild parent/child blocks (Lesson 12)
tip

Try block bindings first. If a Paragraph with a binding can do the job, you don't need a custom block. Only build custom when core blocks genuinely can't handle the use case.

Files changed in this lesson

FileChange typeWhat changes
assets/js/block-filters/group.jsNewregisterBlockExtension('core/group') with hasSeparator attribute, classNameGenerator, and Edit component with ToggleControl
assets/js/block-filters/index.jsNewImports ./group
assets/js/block-extensions.jsModifiedAdded import './block-filters'
templates/single-tenup-movie.htmlRevisitedMetadata row Group now has "hasSeparator":true and class has-separator

Ship it checkpoint

  • "Add Separator" toggle appears in Group block inspector (only for Row Group variation)
  • Dots appear between items in the metadata row on the single movie page
  • Toggle adds styles to both editor and frontend

Takeaways

  • Block extensions add features to core blocks using registerBlockExtension from @10up/block-components.
  • The API wraps three WordPress block filters to handle attribute registration, editor control, and class output.
  • Use classNameGenerator to conditionally add classes based on block attributes.
  • Conditionally render the Edit component so controls only appear when relevant (e.g., horizontal flex layouts only).
  • Build custom when core blocks can't do the job. Extend when they almost can.

Further reading