Notes about WordPress Gutenberg themes development.

  • Block variations

    Read more

    Block styles: create specific look variations with CSS

    Block variations: preset a block configuration.

    Example:

    wp.blocks.registerBlockVariation(
    	'core/quote',
    	{
    		name: 'dev-name',
    		title: 'Title',
    		icon: 'format-status',
    		isDefault: true,
    		attributes: {
    			templateLock: 'all',
    			className: 'dev-classname'
    		},
    		innerBlocks: [
    			[
    				'core/image',
    				{
    					className: 'wp-block-image alignleft'
    				}
    			],
    			[
    				'core/paragraph',
    				{
    					className: 'dev-paragraph'
    				}
    			]
    		]
    	}
    );

    Source:

    • https://fullsiteediting.com/lessons/block-variations/
    • https://developer.wordpress.org/block-editor/reference-guides/block-api/block-variations/
    • https://developer.wordpress.org/news/2023/08/29/an-introduction-to-block-variations/
  • Override blocks style

    Read more

    To override block styles for rules that can’t be changed through theme.json (complexe rules or non core blocks) , one can use dev__blocks__enqueue_styles function:

    add_action( 'init', 'dev__blocks__enqueue_styles' );
    
    function dev__blocks__enqueue_styles() {
    	foreach ( glob( get_stylesheet_directory() . '/assets/css/blocks-overriding/*', GLOB_ONLYDIR ) as $directory) {
    		$namespace = substr( strrchr( $directory, '/' ), 1 );
    		foreach ( glob( $directory . '/*.css' ) as $file) {
    			$filename = pathinfo( $file, PATHINFO_FILENAME );
    			wp_enqueue_block_style(
    				$namespace . '/' . $filename,
    				array(
    					'handle'	=> 'dw-override--' . $namespace . '-' . $filename,
    					'src'		=> get_stylesheet_directory_uri() . '/assets/css/blocks-overriding/' . $namespace . '/' . $filename . '.css',
    					'path'		=> get_stylesheet_directory() . '/assets/css/blocks-overriding/' . $namespace . '/' . $filename . '.css',
    					'ver'		=> filemtime( get_stylesheet_directory() . '/assets/css/blocks-overriding/' . $namespace . '/' . $filename . '.css' )
    				)
    			);
    		}
    	}
    }

    Source : https://developer.wordpress.org/reference/functions/wp_enqueue_block_style/

  • Dynamically generate a block

    Read more
    $block = array(
    	'blockName'	=> 'dev/blockname',
    	'attrs' => array(
    		'name'	=> 'dev/blockname',
    		'data'	=> array(
    			'ACF__field' => get_field( 'ACF__field' )
    		)
    	),
    );
    $html_output = render_block($block);

    To know what data send as parameter for the $block object, one can use the render_block filter

    add_filter( 'render_block', 'dev__paragraph_add_block', 10, 2 );
    function dev__paragraph_add_block( $block_content, $block ){
    
    	if ( 'dw/icon' === $block['blockName'] ){
    		echo '<pre>';
    		var_dump($block);
    		echo '</pre>';
    	}
    
    	return $block_content;
    
    }

    Source : https://www.itsupportguides.com/knowledge-base/wordpress/using-wordpress-render_block-php-function/

  • block supports properties

    Read more

    To use the supports properties, first enable them in the block.json.

    {
    	"$schema": "https://schemas.wp.org/trunk/block.json",
    	"apiVersion": 3,
    	
     ...
    
    	"supports": {
    		"color": {
    			"text": true,
    			"background": true
    		}
    	},
    	"acf": {
    		"mode": "preview",
    		"renderTemplate": "./render.php"
    	}
    }

    Then in render.php :

    <?php
    
    $classes = array();
    
    if ( ! empty( $block['textColor'] ) ) {
    //	$classes = array_merge( $classes, explode( ' ', $block['className'] ) );
    	$classes[] = 'has-text-color';
    	$classes[] = 'has-' . $block['textColor'] . '-color';
    }
    
    echo '<div class="' . esc_attr( join( ' ', $classes ) ) . '"></div>';

    Or simply use the function get_block_wrapper_attributes( string[] $extra_attributes = array() ): string for e.g. to get the classes :

    preg_match( '/class="(.*?)"/', get_block_wrapper_attributes(), $matches);
    classes = $matches[1];

    Sources:

  • Block rendering filter

    Read more
    add_filter( 'render_block', 'dev__paragraph_add_block', 10, 2 );
    
    function dev__paragraph_add_block( $block_content, $block ){
    
    	if ( 'core/paragraph' === $block['blockName'] ){
    		$block_content = new WP_HTML_Tag_Processor( $block_content );
            $block_content->next_tag(); /* first tag should always be ul or ol */
            $block_content->add_class( 'wp-block-paragraph' );
            $block_content->get_updated_html();
    	}
    
    	return $block_content;
    
    }
  • InnerBlock

    Read more

    Interesting attributes : allowedBlocks, template, InnerBlocks.

    Example of a devblock/render.php

    <?php
    
    $classes_container = array( 'block__container' );
    $classes_innerblock = array( 'block__innerblock' );
    
    if ( !empty( $block['className'] ) ){
    	$classes_root = array_merge( $classes_root, explode( ' ', $block['className'] ) );
    }
    
    $allowed_blocks = array( 'namespace/blockname' );
    
    $template = array(
    	array(
    		'namespace/blockname',
    		array(
    			'className'		=> 'some-class'
    		)
    	)
    );
    
    ?>
    
    <div class="<?php echo join( ' ', $classes_container ); ?>">
    	<InnerBlocks
    		class="<?php echo join( ' ', $classes_innerblock ); ?>"
    		allowedBlocks="<?php echo esc_attr( wp_json_encode( $allowed_blocks ) ); ?>"
    		template="<?php echo esc_attr( wp_json_encode( $template ) ); ?>" />
    
    </div>
    
  • Creating a block

    Read more

    Prototype:register_block_type( string|WP_Block_Type $block_type, array $args = array() ): WP_Block_Type|false

    add_action( 'init', 'dev__register_blocks', 5 );
    
    function dev__register_blocks() {
    	register_block_type( __DIR__ . '/some_block_dir' );
    }

    The block.json file :

    {
        "$schema": "https://schemas.wp.org/trunk/block.json",
        "apiVersion": 3,
        "name": "namespace/blockname",
        "title": "Notice",
        "category": "text",
        "parent": [ "core/group" ],
        "icon": "star",
        "description": "Shows warning, error or success notices...",
        "keywords": [ "alert", "message" ],
        "version": "1.0.3",
        "textdomain": "my-plugin",
        "editorScript": "file:./index.js",
        "script": "file:./script.js",
        "viewScript": [ "file:./view.js", "example-shared-view-script" ],
        "editorStyle": "file:./index.css",
        "style": [ "file:./style.css", "example-shared-style" ],
        "render": "file:./render.php",
    	"supports": {
    		"className": true,
    		"customClassName": true,
    		"jsx": true			// to use innerBlocks,
    		"inserter": true	// will be accessible only programatically
    	},
    
    	// ACF options: 
    	"acf": {
    		"mode": "preview",
    		"renderTemplate": "render.php"
    	},
    
    	"example": { "attributes": { "mode": "preview" } }
    
    
    }
    

    Sources: