Add a custom sidebar panel to Gutenberg

WordPress 5.0 will ship with a brand new content editor dubbed Gutenberg. It’s one of – if not the – largest changes to WordPress in the last… ever (?). With change comes anxiety and because this is the Internet, this particular change comes with opinions. Lots and lots of opinions. This post is going to take a massive sidestep around those opinions, and instead focus on something that I haven’t seen published anywhere. I’m going to show you how to add a custom sidebar panel to Gutenberg that can apply to your own custom blocks or, importantly, to existing blocks (whether they be provided by WordPress core, or other plugins)

Going forward in this post, I’m going to assume a fairly high level of familiarity with JavaScript, especially ES6, and also have at least a basic understanding of React. Gutenberg is almost entirely JavaScript (you did learn it deeply, right?).

What is the sidebar?

On a larger screen, Gutenberg’s layout will look a little like screenshot 1 below. If it doesn’t then it’s possible you’re in a full-screen mode. To the right of the ‘Publish’ button, you’ll see a smaller button with a cog on it (which is labeled ‘Settings’). If you click that button, it will toggle the sidebar. You’ll notice I’ve highlighted an area on the right hand side. That’s Gutenberg’s sidebar.

A screenshot of the gutenberg editor, with the document sidebar highlighted.
Screenshot 1: The large-screen gutenberg editor with the sidebar highlighted.

By default, if you haven’t clicked on anything in the main content area, the ‘Document’ tab will be selected at the top of the sidebar. This is for settings and controls that are to do with the document as a whole. If you click on – or add – a block, the sidebar will switch to the ‘Block’ tab. In screenshot 2 below, I’ve clicked on the image block and you’ll see the sidebar has switched to show the settings for that particular block. Each group of settings for a block is contained in a panel. For example in screenshot 2 you’ll see the ‘Image Settings’ panel is currently expanded, and at the very bottom of the screenshot, you’ll see the ‘Link Settings’ panel that’s currently collapsed.

A screenshot of the gutenberg editor, with the block sidebar highlighted.
Screenshot 2: Gutenberg’s sidebar switches to the Block tab when a block is selected in the main content area.

How do I add a custom panel to the sidebar?

Now that we have some of the nomenclature out of the way, we can discuss exactly how to add a custom panel, with a custom field – called a control in Gutenberg parlance – to the block sidebar. Screenshot 3 shows us exactly what we’re going to create.

A screenshot of the gutenberg editor, with a new custom panel in the block sidebar highlighted.
Screenshot 3: The block sidebar for a paragraph block with our added custom panel and control highlighted.

If you’ve developed metaboxes and custom fields for WordPress in the past, you can think of the sidebar panel as being the metabox, and the control as being the custom field. However, the control differs from a custom field insofar as the control directly ties to a block. Further, a control can impact how a block looks or functions in the main content area alongside where it’s being manipulated as well as on the front-end of your site.

There’s 3 parts to adding a sidebar control in your own custom panel.

  1. Register the panel and place the control within your panel
  2. Register an attribute on the block(s) which your control will, err, control
  3. Handle saving the custom data to the props of the block

Each of these is made possible by hooking into a filter provided within Gutenberg. Just like you have done in the past in PHP – using actions and filters – you’re able to do the same in JavaScript.

Registering the custom panel

Here’s the code to do register our custom panel, with a text input control in it:

(Sorry I can’t embed this code in this site right now, my syntax highlighter plugin hates it for some reason)

You’ll notice a call to isValidBlockType() in there. This is a custom function which basically allows you to determine which blocks you want your sidebar panel to display on. It is passed the name of a block. At the end of this post is a list of the currently available (as of Oct 4th 2018, and version 4.0 RC1 of Gutenberg) block names.

So now we have a panel and a text control. The other 2 pieces of our puzzle need to be handled at the same time. Here’s the code to add the attribute and props:

Right now, as it stands, we have all the pieces in place, however, we haven’t specified our dependencies. Those go at the top of our file, and are thus:

Put all those pieces together and you’ll have your custom control, in your custom panel, that will (in this example) show up if you click on either a paragraph, image, or heading block but not if you click on any other block. The data saving is handled for you automagically by Gutenberg, so when the post is updated/published, your data will remain.

I’d like to thank, wholeheartedly, all of the folks who are working so hard on making Gutenberg amazing. It’s no small task they’re undertaking, and I’ve been delighted to see how much progress has been made in the past few weeks and months. Gutenberg is the future of WordPress. It might be the future of content management systems as a whole.

Also I’d like to thank Timothy Jacobs and others in the PostStatus slack team for help with pointing me in the right direction with this code.

List of available core block names as of Gutenberg 4.0 RC1

core/paragraph
core/image
core/heading
core/gallery
core/list
core/quote
core/shortcode
core/archives
core/audio
core/button
core/categories
core/code
core/columns
core/column
core/cover-image
core/embed
core/file
core/freeform
core/html
core/latest-comments
core/latest-posts
core/more
core/nextpage
core/preformatted
core/pullquote
core/separator
core/block
core/spacer
core/subhead
core/table
core/template
core/text-columns
core/verse
core/video
core-embed/twitter
core-embed/youtube
core-embed/facebook
core-embed/instagram
core-embed/wordpress
core-embed/soundcloud
core-embed/spotify
core-embed/flickr
core-embed/vimeo
core-embed/animoto
core-embed/cloudup
core-embed/collegehumor
core-embed/dailymotion
core-embed/funnyordie
core-embed/hulu
core-embed/imgur
core-embed/issuu
core-embed/kickstarter
core-embed/meetup-com
core-embed/mixcloud
core-embed/photobucket
core-embed/polldaddy
core-embed/reddit
core-embed/reverbnation
core-embed/screencast
core-embed/scribd
core-embed/slideshare
core-embed/smugmug
core-embed/speaker
core-embed/speaker-deck
core-embed/ted
core-embed/tumblr
core-embed/videopress
core-embed/wordpress-tv