Creating blocks

Composing your own blocks with BS is extremely easy. The plugin will look for a blockstudio folder within your currently activated theme. Inside of it, every .php and .twig file will create a new block by making use of the file header information. Let's take a look at one of the blocks that is being used on the landing page:

<?php // cta.php /* Title: Call to Action Description: Call to action element. Category: blockstudio Icon: lightbulb Mode: preview SupportsAlign: false SupportsMode: false */

The above is equivalent of this code:

add_action( 'acf/init', 'my_register_blocks' ); function register_cta_block() { if( function_exists( 'acf_register_block_type' ) ) { register_cta_block(array( 'name' => 'cta', 'title' => __('Call to Action'), 'description' => __('Call to action element.'), 'category' => 'blockstudio', 'icon' => 'lightbulb', 'mode' => 'preview', 'supports' => array( 'align' => false, 'mode' => false, ), )); } }

While both of these examples will register a block, nothing is being rendered yet. Instead of relying on callbacks or templates, markup in BS is being defined in the same file like so:

<?php // cta.php /* Title: Call to Action Description: Call to action element. Category: blockstudio Icon: lightbulb Mode: preview SupportsMode: false SupportsAlign: false */ ?> <p>Buy my product!</p>

And that's it, we made our first block! Every filename can only contain lowercase alphanumeric characters and dashes, and must begin with a letter. Below is a full list of possible settings that can be set in the file header.

<?php /* Title: Testimonial Description: Content block for customer testimonials. Category: marketing Icon: smiley Keywords: testimonial customer content Mode: preview Align: full PostTypes: page Parent: acf/my-block SupportsAlign: true SupportsAnchor: true SupportsCustomClassName: true SupportsJSX: true SupportsMode: true SupportsMultiple: true SupportsReusable: true */ ?>

If you need to access other block features, which can't be set using file headers, it is also possible to register blocks and settings via PHP using the $register variable:

<?php $register = array( 'title' => 'First Block', 'title' => __( 'First Block' ), 'category' => 'formatting', 'icon' => 'design', ); ?> <p>My Markup</p>

Alternatively, it is possible to add settings via PHP while maintaining settings set with the file header using the $settings variable:

<?php // cta.php /* Title: Call to Action Description: Call to action element. Category: blockstudio Icon: lightbulb Mode: preview SupportsMode: false SupportsAlign: false */ $settings = array( 'text-align' => 'left' ); ?> <p>Buy my product!</p>

Subfolders

Since BS is built on ACF OR MB, every block will automatically be registered under the acf or namespace. In our example above, the block name would have been acf/cta.

It is also possible to create blocks using folders within the Blockstudio folder. To avoid duplicate block names and errors, every block within a subfolder will be prefixed with the folders name. For example, a file called testimonial.php inside a marketing subfolder will have acf/marketing-testimonial as it's block name.

Unlimited nested folders are supported.

Prefix

It may make sense to prefix all blocks if you already have an existing blocks library in either framework. The blockstudio/prefix filter does exactly that:

add_filter( 'blockstudio/prefix', function () { return 'bs'; } );

The code above would convert the block name from acf/my-block to acf/bsx-my-block. The filter is used internally for the block library with a blockstudio prefix, so avoid this particular prefix.

Custom paths

Changing the location of the folder that is going to be searched for blocks might be necessary, for example if you are using a page builder like Oxygen, which disables the theme altogether. Use the blockstudio/path filter to do so:

// Custom path within your theme. add_filter( 'blockstudio/path' , function () { return get_template_directory() . '/blocks'; } ); // Custom path within a plugin. add_filter( 'blockstudio/path' , function () { return plugins_url . '/my-custom-plugin/blocks'; } );

Multiple instances

If the above options are not enough, it is possible to initiate the Blockstudio\Build class on various folders of your choice:

