Restrict <PanelBody> in Plugin Sidebars by Post Type

When I create settings for Posts, Pages or any custom post type, I always use Gutenberg plugin sidebars. But the thing is that sometimes you do not want to create a separate sidebar for every post type, you’d rather prefer to display some panels (or even fields) for one post type and the other panels for another one.

Like here:

Restrict Gutenberg Sidebar Panels by Post type
In this example our “Post Meta” plugin sidebar consists of two panels, the first one is displayed for every custom post type, the second one – only for Pages.

Here is the ready code in ESNext.

( function( wp ) {

	const { registerPlugin } = wp.plugins;
	const { PluginSidebar } = wp.editPost;
	const { PanelBody } = wp.components;

	const { withSelect } = wp.data;
	const { compose } = wp.compose;

	const MishaSidebar = ( { postType } ) => {

		return (
		
			<PluginSidebar
				name="misha-sidebar"
				title="Post Meta"
			>
					<PanelBody title="Any post type">
					   <p>This is gonna be displayed for all post types.</p>
					</PanelBody>

					{
						'page' == postType &&
							<PanelBody title="Only for Pages" initialOpen={ false }>
								<p>This panel is going to be displayed only for page post type.</p>
							</PanelBody>
					}

			</PluginSidebar>

		)
	}

	// we are going to use withSelect in order for postype to be available inside
	const MishaSidebarwithSelect = withSelect( select => {
		return {
			postType: select( 'core/editor' ).getCurrentPostType(),
		};
	} )( MishaSidebar );

	// register that sidebar
	registerPlugin( 'misha-panel', { render: MishaSidebarwithSelect } );


} )( window.wp );

As you can see in example above, we are using withSelect, which is HOC (a Higher Order Component), it extends our MishaSidebar component a little bit by providing a custom post type name, which will be merged with the component.

If you would like to add multiple post types into the condition, you can do it this way:

{
	( 'page' == postType || 'post' == postType ) &&
		<PanelBody title="Only for Pages" initialOpen={ false }>

You can also easily disable the whole sidebar with these lines of code:

const MishaSidebar = ( { postType } ) => {

	if ( 'page' !== postType ) {
		return null;
	}
Misha Rudrastyh

Misha Rudrastyh

Hey guys and welcome to my website. For more than 10 years I've been doing my best to share with you some superb WordPress guides and tips for free.

Need some developer help? Contact me

Follow me on X