So, you’ve got a classic Metabox on your WordPress site, and you’re looking to bring it into the shiny new Gutenberg editor as a sidebar panel. It’s a pretty common desire, and thankfully, it’s not an impossible task with the right tools. The key player here is PluginDocumentSettingPanel. It’s essentially the official way to inject custom settings and controls into the editor’s sidebar, right where users expect to find them.
Migrating a Metabox isn’t just about making things look modern; it’s about integrating your content management into the Gutenberg workflow more smoothly. This means your metabox options will be alongside other document settings, offering a more cohesive editing experience for your users.
This guide will walk you through the process, breaking down what you need to do and why. We’ll focus on practical steps and the essential code snippets to get your Metabox transformed into a Gutenberg-ready sidebar panel.
Before we dive into the “how,” let’s quickly touch on the “why.” Classic Metaboxes, while functional, often felt like afterthoughts in the WordPress editing flow. They were tucked away, sometimes disconnected from the main content editing area.
Gutenberg, on the other hand, aims for a more unified editing experience. By moving your Metabox content to a sidebar panel, you’re leveraging this unified approach.
Better User Experience
Imagine a user editing a post. They need to adjust some specific post settings related to your custom functionality. In the classic editor, they might have to scroll down, find the Metabox, and interact with it. In Gutenberg, if it’s in the sidebar, it’s right there, alongside other essential settings like featured images, categories, and tags. This immediacy can make a big difference in how intuitive and efficient the editing process feels.
Modernization and Future-Proofing
WordPress development is increasingly leaning towards Gutenberg. By migrating your Metaboxes, you’re ensuring your site’s custom functionality stays relevant and compatible with future WordPress updates. It shows you’re keeping pace with the platform’s evolution.
Integration with Gutenberg’s Ecosystem
Gutenberg has its own set of components and best practices. By using PluginDocumentSettingPanel, you’re tapping into this ecosystem, making your custom features feel like a natural part of the editor, not an add-on.
If you’re looking to enhance your WordPress development skills, you might find it useful to explore related articles that delve into the intricacies of the Gutenberg editor. One such article is about the various ways to customize the Gutenberg experience, which can provide additional insights into working with the PluginDocumentSettingPanel. For more information, you can check out this article at The Sheryar.
The Core Component: PluginDocumentSettingPanel
The star of the show, as mentioned, is PluginDocumentSettingPanel. This is a React component provided by the WordPress core specifically for this purpose. It allows you to create a collapsible panel within the document settings sidebar.
Think of it as a dedicated container for your Metabox’s fields, but positioned in a much more user-friendly and integrated location.
What it Does
At its heart, PluginDocumentSettingPanel takes care of the UI structure of a sidebar panel. You provide it with the content you want to display inside, and it handles the collapsible behavior, the title of the panel, and its placement in the sidebar.
Essential Props
When you use PluginDocumentSettingPanel, you’ll be working with its props. The most important ones are:
title: This is the text that appears at the top of your panel. It should clearly indicate the purpose of the settings within.icon: An optional WordPress dashicon or custom SVG to visually represent your panel.initialOpen: A boolean to determine if the panel should be open or collapsed when the editor loads. Usually, you’ll want this to betruefor immediate visibility.children: This is where the magic happens! You’ll place all your custom input fields and controls (text inputs, select menus, checkboxes, etc.) within thechildrenprop.
Bringing Your Metabox Fields Over: The Migration Process
This is where the real work begins. You’ll need to take the existing fields from your classic Metabox and rebuild them using Gutenberg’s block editor JavaScript API, specifically with React and the components provided by @wordpress/components and @wordpress/block-editor.
Step 1: Identify Your Metabox Fields
First, go through your existing classic Metabox code. List out every single field you have: text inputs, textarea, select dropdowns, checkboxes, radio buttons, etc. For each field, note its purpose and the data it stores.
Step 2: Set Up Your Gutenberg Development Environment
If you haven’t already, you’ll need a development environment for Gutenberg blocks. This typically involves:
- A local WordPress installation.
- A custom plugin where you’ll house your Gutenberg integration code.
- Node.js and npm (or yarn) for managing JavaScript dependencies and building your assets.
- The
@wordpress/scriptspackage for easy build processes.
You can usually set this up in your custom plugin’s directory by running npm init -y and then npm install @wordpress/scripts @wordpress/components @wordpress/block-editor @wordpress/i18n --save. You’ll also need to configure your package.json to use @wordpress/scripts for building.
Step 3: Create the React Component for Your Panel Content
This is the core of the migration. You’ll create a React component that will house all your repurposed Metabox fields.
Let’s say your classic Metabox had a “Post Layout” select field. In Gutenberg, you’d create a component for this.
“`javascript
import { SelectControl } from ‘@wordpress/components’;
import { __ } from ‘@wordpress/i18n’;
function PostLayoutControl( { value, onChange } ) {
const options = [
{ label: __( ‘Default’, ‘your-textdomain’ ), value: ‘default’ },
{ label: __( ‘Full Width’, ‘your-textdomain’ ), value: ‘full-width’ },
{ label: __( ‘Sidebar Left’, ‘your-textdomain’ ), value: ‘sidebar-left’ },
{ label: __( ‘Sidebar Right’, ‘your-textdomain’ ), value: ‘sidebar-right’ },
];
return (
label={ __( ‘Post Layout’, ‘your-textdomain’ ) } value={ value } options={ options } onChange={ ( newValue ) => onChange( newValue ) } /> ); } export default PostLayoutControl; “` You’ll repeat this process for all your fields, using appropriate components from Your Metabox fields store data in the database, usually using Gutenberg operates on the concept of “`javascript import { useSelect, useDispatch } from ‘@wordpress/data’; import { PluginDocumentSettingPanel } from ‘@wordpress/edit-post’; import { useState, useEffect } from ‘@wordpress/element’; import { __ } from ‘@wordpress/i18n’; // Assume PostLayoutControl is imported as above function MigratedMetaboxPanel() { const { editPost } = useDispatch( ‘core/editor’ ); const meta = useSelect( ( select ) => select( ‘core/editor’ ).getEditedPostAttribute( ‘meta’ ), [] ); // Get the current value of our meta field const currentLayout = meta && meta.my_post_layout_meta_key ? meta.my_post_layout_meta_key : ‘default’; const handleLayoutChange = ( newValue ) => { editPost( { meta: { my_post_layout_meta_key: newValue, }, } ); }; return ( title={ __( ‘Advanced Layout Settings’, ‘your-textdomain’ ) } icon=”layout” initialOpen={ true } > value={ currentLayout } onChange={ handleLayoutChange } /> { / Add other migrated fields here / } ); } export default MigratedMetaboxPanel; “` Important Notes on Data Handling: Finally, you need to tell WordPress about your new panel and where to render it. You’ll use the “`javascript // In your plugin’s admin.js or similar JS file import { registerPlugin } from ‘@wordpress/plugins’; import MigratedMetaboxPanel from ‘./migrated-metabox-panel’; // Adjust the path // Register the panel registerPlugin( ‘my-migrated-metabox-panel’, { render: MigratedMetaboxPanel, icon: ‘post-status’, // Optional: a dashicon } ); “` This code registers your Before your JavaScript can interact with your custom fields, you need to register them with WordPress using PHP, specifically using This step is crucial not only for the frontend Gutenberg editor but also for ensuring your data is saved correctly and can be accessed elsewhere in WordPress (like in your theme templates). You’ll typically do this in your plugin’s “`php
/** */ function my_plugin_register_custom_meta_fields() { // Post Layout Meta Field register_post_meta( ‘post’, ‘my_post_layout_meta_key’, array( ‘show_in_rest’ => true, // Important for Gutenberg! ‘single’ => true, ‘type’ => ‘string’, ‘sanitize_callback’ => ‘sanitize_text_field’, // Use appropriate callbacks ‘auth_callback’ => function() { // Optional: restrict who can edit return current_user_can( ‘edit_posts’ ); }, ) ); // Example: Text field for a subtitle register_post_meta( ‘post’, ‘my_subtitle_meta_key’, array( ‘show_in_rest’ => true, ‘single’ => true, ‘type’ => ‘string’, ‘sanitize_callback’ => ‘sanitize_text_field’, ) ); // Example: Checkbox for featured status register_post_meta( ‘post’, ‘my_featured_status_meta_key’, array( ‘show_in_rest’ => true, ‘single’ => true, ‘type’ => ‘boolean’, // ‘boolean’ for true/false ‘sanitize_callback’ => ‘rest_sanitize_boolean’, ) ); // Add more register_post_meta calls for all your metabox fields } add_action( ‘init’, ‘my_plugin_register_custom_meta_fields’ ); “` Key Parameters for You also need to make sure your compiled JavaScript file (the one containing your React components and “`php
/** */ function my_plugin_enqueue_editor_assets() { $asset_file = include( plugin_dir_path( __FILE__ ) . ‘build/index.asset.php’); // If using @wordpress/scripts wp_enqueue_script( ‘my-migrated-metabox-script’, // Unique handle plugin_dir_url( __FILE__ ) . ‘build/index.js’, // Path to your compiled JS file $asset_file[‘dependencies’], // Dependencies automatically handled by @wordpress/scripts $asset_file[‘version’] ); } add_action( ‘enqueue_block_editor_assets’, ‘my_plugin_enqueue_editor_assets’ ); “` Here, If you’re looking to enhance your WordPress development skills, you might find the article on migrating classic metaboxes to Gutenberg sidebar panels particularly useful. This guide provides a step-by-step approach to utilizing the PluginDocumentSettingPanel for a seamless transition. For more insights on this topic, you can check out this related article that delves deeper into the nuances of working with Gutenberg and customizing your editing experience. Your classic Metabox likely had a variety of input types. You’ll need to map these to their Gutenberg equivalents. The For simple text inputs and textareas, use “`javascript import { TextControl, TextareaControl } from ‘@wordpress/components’; import { useSelect, useDispatch } from ‘@wordpress/data’; import { __ } from ‘@wordpress/i18n’; function SubtitleControl() { const { editPost } = useDispatch( ‘core/editor’ ); const meta = useSelect( ( select ) => select( ‘core/editor’ ).getEditedPostAttribute( ‘meta’ ), [] ); const currentSubtitle = meta && meta.my_subtitle_meta_key ? meta.my_subtitle_meta_key : ”; const handleSubtitleChange = ( newValue ) => { editPost( { meta: { my_subtitle_meta_key: newValue, }, } ); }; return ( label={ __( ‘Post Subtitle’, ‘your-textdomain’ ) } value={ currentSubtitle } onChange={ handleSubtitleChange } /> ); } // Add this to your MigratedMetaboxPanel children “` “`javascript import { SelectControl } from ‘@wordpress/components’; // … other imports function MySelectField() { // … data fetching and onChange logic using useSelect and useDispatch const options = [ { label: __( ‘Option 1’, ‘your-textdomain’ ), value: ‘option1’ }, { label: __( ‘Option 2’, ‘your-textdomain’ ), value: ‘option2’ }, ]; return ( label={ __( ‘Choose Option’, ‘your-textdomain’ ) } value={ currentValue } options={ options } onChange={ ( newValue ) => onChange( newValue ) } /> ); } “` “`javascript import { ToggleControl } from ‘@wordpress/components’; // … other imports function FeaturedStatusToggle() { const { editPost } = useDispatch( ‘core/editor’ ); const meta = useSelect( ( select ) => select( ‘core/editor’ ).getEditedPostAttribute( ‘meta’ ), [] ); const isFeatured = meta && meta.my_featured_status_meta_key ? meta.my_featured_status_meta_key : false; const handleToggleChange = ( newValue ) => { editPost( { meta: { my_featured_status_meta_key: newValue, }, } ); }; return ( label={ __( ‘Mark as Featured’, ‘your-textdomain’ ) } checked={ isFeatured } onChange={ handleToggleChange } /> ); } “` If your Metabox had complex fields like repeaters (allowing users to add multiple rows of data), this is where the migration becomes more involved. You’ll likely need to: This is an advanced topic and might require a deeper dive into React state management and custom Gutenberg block development principles. Once you’ve made the migrations and set up your JavaScript and PHP, thorough testing is essential. Once you’re confident in your local tests: Migrating classic Metaboxes to Gutenberg sidebar panels is a rewarding process that significantly improves the user experience and modernizes your WordPress site. By leveraging @wordpress/components like TextControl, TextareaControl, ToggleControl, RadioControl, etc.Step 4: Fetch and Save Data
meta_key options. You need to bridge this with Gutenberg’s state management.postMeta. You’ll use the useSelect hook from @wordpress/data to retrieve the existing meta values and the editPost action to update them.
meta_key names in the JavaScript match exactly those used in your PHP (when registering them with register_post_meta).getEditedPostAttribute('meta'): This hook retrieves all post meta attributes for the currently edited post in Gutenberg.editPost({ meta: { ... } }): This action is used to update post meta. It’s important to pass an object with the meta key.onChange handlers to update the post meta.Step 5: Registering Your Panel
editor.Post.EditPanel filter to achieve this. This is done in your plugin’s JavaScript file, typically enqueued for the block editor.MigratedMetaboxPanel component under a unique plugin name (my-migrated-metabox-panel). When Gutenberg loads, it will be rendered within the editor’s sidebar.PHP-Side Setup: Registering Post Meta
register_post_meta(). This tells WordPress that these meta fields exist and how they should be handled.Registering Your Meta Fields
functions.php or a dedicated plugin file.
register_post_meta():
$meta_type: This will be 'post' for posts, 'page' for pages, etc.$meta_key: This is the unique identifier for your meta field. This key MUST match the one you use in your JavaScript (meta.your_meta_key).$args: An array of arguments:show_in_rest: This is paramount. Set this to true to make your meta field available to the REST API, which Gutenberg relies on for data.single: Set to true if your field stores a single value (most common).type: The data type of your meta field. Common types include 'string', 'integer', 'boolean', 'array', 'object'.sanitize_callback: A function that sanitizes the data before it’s saved. This is a vital security measure. Use appropriate WordPress functions like sanitize_text_field, absint, rest_sanitize_boolean, etc.auth_callback: An optional callback to determine if the current user has permission to edit this meta field.Enqueuing Your JavaScript
registerPlugin call) is enqueued correctly for the block editor.
enqueue_block_editor_assets is the hook that fires only when the block editor is active.Handling Different Field Types
@wordpress/components library is your best friend here.Text and Textarea Fields
TextControl and TextareaControl respectively.Select and Radio Fields
SelectControl is used for dropdowns, and RadioControl for radio buttons. The structure is very similar to the PostLayoutControl example shown earlier.Checkbox and Toggle Fields
ToggleControl is the modern way to handle boolean (on/off) values. For multiple checkboxes that represent a single setting (e.g., specific features enabled), you might need a more custom approach or use a CheckboxControl for each and manage an array/object in your meta.Complex Fields (e.g., Repeater Fields)
TextControl, SelectControl, etc.useSelect to fetch the existing array/object from postMeta.editPost to update the entire array/object when changes occur within your repeater component.Testing and Deployment
Local Testing
Troubleshooting
show_in_rest: true: Double-check this is set for all your register_post_meta calls.@wordpress/scripts.Deployment
npm run build if using @wordpress/scripts). This will compile your JavaScript and CSS into production-ready files.plugins directory or ensure your theme has the necessary enqueueing code.PluginDocumentSettingPanel and understanding how to work with Gutenberg’s data APIs, you can seamlessly integrate your custom functionality into the block editor.