Adding icons to Block Categories

In my previous post I wrote about the various ways to add an icon to your custom blocks. Today we’ll look at adding icons to Categories and Collections.

The first thing you’ll need to do is add your block to a category. You can do this in the block registration. Here is the block.json from the default npx @wordpress/create-block.

JSON
{
  "$schema": "https://schemas.wp.org/trunk/block.json",
  "apiVersion": 2,
  "name": "theme-slug/example-dynamic",
  "version": "0.1.0",
  "title": "Example Dynamic",
  "category": "widgets",
  "icon": "smiley",
  "description": "Example block scaffolded with Create Block tool.",
  "supports": {
    "html": false
  },
  "textdomain": "example-dynamic",
  "editorScript": "file:./index.js",
  "editorStyle": "file:./index.css",
  "style": "file:./style-index.css",
  "render": "file:./render.php"
}

The category only accepts a string, so you can only assign one category to each block. There are several core categories:

  • text
  • media
  • design
  • widgets
  • theme
  • embed

With my new Example Dynamic block added to the site it now appears in the Widgets category.

If you assign your block to a category that has not be registered, it will show in the “Uncategorized” category at the bottom of the block inserter sidebar.

JSON
{
  ...
  "title": "Example Dynamic",
  "category": "custom-category",
  "icon": "smiley"
}

This will also throw a warning in the console.

The block “theme-slug/example-dynamic” is registered with an invalid category “custom-category”.

Registering a new Category

You can add your blocks to the core categories, you can even add icons to those categorizes which we’ll get to later, but for now lets create a new category.

To register a new category we need to use PHP and the block_categories_all hook.

If you added a category before WordPress 5.8 you might have used block_categories, this has been deprecated and you need to update.

PHP
<?php

function themeslug_register_block_categories( array $block_categories, WP_Block_Editor_Context $block_editor_context ): array {

	$block_categories[] = [
	  'slug'  => 'custom-category',
	  'title' => __( 'Custom Category', 'themeslug' ),
	  'icon'  => 'admin-site',
	];

	return $block_categories;
}
add_action( 'block_categories_all', 'themeslug_register_block_categories', 10, 2 );

We are passed in an array of all the current categories. So we just want to append a new array with our category details. The array has three properties: slug, title, and icon.

And now our block is in the correct “Custom Category” category.

You can add an icon from Dashicons to this array, but you can’t add a custom icon at this point. Similar to when we are registering a new block and we add the icon to the block.json file, we can only add dashicons.

Categories vs Collections

Another way to group your blocks in the sidebar is with a Collection. A Collection is based on the namespace of the registered blocks. While your custom blocks for your plugin or theme might go into different categories, you can easily group them all together in one Collection. That way it’s easy to see what blocks were added from that source.

There is no PHP hook to register the collection, you’ll need to do it with javascript.

editor.js
import domReady from '@wordpress/dom-ready';

const customCategoriesAndIcons = () => {

  wp.blocks.registerBlockCollection( 'theme-slug', {
    title: 'Theme Slug',
    slug: 'theme-slug',
    icon: 'admin-site',
  });
  
}

domReady( customCategoriesAndIcons );

You’ll also need to enqueue this file with the enqueue_block_editor_assets hook.

PHP
function theme_slug_front_end_scripts() {

	$asset_file   = include get_template_directory() . '/js/scripts.asset.php';
	$dependencies = $asset_file['dependencies'];

	wp_enqueue_script(
    'theme-slug-front-end-scripts',
    get_template_directory_uri() . '/js/scripts.js',
    $dependencies,
    $asset_file['version'],
    true
  );
}
add_action( 'wp_enqueue_scripts', 'theme_slug_front_end_scripts' );

In this registration I’ve used the same dashicon. But now that we are registering the icon in javascript we open up some of the customization options that we saw with blocks.

From my testing I have not been able to pass in an object to the icon with a background foreground and src properties like we can when we use registerBlockType.