add_action( 'acf/init', function () { // Blockstudio\Build::init( $folder, $prefix ); Blockstudio\Build::init( get_template_directory() . 'client-blocks', 'client' ); Blockstudio\Build::init( get_template_directory() . 'documentation-blocks', 'documentation' ); } );

Using different prefixes is highly advisable in this case, as it'll make sure that no two block names will be the same.

Defining fields

Of course, the real usefulness of blocks come from connecting custom fields to them. This way, blocks can be infinitely reused with different settings or texts.

While defining fields via the ACF or MB interface is completely fine, BS includes a handy way to register fields in the block files like so:

<?php // cta.php /* Title: Call to Action Description: Call to action element. Category: design Icon: lightbulb Mode: preview SupportsAlign: false SupportsMode: false */ $fields = array( array( 'key' => 'cta_title_key', 'label' => 'Title', 'name' => 'cta_title', 'type' => 'text', ), array( 'key' => 'cta_text_key', 'label' => 'Text', 'name' => 'cta_text', 'type' => 'textarea', ), ); ?> <h1><?php echo get_field( 'cta_title' ) ?: 'Title'; ?></h1> <p><?php echo get_field( 'cta_text' ) ?: 'Text'; ?></p>

Blockstudio is automatically going to look for a $fields variable inside your files and if available, will register those and connect them to the block. All of the settings that ACF offers when registering fields via PHP are available here.

Previews

Previews make it possible to show the block in the inserter panel on hover. This feature behaves similar to the field registration and has to be defined in an $example variable inside your block file. All field data is called with $block['data'] or get_field() is available. Below is an example of the heading block used on the landing page.

<?php /* Title: Heading Description: Simple heading. Category: blockstudio Icon: editor-paragraph Mode: preview SupportsAlign: false SupportsMode: false */ $fields = array( array( 'key' => 'heading_heading_key', 'label' => 'Heading', 'name' => 'heading_heading', 'type' => 'text', ), array( 'key' => 'heading_text_key', 'label' => 'Text', 'name' => 'heading_text', 'type' => 'text', ), ); $example = array( 'attributes' => array( 'mode' => 'preview', 'data' => array( 'heading_heading' => "Title", 'heading_text' => "Text" ) ) ); $heading = get_field( 'heading_heading' ); $text = get_field( 'heading_text' ); ?> <div class="<?php echo $block['blockstudio_center']; ?>"> <?php if ( $heading ): ?> <h1 class="<?php echo $block['blockstudio_text_2xl']; ?>"> <?php echo $heading; ?> </h1> <?php endif; ?> <?php if ( $text ): ?> <p class="<?php echo $block['blockstudio_text_md']; ?> bsx-text-gray-600 2xl:bsx-max-w-none inter"> <?php echo $text; ?> </p> <?php endif; ?> </div>

Defaults

It is possible to set global defaults for all blocks registered with Blockstudio using the blockstudio/defaults filter:

add_filter( 'blockstudio/defaults', function () { return array( 'post_types' => array( 'post' ), ); } );

The code above will limit all BS blocks to posts. Setting the post type on individual blocks will override the global setting.

Excluding folders

Sometimes it makes sense to exclude certain folders from Blockstudio. For example, you could have a place to store all components which are used throughout your blocks.

add_filter( 'blockstudio/exclude', function () { return array( 'components' ); } );

The code above will exclude all folders named components from block generation.

Metabox

Since version 1.3.0, BS supports Metabox (MB) blocks with the same known syntax. Since MB blocks are registed using the rwmb_meta_boxes filter, following snippet has to be added to the functions.php of your currently active theme:

add_filter( 'rwmb_meta_boxes', function ( $meta_boxes ) { return Blockstudio\Build::init( get_template_directory() . '/my-mb-blocks', 'my-prefix', 'mb' ); } );

All of the features above (excluding filters for custom paths and prefixes) are also available here.

All of the features above (excluding filters for custom paths and prefixes) are also available here.

Twig

Since version 1.4.0, BS also supports Twig templates. Please note that Timber is needed for templates written with Twig.

Register

Same as PHP, all block registration data is being taken from the file header.

{# Title: Testimonial Description: Content block for customer testimonials. Category: marketing Icon: smiley Keywords: testimonial customer content Mode: preview Align: full PostTypes: page Parent: acf/my-block SupportsAlign: true SupportsAnchor: true SupportsCustomClassName: true SupportsJSX: true SupportsMode: true SupportsMultiple: true SupportsReusable: true #} <p>My Markup</p>

Fields

Similar to PHP, custom fields can be defined in the a fields variable. All connected block fields can be accessed using the field variable. Let's create the CTA example from before with Twig:

{# Title: Call to Action Description: Call to action element. Category: blockstudio Icon: lightbulb Mode: preview SupportsMode: false SupportsAlign: false #} {% set fields = [ { "key" : "cta_title_key", "label": "Title", "name" : "cta_title", "type" : "text" }, { "key" : "cta_subtitle_key", "label": "Subtitle", "name" : "cta_subtitle", "type" : "text" } ] %} <h1>{{ field.cta_title }} </h1> <h2>{{ field.cta_subtitle }} </h2>