Skip to Content
Everything you need to create a WP plugin sidebar with React/Material UI.

Everything you need to create a WP plugin sidebar with React/Material UI.

Looking to create your own PluginSidebar but want to use React or Material UI for your components instead of createElement? Look no further! This post walks you through creating a Plugin, Creating the Plugin Sidebar, Webpack & Babel Configurations, and Using WordPress Data stores to hook up to Material UI components. This post has everything you need to create a WP plugin sidebar with react/material UI.

Estimated reading time: 8 minutes

Create your first block and plugin quickly using WordPress Create-Block

While the Create-Block plugin is specifically built for creating a WordPress block quickly and easily, it is also useful here in creating a scaffolded plugin. This allows us to create a plugin quickly with minimal set up that we can start using right away.

Get started with Create-Block

Open your plugin folder in your code editor. I use VSCode with the terminal.

In the terminal run npx @wordpress/create-block@latest fancy-plugin

Change directories into the fancy-plugin folder:

 cd fancy-plugin

Want to learn how to create multiple blocks in your new block plugin? Don’t miss this post to learn how to register multiple blocks with @wordpress/create-block.

Create the Plugin Sidebar File

Now that we’ve created a plugin, to create a WP plugin sidebar with react/material UI let’s go inside the /src directory and create a js file that will handle the creation of the “Plugin Sidebar”. I’ll call it plugin-sidebar.js

Inside this file, I’ll just scaffold some code here until I can start building with Material UI. The following code just provides me a little template to work with.

import { registerPlugin } from '@wordpress/plugins'

registerPlugin('fancy-sidebar', {
	render: 'el',
	icon: 'el'
})

All we’re doing here is using the registerPlugin function to name our sidebar. Later we’re going to provide it an MUI Icon and a function to Render our React components in the Site Editor Sidebar.

Enqueue the Plugin Sidebar file

In my fancy-plugin.php file, now I need to enqueue this script so that it’s available in the editor.

The following code registers the plugin-sidebar.js script and tells WordPress to find this file in the /src directory.

In the wp_register_script() funciton, we’re also telling WordPress that we have 3 dependencies. These are actual packages from WordPress.

  • wp-plugins
  • wp-edit-post
  • wp-element

Then we enqueue the script we just registered.

/**
 * Register plugin sidebar.
 */
function sidebar_plugin_register() {
    wp_register_script(
        'plugin-sidebar-js',
        plugins_url( '/src/plugin-sidebar.js', __FILE__ ),
        array( 'wp-plugins', 'wp-edit-post', 'wp-element' )
    );
}
add_action( 'init', 'sidebar_plugin_register' );

function sidebar_plugin_script_enqueue() {
    wp_enqueue_script( 'plugin-sidebar-js' );
}
add_action( 'enqueue_block_editor_assets', 'sidebar_plugin_script_enqueue' );

Ensure your script is working

To test if this worked, navigate to the site editor and open up devtools. Next navigate to the Network -> JS tabs and search for the js file you enqueued. As you can see in the image below, I’m searching for plugin-sidebar and I see my file is there and has a status of 200.

chrome devtools network tab shows the plugin-sidebar.js file loaded with a 200 status code

If you are getting a 404 status, you likely need to update the following line of code to ensure the plugin can find the js file:

plugins_url( '/src/plugin-sidebar.js', __FILE__ ),

This code is telling WordPress to find the plugin-sidebar.js file in the Plugin Directory -> src folder.

Install our Dependencies

To build a WordPress Plugin Sidebar with Material UI, we’re going to need to install several dependencies.

Let’s ensure we have the WordPress packages installed and ready to use by first installing them in the terminal:

npm install @wordpress/plugins @wordpress/edit-post @wordpress/element --legacy-peer-deps  

Let’s install Material UI with their styled components. In your terminal run the following commands:

npm install @mui/material @emotion/react @emotion/styled

Next let’s import the Material UI styled components so we don’t have to worry about any CSS.

npm install @mui/material @mui/styled-engine-sc styled-components

Then, we’re going to want to use Material UI icons as well so let’s install those too:

npm install @mui/icons-material

Webpack and Babel configuration

Since we want to create a WP plugin sidebar with react/material UI, we can’t get React and Material UI working in our Plugin without making some webpack and pabel configurations to ensure everything loads as it should.

Install Dependencies

Yes we are installing more dependencies. These are needed to ensure our Javascript loads and builds as we’d expect it to.

Without these configurations, React and Material UI simply won’t work.

Run each of these installs one after another:

npm install @babel/core babel-loader @babel/preset-env @babel/preset-react @babel/plugin-proposal-class-properties @babel/plugin-syntax-dynamic-import css-loader style-loader html-webpack-plugin webpack webpack-dev-server webpack-cli -D
npm install @wordpress/babel-preset-default -D   
npm install react react-dom prop-types react-router-dom semantic-ui-react -D
npm install dotenv -D    
npm install babel-plugin-direct-import -D

The .env file

In your root directory, create a file titled .env and add the following code. Just be sure to update your dev url to the IP and PORT you’re using as your development server. For instance http://localhost:3000.

DEV_URL="http://localhost:3000

If you use Local by Flywheel, you can find your dev url in your site’s Overview -> Site host. Or simply look in the address bar of your browser to see what your server IP and PORT are.

The .babelrc file

In your root directory, create a file titled .babelrc then paste the following in:

{
	"presets": [ "@wordpress/babel-preset-default", "@babel/preset-react", "@babel/preset-env"],
	"plugins": [
		["@babel/plugin-transform-react-jsx"],
		[
			"babel-plugin-direct-import",
			{"modules": ["@mui/material", "@mui/icons-material", "@mui/styled-engine"] }
		]
	]
}

These presets allow webpack to compile the WordPress, React, and Material UI modules in a way that the browser can use them.

The webpack.config files

In your root directory, create a file named as follows:

  • weback.config.js

Paste the following code into the config file and save:

const webpack = require('webpack')
const path = require("path") // a node function
const defaultConfig = require("@wordpress/scripts/config/webpack.config")
const DependencyExtractionWebpackPlugin = require( '@wordpress/dependency-extraction-webpack-plugin' );

var dotenv = require('dotenv').config({path: __dirname + '/.env'});

const environment = ({
	'process.env': {
		'process.env.NODE_ENV': JSON.stringify('production'),
	...dotenv.parsed,
	},
})

module.exports = {
	...defaultConfig,
	entry: path.resolve(__dirname, "./src/index.js"),
	module: {
		...defaultConfig.module,
		rules: [
			{
				test: /\.jsx?$/,
				use: "babel-loader",
				exclude: /node_modules/,
			},
			{
				test: /\.js?$/,
				use: "babel-loader",
				exclude: /node_modules/,
			},
		],
	},

	resolve: {
			alias: {
				'@wordpress/block-library/build/group/transforms': path.resolve('node_modules', '@wordpress/block-library/build/group/transforms'),
				'@mui/styled-engine': path.resolve('node_modules', '@mui/styled-engine')
    		},
		...defaultConfig.resolve,
		extensions: [".tsx", ".ts", ".js", ".jsx"],
	},

	output: {
		...defaultConfig.output,
		filename: "[name].js",
		path: path.resolve(__dirname, "./assets/js"),
	},
	plugins: [
		...defaultConfig.plugins.filter(
            ( plugin ) =>
                plugin.constructor.name !== 'DependencyExtractionWebpackPlugin'
        ),
        new DependencyExtractionWebpackPlugin( {
            requestToExternal( request ) {
                if ( request === '@wordpress/block-library/build/group/variations' ) {
				console.log('Got @wordpress/block-library/build/group/variations from node_modules!')
				return ''
				}
            },
        } ),
		new webpack.DefinePlugin(environment),

	],
};

The configuration above will compile your jsx files in a way that allows browsers to read them. There is a lot going on here, but mostly what you need to know is that we’re using the @wordpress/scripts/config/webpack.config as our default configuration which gives us what we need from WordPress.

We’re also adding a couple of rules (one for js and one for jsx) to use the babel-loader.

Another thing we’re doing is we’re adding some aliases to ensure our modules are found within the node_modules folder.

NOTE: the entry property is a file we haven’t created yet.

This file is going to be where webpack gets our JSX files and compiles them into something the browser can understand. Also pay attention to the output path property.

The output path is where our compiled JS will live, and that’s the JS we want to enqueue.

The package.json

Finally, we need to create the commands necessary to run and build this app. Inside our package.json file, we’re going to add a new command in the “scripts” section.

"build:blocksJs": "NODE_ENV=production webpack --config webpack.config.js",

Next we’ll add the following 2 new commands:

"prebuild": "rimraf dist",
"dev": "webpack-dev-server --config webpack.config.js",

Last but most certainly not least, we need to update our build command as follows:

"build": "wp-scripts build && npm run build:blocksJs",

IMPORTANT STEP DON’T SKIP

Now that we have a Javascript file that’s been compiled to work we need to make a couple of adjustments.

In the /src directory create a file titled index.js. Inside this file add an import statement like so:

import './plugin-sidebar'

Update the plugins-sidebar.js file extension to jsx so it looks like this: plugin-sidebar.jsx

And finally, update the fancy-plugin.php file so we’re enqueueing the script from the compiled file not the development file.

/**
 * Register plugin sidebar.
 */
function sidebar_plugin_register() {
	// $src = __DIR__ . '/src';
    wp_register_script(
        'index-js',
        plugins_url( '/assets/js/main.js', __FILE__ ),
        array( 'wp-plugins', 'wp-edit-post', 'wp-element' )
    );
}
add_action( 'init', 'sidebar_plugin_register' );

function sidebar_plugin_script_enqueue() {
    wp_enqueue_script( 'index-js' );
}
add_action( 'enqueue_block_editor_assets', 'sidebar_plugin_script_enqueue' );

Create sidebar settings

Now we can get to the fun part, building a WordPress Plugin Sidebar with React and Material UI! Inside our plugin-sidebar.jsx file, lets import what we’re going to need.

import React from 'react'
import { registerPlugin } from '@wordpress/plugins'
import { PluginSidebar, PluginSidebarMoreMenuItem } from '@wordpress/edit-site'
import AutoAwesomeIcon from '@mui/icons-material/AutoAwesome'

Here we are importing React, of course, and also the PluginSidebar and PluginSidebarMoreMenuItem components from the @wordpress/edit-site package.

These components will allow us to easily insert our own React components in the site editor sidebar we’d expect to see.

NOTE: This sidebar will only appear in the Full Site Editor, not the Post Editor.

Finally, we’re importing a really cool Material UI Icon called AutoAwesomeIcon.

Above the registerPlugin() function, let’s create a React component and utilize the PluginSidebar as follows:

const FancySidebar = () => {
	return (
		<>
			<PluginSidebarMoreMenuItem target="fancy-sidebar" icon="smiley">
				Fancy Settings
			</PluginSidebarMoreMenuItem>
			<PluginSidebar
				name="fancy-sidebar"
				className="fancy-sidebar"
				headerClassName="edit-site-sidebar__panel-tabs"
				icon="smiley"				title="Fancy Settings"
				header="My Material UI Sidebar">
"placeholder"
			</PluginSidebar>
		</>
	)
}

Next let’s update the registerPlugin function to use our nifty icon and brand new function.

registerPlugin('fancy-sidebar', {
	render: FancySidebar,
	icon: () => <AutoAwesomeIcon />
})

Finally, let’s create and use our first Material UI component.

Before you do anything, just to be sure all of our modules are imported, quickly run npm install in your terminal.

