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.

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:

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

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