Contents
Overview — what SlotFill is and why use it
SlotFill is the UI composition pattern used throughout the WordPress block editor (Gutenberg) to let independent pieces of code insert UI into named places (slots) in the editor shell. It is the pattern behind many editor extension points such as sidebars, toolbar buttons, post status info panels, and more. SlotFill decouples where UI is defined from where UI is rendered: a Slot is a placeholder (a named location), and any number of Fill components can provide content for that placeholder.
When to use SlotFill
- When you need to insert UI into an existing editor area (header, status area, more menu, prepublish panel, document settings) provided by the editor shell.
- When building multiple independent extensions that need to target the same place without knowing about each other directly.
- When you want to create your own pluggable placeholder in a UI you control, and let other code provide content for it.
Core concepts and API
Two components are central: Slot and Fill. A Slot (by name) is the consumer side — it renders whatever Fills exist for that name. A Fill (by name) is the provider — it defines content that will be rendered into its corresponding Slot.
Basic properties and behavior
- name (string): The identifier that pairs Slot and Fill. Must match exactly.
- scope (optional): An additional value that can be used to scope fills to a particular slot instance when you render multiple slot instances with different scopes.
- children: You can pass JSX as Fill children. Slot also supports a render-function child that receives the fills array so you can control the render order, wrap fills, or provide props.
- Multiple fills appear in insertion order by default the Slot can reorder or wrap them using a render function.
- The editor provides a SlotFillProvider in the editor environment, so when building inside the block editor you usually do not need to add your own provider.
Where SlotFill is already used in the editor
- PluginSidebar (the right-hand plugin sidebar)
- PluginPrePublishPanel (pre-publish checks)
- PluginMoreMenuItem (the More menu)
- PluginPostStatusInfo (the post status area near the publish button)
- Various header and toolbar extension points
How to use SlotFill — practical examples
Below you will find multiple real examples you can use in a plugin. Each example is given both as the editor-facing JavaScript and, where needed, the PHP needed to enqueue it within WordPress.
1) Minimal ESNext plugin adding a small widget to the post status area
This example assumes you use the standard @wordpress/scripts build toolchain (so you can import packages). It inserts a small status indicator into the post status area using the Fill name that the edit-post package exposes (PluginPostStatusInfo).
import { Fill } from @wordpress/components import { registerPlugin } from @wordpress/plugins import { useSelect } from @wordpress/data import { __ } from @wordpress/i18n import { Fragment } from @wordpress/element function PostStatusLengthIndicator() { const title = useSelect( (select) => select(core/editor).getEditedPostAttribute(title) ) const length = title.length return ( ltFill name=PluginPostStatusInfogt ltdiv style={{ paddingLeft: 8, display: flex, alignItems: center }}gt ltspan aria-hidden=true style={{ opacity: 0.7 }}gt✎lt/spangt ltdiv style={{ marginLeft: 6 }}gt ltstronggt{__(Title length:, my-text-domain)}lt/stronggt {length} lt/divgt lt/divgt lt/Fillgt ) } registerPlugin(my-post-status-length, { render: PostStatusLengthIndicator, })
Enqueue this script from PHP so it runs only inside the block editor:
lt?php / Plugin bootstrap file / function my_slotfill_enqueue_editor_assets() { wp_enqueue_script( my-slotfill-editor, plugins_url( build/index.js, __FILE__ ), array( wp-plugins, wp-edit-post, wp-element, wp-components, wp-data, wp-i18n ), filemtime( plugin_dir_path( __FILE__ ) . build/index.js ), true ) } add_action( enqueue_block_editor_assets, my_slotfill_enqueue_editor_assets )
2) Using globals (no build tool) — the equivalent approach
If you do not use a bundler, you can write a script that relies on the global wp. objects that Gutenberg exposes. This example performs the same insertion into PluginPostStatusInfo.
( function( wp ) { const { Fill } = wp.components const { registerPlugin } = wp.plugins const { select } = wp.data function PostStatusLengthIndicator() { const title = select(core/editor).getEditedPostAttribute(title) return wp.element.createElement( Fill, { name: PluginPostStatusInfo }, wp.element.createElement(div, { style: { paddingLeft: 8, display: flex, alignItems: center } }, wp.element.createElement(span, { aria-hidden: true, style: { opacity: 0.7 } }, ✎), wp.element.createElement(div, { style: { marginLeft: 6 } }, wp.element.createElement(strong, null, Title length:), , title.length ) ) ) } registerPlugin(my-post-status-length-global, { render: PostStatusLengthIndicator }) })( window.wp )
3) Creating a custom Slot in your own UI and filling it
SlotFill is useful even inside your own component tree. Render a Slot where you want content to be inserted render Fill elsewhere (the Slot and Fill must render under the same SlotFillProvider — the editor provides one when inside the block editor if outside you can provide your own).
import { Slot, Fill } from @wordpress/components import { registerPlugin } from @wordpress/plugins function MyPluginHost() { // This Slot will render fills that target MyPlugin/CustomToolbar return ( ltdivgt lth3gtMy Plugin UIlt/h3gt ltdiv className=my-plugin-toolbargt ltSlot name=MyPlugin/CustomToolbargt { ( fills ) =gt ( ltdiv style={{ display: flex, gap: 8 }}gt { fills.map( ( FillComponent, i ) =gt ltFillComponent key={ i } /gt ) } lt/divgt ) } lt/Slotgt lt/divgt lt/divgt ) } function RemoteFill() { return ( ltFill name=MyPlugin/CustomToolbargt ltbuttongtRemote Actionlt/buttongt lt/Fillgt ) } registerPlugin(my-plugin-host, { render: MyPluginHost }) registerPlugin(my-plugin-remote-fill, { render: RemoteFill })
4) Advanced: using Slot render-prop to pass props into fills
Slot supports a child function that receives the fills array. This lets you render fills yourself and pass props into them. That pattern allows the host to control how fills are integrated, to set ordering rules, or to provide contextual props.
import { Slot, Fill } from @wordpress/components import { registerPlugin } from @wordpress/plugins function HostWithProps() { const hostContext = { color: purple } return ( ltSlot name=MyPlugin/PropSlotgt { ( fills ) =gt ( ltdivgt { fills.map( ( FillComponent, idx ) =gt ltFillComponent key={ idx } hostContext={ hostContext } /gt ) } lt/divgt ) } lt/Slotgt ) } function FillConsumer( { hostContext } ) { return ltdiv style={{ color: hostContext.color }}gtI use host propslt/divgt } function ProvideFill() { return ltFill name=MyPlugin/PropSlotgt{( props ) =gt ltFillConsumer { ...props } /gt}lt/Fillgt } registerPlugin( my-prop-slot-host, { render: HostWithProps } ) registerPlugin( my-prop-slot-fill, { render: ProvideFill } )
5) Styling fills
You can enqueue CSS the usual way (enqueue_block_editor_assets) or add a small inline stylesheet. Keep styles scoped to your plugin classes to avoid collisions.
.my-plugin-toolbar { display: flex gap: 8px align-items: center } .my-plugin-toolbar button { background: #fff border: 1px solid #ddd padding: 6px 10px border-radius: 4px }
Practical pointers and best practices
- Use edit-post helper components when available: The edit-post package provides PluginSidebar, PluginPrePublishPanel and other convenience components that wrap slot/fill logic and provide consistent UX with WordPress. Prefer those components when they match your need.
- Enqueue your script with the editor-only hook: Use enqueue_block_editor_assets so your slot/fill code loads only in the block editor.
- Use wp.data selectors and hooks: Keep UI stateless where possible and rely on useSelect and useDispatch to read and update editor state.
- Scope if you need multiple slot instances: When you render multiple slot instances (for example multiple editors on the same page), use the scope prop to separate the fills for each instance so fills only appear in the intended slot.
- Accessibility and keyboard focus: Ensure injected controls are accessible, keyboard reachable, and provide ARIA labels if needed.
- Localization: Use __() and related functions from @wordpress/i18n for strings displayed inside fills.
- Performance: Avoid heavy computations in the render path of fills memoize or use selectors wisely to avoid unnecessary re-renders.
Troubleshooting — common issues
- Nothing appears: Confirm the name matches exactly between Slot and Fill, and that your script is actually loading in the editor (use browser devtools). Confirm you enqueue with enqueue_block_editor_assets.
- Slot provider not present (you see nothing for a Slot you added in a context outside the editor): If rendering Slot/Fill outside the editor shell you must provide a SlotFillProvider from @wordpress/components around the parts of the tree using Slots and Fills.
- Ordering or grouping isnt what you expect: Use the Slot render-prop to inspect the fills array and control ordering directly, or have fills include their own ordering metadata so the Slot can sort them before rendering.
- Conflicting CSS: Scope styles to plugin-specific classes to avoid accidental overrides.
Compatibility notes and package references
If you target older WordPress versions, verify that the editor packages you rely on are present. For example the edit-post conveniences (PluginSidebar, PluginPrePublishPanel, etc.) require specific Gutenberg versions. When building with a toolchain you will import from packages such as:
- @wordpress/components — provides Slot and Fill, plus UI building blocks.
- @wordpress/plugins — registerPlugin used to mount your plugin component into the editor lifecycle.
- @wordpress/edit-post — convenience components that themselves use SlotFill.
- @wordpress/data — useSelect and useDispatch to interact with editor state.
Examples summary table
Scenario | API to use | Notes |
Insert control in post status area | Fill name=PluginPostStatusInfo / registerPlugin | Common small contextual info near the Publish/Update button |
Create sidebar panel | PluginSidebar (edit-post) | Preferred over raw SlotFill for sidebars — consistent styling and behavior |
Custom internal extensibility | Slot Fill | Great for letting other parts of your plugin contribute UI to a shared area |
Further reading
Official documentation and API reference are valuable for up-to-date slot names and helper components. Start at the WordPress block editor package docs and the components package docs:
- Block Editor Handbook (WordPress Developer Resources)
- @wordpress/components — Slot and Fill and more
Final note
SlotFill is a flexible, composable, and well-established pattern inside the block editor. Use the provided edit-post helper components when possible for consistent UX otherwise, use Slot and Fill to create or consume custom extension points, combine with wp.data for reactive data-driven UI, and keep styling and accessibility in mind.
|
Acepto donaciones de BAT's mediante el navegador Brave 🙂 |