{"id":63,"date":"2022-11-18T15:18:25","date_gmt":"2022-11-18T15:18:25","guid":{"rendered":"https:\/\/developer.wordpress.org\/news\/?p=63"},"modified":"2023-09-07T13:51:12","modified_gmt":"2023-09-07T13:51:12","slug":"how-to-extend-wordpress-via-the-slotfill-system","status":"publish","type":"post","link":"https:\/\/developer.wordpress.org\/news\/2022\/11\/how-to-extend-wordpress-via-the-slotfill-system\/","title":{"rendered":"How to extend WordPress via the SlotFill system"},"content":{"rendered":"\n<div class=\"wp-block-group is-layout-constrained wp-block-group-is-layout-constrained\">\n<p class=\"wp-block-paragraph\">WordPress developers have relied on <a href=\"https:\/\/codex.wordpress.org\/Plugin_API\/Hooks\">Hooks AP<\/a>I since version 2.0 to extend the functionality of WordPress and until WordPress 5.0, it was the only way.&nbsp;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In WordPress 5.0, the WordPress SlotFill system was introduced as part of the Gutenberg project and is the extension paradigm that allows developers to extend the UIs introduced with the Gutenberg project such as the Post Editor and the Site Editor.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">At a high level, the SlotFill system is an extension paradigm that allows developers to register plugins containing content, or Fills, to be displayed in a specific location, or Slot,  in the UI.&nbsp;<\/p>\n<\/div>\n\n\n\n<div class=\"wp-block-group is-layout-constrained wp-block-group-is-layout-constrained\">\n<h1 class=\"wp-block-heading\">How does it compare to Hooks?<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Historically, if a developer wanted to add UI elements to the WordPress admin, there would be an Action exposed that they could \u201chook\u201d into.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For example, if the<code> edit_form_after_title <\/code>action was leveraged, it was possible to add a secondary title to the existing post-edit screen:<\/p>\n\n\n\n<pre title=\"\" class=\"wp-block-code\"><code lang=\"php\" class=\"language-php\">add_action(\n   edit_form_after_title',\n   function() {\n       echo ''&lt;input type=\"text\" class=\"widefat\" placeholder=\"Add secondary title\" \/&gt;';\n   }\n);<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Which would display as:<\/p>\n\n\n\n<figure data-wp-context=\"{&quot;imageId&quot;:&quot;69f2d38cb35ab&quot;}\" data-wp-interactive=\"core\/image\" data-wp-key=\"69f2d38cb35ab\" class=\"wp-block-image size-large wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"154\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on--click=\"actions.showLightbox\" data-wp-on--load=\"callbacks.setButtonStyles\" data-wp-on--pointerdown=\"actions.preloadImage\" data-wp-on--pointerenter=\"actions.preloadImageWithDelay\" data-wp-on--pointerleave=\"actions.cancelPreload\" data-wp-on-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/developer.wordpress.org\/news\/files\/2022\/10\/edit_form_after_title-example-1024x154.png\" alt=\"\" class=\"wp-image-77\" srcset=\"https:\/\/developer.wordpress.org\/news\/files\/2022\/10\/edit_form_after_title-example-1024x154.png 1024w, https:\/\/developer.wordpress.org\/news\/files\/2022\/10\/edit_form_after_title-example-300x45.png 300w, https:\/\/developer.wordpress.org\/news\/files\/2022\/10\/edit_form_after_title-example-768x116.png 768w, https:\/\/developer.wordpress.org\/news\/files\/2022\/10\/edit_form_after_title-example.png 1030w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><button\n\t\t\tclass=\"lightbox-trigger\"\n\t\t\ttype=\"button\"\n\t\t\taria-haspopup=\"dialog\"\n\t\t\tdata-wp-bind--aria-label=\"state.thisImage.triggerButtonAriaLabel\"\n\t\t\tdata-wp-init=\"callbacks.initTriggerButton\"\n\t\t\tdata-wp-on--click=\"actions.showLightbox\"\n\t\t\tdata-wp-style--right=\"state.thisImage.buttonRight\"\n\t\t\tdata-wp-style--top=\"state.thisImage.buttonTop\"\n\t\t>\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewBox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\" \/>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">This was possible due to the action being exposed by calling <code>do_action()<\/code> in a specific location in the files that are loaded to render the edit post screen.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"php\" class=\"language-php\">do_action( 'edit_form_after_title', $post );<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Based on this, an Action can be viewed as having three steps:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>A location is exposed for extension via a <code>do_action()<\/code> call in WordPress core.<\/li>\n\n\n\n<li>A developer creates a plugin ( or theme ) that contains a corresponding <code>add_action()<\/code> call.<\/li>\n\n\n\n<li>WordPress loads the page and when the <code>do_action<\/code> is run, the custom code from the plugin is run in the location where <code>do_action<\/code> was called.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">SlotFill is similar to actions in the sense that they are also location-based. The actual implementation is much different, but the steps are very similar in concept<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>A Slot is exposed somewhere in WordPress core.<\/li>\n\n\n\n<li>A developer registers a plugin with <code>wp.plugins.registerPlugin(<\/code>) which contains a Fill for a corresponding Slot.<\/li>\n\n\n\n<li>WordPress loads the page where the Slot is exposed and The SlotFill system renders the Fill content in the Slot location.<\/li>\n<\/ol>\n<\/div>\n\n\n\n<div class=\"wp-block-group is-layout-constrained wp-block-group-is-layout-constrained\">\n<h1 class=\"wp-block-heading\">The pieces of the puzzle<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">The SlotFill system consists of five pieces that work together to render Fill content in Slot locations:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Slot component<\/li>\n\n\n\n<li>Fill component<\/li>\n\n\n\n<li>SlotFillProvider component<\/li>\n\n\n\n<li>registerPlugin()<\/li>\n\n\n\n<li>PluginArea component.<\/li>\n<\/ol>\n<\/div>\n\n\n\n<div class=\"wp-block-group is-layout-constrained wp-block-group-is-layout-constrained\">\n<h2 class=\"wp-block-heading\" id=\"slot\">Slot<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The Slot component is used to determine where in the UI the extension point will be exposed. Wherever this component is rendered is where the associated Fill components content will be displayed.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Slot accepts the following props:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>name<\/strong>:&nbsp; The name of the Slot.<\/li>\n\n\n\n<li><strong>fillProps<\/strong>:&nbsp; Object that is passed to the Fill.<\/li>\n\n\n\n<li><strong>bubblesVirtually<\/strong>:&nbsp; Changes event bubbling behavior<\/li>\n<\/ul>\n\n\n\n<pre title=\"Basic Slot Example\" class=\"wp-block-code\"><code lang=\"jsx\" class=\"language-jsx\">import { Slot } from '@wordpress\/components';\n&lt;Slot\n    name=\"my-slot-name\"\n    fillProps={ { key: 'value' } }\n    bubblesVirtually\n\/&gt;<\/code><\/pre>\n<\/div>\n\n\n\n<div class=\"wp-block-group is-layout-constrained wp-block-group-is-layout-constrained\">\n<h2 class=\"wp-block-heading\" id=\"fill\">Fill<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The Fill component is used to provide content to a Slot with the same name property.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This component can be rendered anywhere inside the UI &#8211; even in a completely different element tree. The contents of the Fill will be rendered in the Slot with the same name property. Regardless of where the Fill is rendered.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Fill accepts a single prop:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>name<\/strong>: The name of the Slot that this Fill is targeting.<\/li>\n<\/ul>\n\n\n\n<pre title=\"Basic Fill Example\" class=\"wp-block-code\"><code lang=\"jsx\" class=\"language-jsx\">import { Fill } from '@wordpress\/components';\n \n&lt;Fill name=\"my-slot-name\"&gt;\n    Fill Contents\n&lt;\/Fill&gt;<\/code><\/pre>\n<\/div>\n\n\n\n<div class=\"wp-block-group is-layout-constrained wp-block-group-is-layout-constrained\">\n<h2 class=\"wp-block-heading\" id=\"slot-fill-provider\">SlotFillProvider<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The SlotFillProvider component is the magical glue that connects Fills to their Slots.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It wraps the UI and its job is to detect any Slots or Fills anywhere inside of it or any of its child components and then render the Fill content in the associated Slot location. This component does not accept any props.<\/p>\n<\/div>\n\n\n\n<div class=\"wp-block-group is-layout-constrained wp-block-group-is-layout-constrained\">\n<h2 class=\"wp-block-heading\" id=\"register-plugin\">registerPlugin()<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The only item in the list that is not a React component, this function is used to register a plugin that contains one for more fills. It is part of the <code>@wordpress\/plugins<\/code> package and it accepts two parameters:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>name<\/strong>&nbsp;A string identifying the plugin<\/li>\n\n\n\n<li><strong>settings<\/strong>: Object containing settings for the plugin\n<ul class=\"wp-block-list\">\n<li><strong>render<\/strong>: The component to render<\/li>\n\n\n\n<li><strong>icon<\/strong>: A visual asset to be associated with the plugin<\/li>\n\n\n\n<li><strong>scope<\/strong>: The scope this plugin belongs to. <strong><em>This is only used for custom implementations and should be left undefined<\/em><\/strong><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">For more information on <code>registerPlugin<\/code> and the other functions provided by this package, please refer to the <a href=\"https:\/\/developer.wordpress.org\/block-editor\/reference-guides\/packages\/packages-plugins\/\">official documentation on the plugins module<\/a>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"jsx\" class=\"language-jsx\">import { registerPlugin } from '@wordpress\/plugins';\n\nregisterPlugin( 'example-plugin', {\n    render: ComponentToRender,\n    icon: 'smiley',\n} );<\/code><\/pre>\n<\/div>\n\n\n\n<div class=\"wp-block-group is-layout-constrained wp-block-group-is-layout-constrained\">\n<h2 class=\"wp-block-heading\">PluginArea<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Finally, there is the PluginArea component. Its job is to retrieve all of the registered plugins from the plugins API and render them internally inside a hidden div element.&nbsp;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The PluginArea component accepts the following props:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>scope<\/strong>: Scope for the plugin area. Registered plugins must match the scope to be rendered. <strong><em>This is currently not defined in existing implementations<\/em><\/strong><\/li>\n\n\n\n<li><strong>onError<\/strong>: Function to handle errors<\/li>\n<\/ul>\n\n\n\n<pre title=\"Basic PluginArea Example\" class=\"wp-block-code\"><code lang=\"jsx\" class=\"language-jsx\">import { PluginArea } from '@wordpress\/plugins';\n \n&lt;PluginArea\n    scope=\"custom-scope\"\n    onError={ onErrorHandler }\n\/&gt;;<\/code><\/pre>\n<\/div>\n\n\n\n<div class=\"wp-block-group is-layout-constrained wp-block-group-is-layout-constrained\">\n<h2 class=\"wp-block-heading\">Putting it together<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Both the Post Editor and Site Editor screens implement a SlotFill system. At a high level, it looks like this:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>A <code>SlotFillProvider<\/code> wraps the <code>EditorProvider<\/code> component.<\/li>\n\n\n\n<li>Various <code>Slot<\/code> components are exposed in the Layout component.<\/li>\n\n\n\n<li><code>Fill<\/code> components are added using the <code>registerPlugin()<\/code> function.<\/li>\n\n\n\n<li>The <code>Fill<\/code> components are rendered in hidden div by the <code>PluginArea<\/code> component.<\/li>\n\n\n\n<li><code>Fill<\/code> content is rendered in the associated <code>Slot<\/code> location.<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"jsx\" class=\"language-jsx\">\/\/ Pseudo code for edit-post\n&lt;SlotFillProvider&gt;\n    &lt;EditorProvider&gt;\n        &lt;Layout&gt;\n            { \/* Slots are exposed in various locations *\/ }\n            &lt;PluginArea \/&gt;\n        &lt;\/Layout&gt;\n    &lt;\/EditorProvider&gt;\n&lt;\/SlotFillProvider&gt;;<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">A visual representation<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">In the visual representations below, it can be seen how the system works together. Plugins are registered using <code>registerPlugin()<\/code> and added to the list of plugins that have been registered. The PluginArea component retrieves the the plugins and renders each plugins <code>render<\/code> property that contains Fill components into a hidden div.<\/p>\n\n\n\n<figure data-wp-context=\"{&quot;imageId&quot;:&quot;69f2d38cb5910&quot;}\" data-wp-interactive=\"core\/image\" data-wp-key=\"69f2d38cb5910\" class=\"wp-block-image size-large has-custom-border wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"576\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on--click=\"actions.showLightbox\" data-wp-on--load=\"callbacks.setButtonStyles\" data-wp-on--pointerdown=\"actions.preloadImage\" data-wp-on--pointerenter=\"actions.preloadImageWithDelay\" data-wp-on--pointerleave=\"actions.cancelPreload\" data-wp-on-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/developer.wordpress.org\/news\/files\/2022\/11\/sf-visual-one-1024x576.png\" alt=\"A simplified visual representation of how the SlotFill system accesses the list of registered plugins and renders them inside the PluginArea component. \" class=\"has-border-color has-light-grey-1-border-color wp-image-264\" style=\"border-width:1px\" srcset=\"https:\/\/developer.wordpress.org\/news\/files\/2022\/11\/sf-visual-one-1024x576.png 1024w, https:\/\/developer.wordpress.org\/news\/files\/2022\/11\/sf-visual-one-300x169.png 300w, https:\/\/developer.wordpress.org\/news\/files\/2022\/11\/sf-visual-one-768x432.png 768w, https:\/\/developer.wordpress.org\/news\/files\/2022\/11\/sf-visual-one-1536x864.png 1536w, https:\/\/developer.wordpress.org\/news\/files\/2022\/11\/sf-visual-one.png 1920w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><button\n\t\t\tclass=\"lightbox-trigger\"\n\t\t\ttype=\"button\"\n\t\t\taria-haspopup=\"dialog\"\n\t\t\tdata-wp-bind--aria-label=\"state.thisImage.triggerButtonAriaLabel\"\n\t\t\tdata-wp-init=\"callbacks.initTriggerButton\"\n\t\t\tdata-wp-on--click=\"actions.showLightbox\"\n\t\t\tdata-wp-style--right=\"state.thisImage.buttonRight\"\n\t\t\tdata-wp-style--top=\"state.thisImage.buttonTop\"\n\t\t>\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewBox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\" \/>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Once the <code>PluginArea<\/code> renders the plugins, the <code>SlotFillProvider<\/code> then detects that there are FIlls available and renders their content in the association <code>Slot<\/code> location.<\/p>\n<\/div>\n\n\n\n<figure data-wp-context=\"{&quot;imageId&quot;:&quot;69f2d38cb5faf&quot;}\" data-wp-interactive=\"core\/image\" data-wp-key=\"69f2d38cb5faf\" class=\"wp-block-image size-large has-custom-border wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"576\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on--click=\"actions.showLightbox\" data-wp-on--load=\"callbacks.setButtonStyles\" data-wp-on--pointerdown=\"actions.preloadImage\" data-wp-on--pointerenter=\"actions.preloadImageWithDelay\" data-wp-on--pointerleave=\"actions.cancelPreload\" data-wp-on-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/developer.wordpress.org\/news\/files\/2022\/11\/Slot-Visual-Two-1024x576.png\" alt=\"A simplified representation that demonstrates how the Fill content is moved into the Slot location by the SlotFillProvider component.\" class=\"has-border-color has-light-grey-1-border-color wp-image-265\" style=\"border-width:1px\" srcset=\"https:\/\/developer.wordpress.org\/news\/files\/2022\/11\/Slot-Visual-Two-1024x576.png 1024w, https:\/\/developer.wordpress.org\/news\/files\/2022\/11\/Slot-Visual-Two-300x169.png 300w, https:\/\/developer.wordpress.org\/news\/files\/2022\/11\/Slot-Visual-Two-768x432.png 768w, https:\/\/developer.wordpress.org\/news\/files\/2022\/11\/Slot-Visual-Two-1536x864.png 1536w, https:\/\/developer.wordpress.org\/news\/files\/2022\/11\/Slot-Visual-Two.png 1920w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><button\n\t\t\tclass=\"lightbox-trigger\"\n\t\t\ttype=\"button\"\n\t\t\taria-haspopup=\"dialog\"\n\t\t\tdata-wp-bind--aria-label=\"state.thisImage.triggerButtonAriaLabel\"\n\t\t\tdata-wp-init=\"callbacks.initTriggerButton\"\n\t\t\tdata-wp-on--click=\"actions.showLightbox\"\n\t\t\tdata-wp-style--right=\"state.thisImage.buttonRight\"\n\t\t\tdata-wp-style--top=\"state.thisImage.buttonTop\"\n\t\t>\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewBox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\" \/>\n\t\t\t<\/svg>\n\t\t<\/button><\/figure>\n\n\n\n<div class=\"wp-block-group is-layout-constrained wp-block-group-is-layout-constrained\">\n<h2 class=\"wp-block-heading\">How SlotFills are built<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">So far in this post, examples have focused on the basic Slot component.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">However, the available SlotFills are not just simple components. They are named components that usually contain other functionality and inner components.&nbsp;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In this example, you can view how the PluginPostStatusInfo SlotFill is structured.&nbsp;<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"jsx\" class=\"language-jsx\">const PluginPostStatusInfo = ( { children, className } ) =&gt; (\n    &lt;Fill&gt;\n        &lt;PanelRow className={ className }&gt;{ children }&lt;\/PanelRow&gt;\n    &lt;\/Fill&gt;\n);\n\nPluginPostStatusInfo.Slot = Slot;\n\nexport default PluginPostStatusInfo;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Notice that the exported SlotFill component contains both the Slot and the Fill. Hence the name of the component!<\/p>\n<\/div>\n\n\n\n<div class=\"wp-block-group is-layout-constrained wp-block-group-is-layout-constrained\">\n<h2 class=\"wp-block-heading\">Exposing a Slot<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Each SlotFIll is exposed in the UI using its dot-Slot property.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In this simplified example, we see how the <code>PluginPostStatusInfo<\/code> Slot is exposed inside the <code>PostStatus<\/code> component. The full source is available in the <a rel=\"noreferrer noopener\" href=\"https:\/\/github.com\/WordPress\/gutenberg\/blob\/trunk\/packages\/edit-post\/src\/components\/sidebar\/post-status\/index.js#L30\" target=\"_blank\">WordPress Gutenberg repository on GitHub<\/a>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"jsx\" class=\"language-jsx\">function PostStatus( { isOpened, onTogglePanel } ) {\n    return (\n        &lt;PanelBody\n            className=\"edit-post-post-status\"\n            title={ __( 'Summary' ) }\n            opened={ isOpened }\n            onToggle={ onTogglePanel }\n        &gt;\n            &lt;PluginPostStatusInfo.Slot\/&gt;\n        &lt;\/PanelBody&gt;\n    );\n}<\/code><\/pre>\n<\/div>\n\n\n\n<div class=\"wp-block-group is-layout-constrained wp-block-group-is-layout-constrained\">\n<h2 class=\"wp-block-heading\"><strong>Registering a Fill<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Now that the Slot has been exposed, we can use <code>registerPlugin<\/code> to add a Fill.&nbsp;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In the example below, the PluginPostStatusInfo SlotFill is imported from the wordpress\/edit-post package and is used in our render property.&nbsp;<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"jsx\" class=\"language-jsx\">import { registerPlugin } from '@wordpress\/plugins';\nimport { PluginPostStatusInfo } from '@wordpress\/edit-post';\n\nregisterPlugin('example-plugin', {\n    render: () =&gt; (\n        &lt;PluginPostStatusInfo&gt;\n            &lt;p&gt;Post Status info SlotFill&lt;\/p&gt;\n        &lt;\/PluginPostStatusInfo&gt;\n    ),\n    icon: 'smiley'\n})<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Any children of the PluginPostStatusInfo component will be rendered in the associated Slot location.<\/p>\n\n\n\n<figure data-wp-context=\"{&quot;imageId&quot;:&quot;69f2d38cb6f26&quot;}\" data-wp-interactive=\"core\/image\" data-wp-key=\"69f2d38cb6f26\" class=\"wp-block-image aligncenter size-full wp-lightbox-container\"><img loading=\"lazy\" decoding=\"async\" width=\"278\" height=\"391\" data-wp-class--hide=\"state.isContentHidden\" data-wp-class--show=\"state.isContentVisible\" data-wp-init=\"callbacks.setButtonStyles\" data-wp-on--click=\"actions.showLightbox\" data-wp-on--load=\"callbacks.setButtonStyles\" data-wp-on--pointerdown=\"actions.preloadImage\" data-wp-on--pointerenter=\"actions.preloadImageWithDelay\" data-wp-on--pointerleave=\"actions.cancelPreload\" data-wp-on-window--resize=\"callbacks.setButtonStyles\" src=\"https:\/\/developer.wordpress.org\/news\/files\/2022\/10\/plugin-post-status-info-location.png\" alt=\"\" class=\"wp-image-92\" srcset=\"https:\/\/developer.wordpress.org\/news\/files\/2022\/10\/plugin-post-status-info-location.png 278w, https:\/\/developer.wordpress.org\/news\/files\/2022\/10\/plugin-post-status-info-location-213x300.png 213w\" sizes=\"auto, (max-width: 278px) 100vw, 278px\" \/><button\n\t\t\tclass=\"lightbox-trigger\"\n\t\t\ttype=\"button\"\n\t\t\taria-haspopup=\"dialog\"\n\t\t\tdata-wp-bind--aria-label=\"state.thisImage.triggerButtonAriaLabel\"\n\t\t\tdata-wp-init=\"callbacks.initTriggerButton\"\n\t\t\tdata-wp-on--click=\"actions.showLightbox\"\n\t\t\tdata-wp-style--right=\"state.thisImage.buttonRight\"\n\t\t\tdata-wp-style--top=\"state.thisImage.buttonTop\"\n\t\t>\n\t\t\t<svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"12\" height=\"12\" fill=\"none\" viewBox=\"0 0 12 12\">\n\t\t\t\t<path fill=\"#fff\" d=\"M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z\" \/>\n\t\t\t<\/svg>\n\t\t<\/button><figcaption class=\"wp-element-caption\">The rendered Fill content.<\/figcaption><\/figure>\n<\/div>\n\n\n\n<div class=\"wp-block-group is-layout-constrained wp-block-group-is-layout-constrained\">\n<h2 class=\"wp-block-heading\">Currently available SlotFills<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">As of WordPress 6.1, there are a total of 12 available slots, nine in the Edit Post screen and three in the Site Editor screen. These are well-documented in the <a href=\"https:\/\/developer.wordpress.org\/block-editor\/reference-guides\/slotfills\/\" target=\"_blank\" rel=\"noreferrer noopener\">block editor handbook<\/a> and include examples.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Edit Post Screen<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/developer.wordpress.org\/block-editor\/reference-guides\/slotfills\/plugin-post-status-info\/\" target=\"_blank\" rel=\"noreferrer noopener\">PluginPostStatusInfo<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/developer.wordpress.org\/block-editor\/reference-guides\/slotfills\/plugin-pre-publish-panel\/\" target=\"_blank\" rel=\"noreferrer noopener\">PluginPrePublishPanel<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/developer.wordpress.org\/block-editor\/reference-guides\/slotfills\/plugin-post-publish-panel\/\" target=\"_blank\" rel=\"noreferrer noopener\">PluginPostPublishPanel<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/developer.wordpress.org\/block-editor\/reference-guides\/slotfills\/plugin-more-menu-item\/\">PluginMoreMenuItem<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/developer.wordpress.org\/block-editor\/reference-guides\/slotfills\/plugin-block-settings-menu-item\/\" target=\"_blank\" rel=\"noreferrer noopener\">PluginBlockSettingsMenuItem<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/developer.wordpress.org\/block-editor\/reference-guides\/slotfills\/plugin-sidebar\/\" target=\"_blank\" rel=\"noreferrer noopener\">PluginSidebar<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/developer.wordpress.org\/block-editor\/reference-guides\/slotfills\/plugin-sidebar-more-menu-item\/\" target=\"_blank\" rel=\"noreferrer noopener\">PluginSidebarMoreMenuItem<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/developer.wordpress.org\/block-editor\/reference-guides\/slotfills\/plugin-document-setting-panel\/\" target=\"_blank\" rel=\"noreferrer noopener\">PluginDocumentSettingPanel<\/a><\/li>\n\n\n\n<li><a rel=\"noreferrer noopener\" href=\"https:\/\/developer.wordpress.org\/block-editor\/reference-guides\/slotfills\/main-dashboard-button\/\" target=\"_blank\">MainDashboardButton<\/a><\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">These Slots are part of the <code><a href=\"https:\/\/developer.wordpress.org\/block-editor\/reference-guides\/packages\/packages-edit-post\/\">@wordpress\/edit-post<\/a><\/code> package.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">import {\n    PluginPostStatusInfo\n    PluginPrePublishPanel\n    PluginPostPublishPanel\n    PluginMoreMenuItem\n    PluginBlockSettingsMenuItem\n    PluginSidebar\n    PluginSidebarMoreMenuItem\n    PluginDocumentSettingPanel\n    __experimentalMainDashboardButton as MainDashboardButton,\n} from '@wordpress\/edit-post';<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Site Editor screen<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/developer.wordpress.org\/block-editor\/reference-guides\/slotfills\/plugin-more-menu-item\/\">PluginMoreMenuItem<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/developer.wordpress.org\/block-editor\/reference-guides\/slotfills\/plugin-sidebar\/\" target=\"_blank\" rel=\"noreferrer noopener\">PluginSidebar<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/developer.wordpress.org\/block-editor\/reference-guides\/slotfills\/main-dashboard-button\/\" target=\"_blank\" rel=\"noreferrer noopener\">MainDashboardButton<\/a><\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">These Slots are part of the <a href=\"https:\/\/developer.wordpress.org\/block-editor\/reference-guides\/packages\/packages-edit-site\/\"><code>@wordpress\/edit-site<\/code> package<\/a>. These slots link to the same documentation as their counterparts in the Edit Post screen. The difference is where the slot is exposed. <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">import {\n    PluginMoreMenuItem,\n    PluginSidebar,\n    __experimentalMainDashboardButton as MainDashboardButton,\n} from '@wordpress\/edit-site';<\/code><\/pre>\n<\/div>\n\n\n\n<div class=\"wp-block-group is-layout-constrained wp-block-group-is-layout-constrained\">\n<h2 class=\"wp-block-heading\">Resources to learn more<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/developer.wordpress.org\/block-editor\/reference-guides\/slotfills\/\">SlotFills Reference<\/a> in the block editor handbook (Documentation)<\/li>\n\n\n\n<li><a rel=\"noreferrer noopener\" href=\"https:\/\/wordpress.tv\/2022\/07\/21\/ryan-welcher-creating-a-pre-publish-checklist-for-gutenberg\/\" target=\"_blank\">Talk &#8211; creating a pre-publish checklist for Gutenberg<\/a> (WordPress.tv 2022)<\/li>\n\n\n\n<li><a rel=\"noreferrer noopener\" href=\"https:\/\/wordpress.tv\/2022\/07\/22\/paul-halfpenny-imran-sayed-evan-mullins-ryan-welcher-juanma-garrido-lightning-talks\/?at=555\" data-type=\"URL\" target=\"_blank\">Lightning Talk &#8211; Extending Gutenberg with SlotFill<\/a> (WordPress.tv 2022)<\/li>\n\n\n\n<li><a href=\"https:\/\/github.com\/ryanwelcher\/wordpress-slot-fill-system\">SlotFill examples repository<\/a> (external) <\/li>\n<\/ul>\n<\/div>\n\n\n\n<p class=\"has-text-align-right is-style-default wp-block-paragraph\"><em>Thanks to <a href='https:\/\/profiles.wordpress.org\/bph\/' class='mention'><span class='mentions-prefix'>@<\/span>bph<\/a>, <a href='https:\/\/profiles.wordpress.org\/bcworkz\/' class='mention'><span class='mentions-prefix'>@<\/span>bcworkz<\/a> and <a href='https:\/\/profiles.wordpress.org\/webcommsat\/' class='mention'><span class='mentions-prefix'>@<\/span>webcommsat<\/a> for reviewing this article.<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In WordPress 5.0, the WordPress SlotFill system was introduced as part of the Gutenberg project and is the extension paradigm that allows developers to extend the UIs introduced with the Gutenberg project such as the Post Editor and the Site Editor.<\/p>\n","protected":false},"author":7543064,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"template-center-column","format":"standard","meta":{"_crdt_document":"","jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"edge","default_image_id":0,"font":"","enabled":false},"version":2},"_wpas_customize_per_network":false},"categories":[4,2,40],"tags":[10,28,27],"class_list":["post-63","post","type-post","status-publish","format-standard","hentry","category-advanced","category-concepts","category-plugins","tag-extenders","tag-extending-wordpress","tag-slotfill","mentions-bcworkz","mentions-bph","mentions-webcommsat","mentions-wordpress"],"revision_note":"","jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/developer.wordpress.org\/news\/wp-json\/wp\/v2\/posts\/63","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/developer.wordpress.org\/news\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/developer.wordpress.org\/news\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/developer.wordpress.org\/news\/wp-json\/wp\/v2\/users\/7543064"}],"replies":[{"embeddable":true,"href":"https:\/\/developer.wordpress.org\/news\/wp-json\/wp\/v2\/comments?post=63"}],"version-history":[{"count":47,"href":"https:\/\/developer.wordpress.org\/news\/wp-json\/wp\/v2\/posts\/63\/revisions"}],"predecessor-version":[{"id":1960,"href":"https:\/\/developer.wordpress.org\/news\/wp-json\/wp\/v2\/posts\/63\/revisions\/1960"}],"wp:attachment":[{"href":"https:\/\/developer.wordpress.org\/news\/wp-json\/wp\/v2\/media?parent=63"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/developer.wordpress.org\/news\/wp-json\/wp\/v2\/categories?post=63"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/developer.wordpress.org\/news\/wp-json\/wp\/v2\/tags?post=63"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}