Custom Blocks

Barebones supports custom WordPress blocks using block.json, ACF fields, PHP render templates, and block-specific assets. Block setup lives primarily in includes/blocks.php.

Block category

Barebones adds a custom block category called Custom Blocks. You can define your own categories in order to organise blocks by purpose or type. You can define a category within each block's block.json.

PHP
add_filter( 'block_categories_all', function ( $categories ) {
    $categories[] = [
        'slug'  => 'custom-blocks',
        'title' => 'Custom Blocks'
    ];

    return $categories;
});
JSON
"category": "custom-blocks"

Block directory

Each block lives in its own directory inside blocks/.

MD
blocks/split-content/
├── block.json
├── split-content.php
├── split-content.scss
├── split-content.js
└── preview.jpg

Use the same kebab-case name for the directory, PHP file, Sass file, JavaScript file, and compiled assets.

Block registration

Barebones automatically registers blocks by scanning for block.json files. A new block does not need to be manually registered if it follows the expected structure.

PHP
function bb_register_blocks() {
    $blocks = glob( get_stylesheet_directory() . '/blocks/*/block.json' );

    if ( $blocks ) {
        foreach ( $blocks as $block ) {
            register_block_type( $block );
        }
    }
}

add_action( 'init', 'bb_register_blocks' );

Block namespace

Custom blocks should use the custom-blocks/ namespace. This namespace is used by the editor restriction logic to hide any default WordPress blocks when creating a project that exclusively uses custom blocks.

JSON
"name": "custom-blocks/split-content"
PHP
/**
 * Restrict the block editor to custom blocks
 *
 * @return void
 */

add_filter('allowed_block_types_all', function ($allowed_blocks, $editor_context) {
    // Check if we're in the post editor
    if (!empty($editor_context->post)) {
        // Get all ACF blocks
        $acf_blocks = WP_Block_Type_Registry::get_instance()->get_all_registered();
        $acf_block_names = [];

        foreach ($acf_blocks as $block_name => $block) {
            if (strpos($block_name, 'custom-blocks/') === 0) {
                $acf_block_names[] = $block_name;
            }
        }

        return $acf_block_names;
    }

    return $allowed_blocks;
}, 10, 2);

ACF render templates

Blocks use ACF to connect block.json to a PHP render template. The render template lives inside the block directory. It can use normal ACF functions.

JSON
"acf": {
    "mode": "preview",
    "renderTemplate": "split-content.php"
}
PHP
$content   = get_field( 'content' );
$image     = get_field( 'image' );
$alignment = get_field( 'content_alignment' );

Block assets

Block styles and scripts are referenced from block.json.

JSON
"style": ["file:../../css/blocks/split-content.css"],
"viewScript": ["file:../../js/blocks/split-content.js"]

The source files live beside the block.

  • blocks/split-content/split-content.scss
  • blocks/split-content/split-content.js

Vite compiles these into the paths referenced by block.json.

Asset versioning

Block assets are versioned with the same file-based approach as global assets.

Barebones filters theme style and script URLs and adds the file modification time as the version.

PHP
add_filter( 'style_loader_src', 'bb_block_asset_versioning', 10, 2 );
add_filter( 'script_loader_src', 'bb_block_asset_versioning', 10, 2 );

Inline styles

Barebones prevents WordPress from inlining block styles. This encourages WordPress to load the compiled CSS files instead.

PHP
add_filter( 'styles_inline_size_limit', '__return_zero' );

Preview images

Blocks can define a static preview image in block.json.

JSON
"example": {
    "attributes": {
        "data": {
            "preview": "blocks/split-content/preview.jpg"
        }
    }
}

Each block then renders the preview image using bb_block_preview_image_src() when it detects that the block is being loaded in the 'Add Block' editor preview.

PHP
<?php if (bb_is_block_preview($block)): ?>

    <div class="block-preview"><img src="<?php echo bb_block_preview_image_src($block); ?>" /></div>

<?php else: ?>

Triggering Javascript in the Block Preview

When you're writing Javascript that would normally trigger on the load event, you will find that it doesn't fire as expected within the block preview. In this context, we need to wait until the block is rendered by ACF before we trigger the code.

We can do this by hooking onto the window.acf event. The sample code below will fire on load in the frontend and on window.acf within the block preview for a block called gallery.

JAVASCRIPT
(function($) {

    function initialiseGallery(block) {
        // Do something
    });

    initialiseGallery(document);

    if (window.acf) {
        window.acf.addAction('render_block_preview/type=gallery', initialiseGallery);
    }

})( jQuery );