JavaScript
wp.blocks.registerBlockCollection('theme-slug', {
	title: 'Theme Slug',
	slug: 'theme-slug',
	icon: { // This does not work
		'background': '#21759b',
		'foreground': '#ffffff',
		'src': 'admin-site'
	}
});

Doing so causes an error in the editor:

Objects are not valid as a React child (found: [missing argument]). If you meant to render a collection of children, use an array instead.

However you can add a custom svg icon here.

JavaScript
wp.blocks.registerBlockCollection( 'theme-slug', {
		title: 'Theme Slug',
		slug: 'theme-slug',
		icon: (
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="8.37 14 83.27 72.02"><path d="M70 86a1.601 1.601 0 0 1-1.602-1.602V61.2a1.606 1.606 0 0 1 1.063-1.5l20-7.148a1.599 1.599 0 0 1 2.14 1.5v22.25c0 .652-.398 1.238-1 1.48l-20 8.102A1.586 1.586 0 0 1 70 86zm1.602-23.672v19.695l16.8-6.809-.003-18.89z"/><path d="M70 86c-.207 0-.41-.04-.602-.117l-20-8.102c-.601-.242-1-.828-1-1.48V54.05a1.603 1.603 0 0 1 2.141-1.505l20 7.15a1.602 1.602 0 0 1 1.063 1.503v23.2A1.6 1.6 0 0 1 70 86zM51.602 75.219l16.801 6.809-.004-19.7-16.797-6.003z"/><path d="M70 62.801c-.184 0-.367-.031-.54-.094l-20-7.148v-.004a1.598 1.598 0 1 1 1.08-3.012L70 59.5l19.461-6.957a1.602 1.602 0 0 1 2.047.965 1.603 1.603 0 0 1-.969 2.047l-20 7.148a1.496 1.496 0 0 1-.539.098z"/><path d="M90 55.652c-.207 0-.41-.04-.602-.117L70 47.675l-19.398 7.86a1.598 1.598 0 0 1-2.058-.895 1.598 1.598 0 0 1 .855-2.07l20-8.102a1.603 1.603 0 0 1 1.203 0l20 8.102a1.6 1.6 0 0 1 .973 1.79 1.606 1.606 0 0 1-1.574 1.292z"/><path d="M50 55.652a1.601 1.601 0 0 1-1.602-1.602V30.851c0-.675.426-1.277 1.063-1.507l20-7.149a1.605 1.605 0 0 1 2.14 1.508v22.246c0 .652-.398 1.238-1 1.48l-20 8.102a1.669 1.669 0 0 1-.601.121zm1.602-23.668v19.691l16.797-6.805V25.975z"/><path d="M50 55.652c-.207 0-.41-.04-.602-.117l-20-8.102c-.601-.242-1-.828-1-1.48v-22.25a1.603 1.603 0 0 1 2.141-1.505l20 7.15v.003a1.597 1.597 0 0 1 1.063 1.504v23.199A1.6 1.6 0 0 1 50 55.656zM31.602 44.871l16.801 6.809-.004-19.695-16.797-6.008z"/><path d="M50 32.457c-.184 0-.367-.031-.54-.094l-20-7.152a1.582 1.582 0 0 1-.933-.816 1.597 1.597 0 0 1 .77-2.157c.39-.18.84-.191 1.242-.039L50 29.156 69.461 22.2a1.604 1.604 0 0 1 2.047.969 1.604 1.604 0 0 1-.969 2.047l-20 7.152v-.004a1.581 1.581 0 0 1-.539.094z"/><path d="M70 25.305c-.207 0-.41-.04-.602-.117L50 17.328l-19.398 7.86a1.602 1.602 0 0 1-2.093-2.11c.172-.394.492-.703.89-.855l20-8.102a1.603 1.603 0 0 1 1.203 0l20 8.102a1.6 1.6 0 0 1-.601 3.082zM30 86a1.601 1.601 0 0 1-1.602-1.602V61.2a1.606 1.606 0 0 1 1.063-1.5l20-7.148a1.599 1.599 0 0 1 2.14 1.5v22.25c0 .652-.398 1.238-1 1.48l-20 8.102A1.586 1.586 0 0 1 30 86zm1.602-23.672v19.695l16.8-6.809-.003-18.89z"/><path d="M30 86c-.207 0-.41-.04-.602-.117l-20-8.102c-.601-.242-1-.828-1-1.48V54.05a1.603 1.603 0 0 1 2.141-1.505l20 7.15a1.602 1.602 0 0 1 1.063 1.503v23.2A1.6 1.6 0 0 1 30 86zM11.602 75.219l16.801 6.809-.004-19.7-16.797-6.003z"/><path d="M30 62.801c-.184 0-.367-.031-.54-.094l-20-7.148v-.004a1.598 1.598 0 1 1 1.08-3.012L30 59.5l19.461-6.957a1.602 1.602 0 0 1 2.047.965 1.603 1.603 0 0 1-.969 2.047l-20 7.148a1.496 1.496 0 0 1-.539.098z"/><path d="M50 55.652c-.207 0-.41-.04-.602-.117L30 47.675l-19.398 7.86a1.602 1.602 0 0 1-2.093-2.11c.172-.394.492-.703.89-.855l20-8.102a1.603 1.603 0 0 1 1.203 0l20 8.102a1.6 1.6 0 0 1 .973 1.789 1.606 1.606 0 0 1-1.574 1.293z"/></svg>
	)
});