In the /src directory, create a folder titled /components. Within the components folder create a jsx file titled ToggleButtons.jsx.

Inside ToggleButtons.jsx we’ll import what we need:

import React from 'react'
import Stack from '@mui/material/Stack'
import Button from '@mui/material/Button'

Then create a default exported function titled ToggleButtons() like so:

export default function ToggleButtons() {
  return (
    <Stack spacing={2} direction="row">
      <Button variant="contained">Open</Button>
      <Button variant="outlined">Close</Button>
    </Stack>
  )
}

Last but not least, back in our plugin-sidebar.jsx file, let’s import and use our buttons. Our completed plugin-sidebar.jsx file should now look like this:

import React from 'react'
import { registerPlugin } from '@wordpress/plugins'
import { PluginSidebar, PluginSidebarMoreMenuItem } from '@wordpress/edit-site'
import AutoAwesomeIcon from '@mui/icons-material/AutoAwesome'
import ToggleButtons from './components/ToggleButtons'

const FancySidebar = () => {
	return (
		<>
			<PluginSidebarMoreMenuItem target="fancy-sidebar" icon={<AutoAwesomeIcon />}>
				Fancy Settings
			</PluginSidebarMoreMenuItem>
			<PluginSidebar
				name="fancy-sidebar"
				className="fancy-sidebar"
				headerClassName="edit-site-sidebar__panel-tabs"
				icon={<AutoAwesomeIcon />}
				title="Fancy Settings"
				header="My Material UI Sidebar">
				<ToggleButtons />
			</PluginSidebar>
		</>
	)
}

registerPlugin('fancy-sidebar', {
	render: FancySidebar,
	icon: () => <AutoAwesomeIcon />
})

Intro to wordpress data stores

If you’re not familiar, WordPress has a really cool way for us to manipulate the editor, blocks, and other aspects within the Gutenberg editor using their Data packages. These data packages are essentially a library of Redux like state management functions. A tab I often have open is this Data Module Reference from WordPress, just bare in mind that the documentation for much of these functions is lacking and in some cases outdated.

We’re going to bind some dispatch functions from the WordPress data store to our Material UI button onClick events.

To do that, we need to install another dependency (sorry!).

In your terminal install the following:

npm install @wordpress/data --save

Want more advanced usage of WordPress data stores? Check out this post on how to hide a block from the inserter.

Dispatch actions with setting events

Now that we have access to the WordPress Data stores, let’s go into our ToggleButtons.jsx file and hook some functions up to the onClick events.

In ToggleButtons.jsx let’s import dispatch from @wordpress/data:

import { dispatch } from '@wordpress/data'

Next let’s create a function for the Open button to tell the user that the Plugin Sidebar we created is already open when they click it:

<Button variant="contained" onClick={() => dispatch('core/notices').createInfoNotice("Plugin Sidebar is already open")}>Open</Button>

I want the Close button to do 2 things; remove all notices, and close the plugin sidebar.

I’ll create a function before my return statement like so:

export default function ToggleButtons() {
	const handleClose = () => {
		dispatch('core/notices').removeAllNotices()
		dispatch('core/edit-site').closeGeneralSidebar('fancy-sidebar')
	}
  return (

Now all I have to do is set the onClick prop to handleClose:

<Button variant="outlined" onClick={handleClose}>Close</Button>

And that’s it! If I run npm run dev or npm run build, I’ll be able to see my Sidebar, and Buttons in action!

Here’s the notification we get when the Open button is clicked:

our plugin sidebar is open in the site editor with two buttons one that says open and one that says closed. there is a message 'Plugin Sidebar is already open"

And here is what we see when the Close button is clicked:

our plugin sidebar is closed in the site editor we can no longer see the buttons. ther message 'Plugin Sidebar is already open" is no longer there

This was an extremely long article. I hope you had fun, learned how to Create a WP plugin sidebar with react/material UI, and found this all very useful!

Photo by Souvik Banerjee on Unsplash