Now we get our fun stacked blocks icon next to our Block Collection.

Using Custom SVG’s for Block Category Icon

Since we have already registered our custom category in PHP, we will need to update the category to give it a custom icon. Note, if you added an icon like a dashicon during the initial registration adding this script will replace that icon.

I’ll add this is the same file as my block collection registration from above. It’s in the same function that gets run on domReady.

editor.js
wp.blocks.updateCategory('custom-category', {
	icon: (
			<svg xmlns="http://www.w3.org/2000/svg" viewBox="10.07 15.08 79.85 69.83"><path fill="none" stroke="#000" strokeLinecap="round" strokeLinejoin="round" strokeMiterlimit="10" strokeWidth="2" d="M27.5 42.5h45v20h-45zm0 0"/><path fill="none" stroke="#000" strokeLinecap="round"strokeLinejoin="round" strokeMiterlimit="10"strokeWidth="2"d="M32.504 37.5h5v5.004h-5zm9.996-15h45v20h-45zm5.004-5h5v5h-5zm15 0h5v5h-5zm15 0h5v5h-5zM12.5 62.5h45v20h-45zm5-5.004h5V62.5h-5zm0 0"/></svg>
	)
});

We pass in the slug of the category as the first argument, then an object with our updates. We’re only updating the icon so that’s all we need, and now our custom category has a different stacked block icon.

Since we have this function to update categories, we could also update a core category.

editor.js
wp.blocks.updateCategory('text', {
	icon: (
		<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
			<path d="M26 29h14v42h-8v6h22v-6h-8V29h14v6h6v-9a3 3 0 0 0-3-3H23a3 3 0 0 0-3 3v9h6z"/>
			<path d="M65 44v8h-8v6h8v10c0 4.969 4.031 9 9 9h6v-6h-6a3 3 0 0 1-3-3V58h8v-6h-8v-8z"/>
		</svg>
	)
});

Now should we actually add icons to core categories?

Should I have even told you that was a possibility?

Probably not, so … sorry everyone!

Examples from the wild

Love it or hate it, Jetpack adds a lot of functionality to a site. One thing I do like about Jetpack is all the icons for their blocks and categories use their brand green which make it very easy to spot. Now we probably don’t want everyone adding a bunch of colors to the sidebar. But I think for Jetpack it makes a lot of sense.

Media category with Jetpack blocks

They also register a Block Collection so you can see all of the blocks that are added with the plugin.

The first 9 Jetpack Blocks of the 45 added (as of August 2024)

Wrapping things up

That does it for adding icons to Categories and Collections in the WordPress sidebar. If you want to add icons to your blocks, check out my other post.


in

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *