Contents
Introducción: ¿Qué es SlotFill y por qué usarlo en el editor de WordPress?
SlotFill es un patrón de diseño utilizado en Gutenberg (el editor de bloques de WordPress) que permite definir lugares (Slots) donde otros módulos o plugins pueden inyectar contenido (Fills) de forma desacoplada. Es extremadamente útil para extender la interfaz del editor sin tocar el código core ni acoplar componentes entre sí.
Con SlotFill puedes:
- Ofrecer puntos de extensión reutilizables dentro de tu plugin o tema.
- Permitir que terceros añadan controles o información en zonas concretas del editor.
- Mantener componentes independientes y composables.
Arquitectura y conceptos clave
Antes de entrar en ejemplos prácticos conviene entender los elementos básicos:
- Slot: componente que declara un punto donde se mostrará contenido externo. Puede aceptar propiedades que serán pasadas a los Fills.
- Fill: componente que se registra para rellenar un Slot concreto. Recibe las props que haya declarado el Slot y su contenido se renderiza en el lugar del Slot.
- Proveedor (Provider): normalmente el sistema de React de WordPress ya ofrece el contexto necesario en caso de apps React propias puede usarse un provider local para compartir estado entre fills y slots.
- Slots core: Gutenberg expone varios Slots en su UI (p. ej. para barras laterales, menús o paneles) puedes usarlos para inyectar contenido en zonas del editor.
Preparar el plugin: registrar y encolar scripts
Para que el navegador cargue tu código JS que usa SlotFill debes encolarlo desde PHP en tu plugin o tema. A continuación un ejemplo mínimo de registro y encolado compatible con ESNext mediante build (webpack/webpack-mix, etc.).
lt?php / Plugin Name: Mi Plugin SlotFill / function mi_plugin_enqueue() { wp_enqueue_script( mi-plugin-editor, plugins_url( build/index.js, __FILE__ ), array( wp-plugins, wp-edit-post, wp-components, wp-element, wp-data, wp-compose, wp-hooks ), filemtime( plugin_dir_path( __FILE__ ) . build/index.js ) ) // Opcional: estilos wp_enqueue_style( mi-plugin-editor-style, plugins_url( build/editor.css, __FILE__ ), array(), filemtime( plugin_dir_path( __FILE__ ) . build/editor.css ) ) } add_action( enqueue_block_editor_assets, mi_plugin_enqueue )
Ejemplo 1 — Crear un Slot propio y un Fill que lo rellena
Este ejemplo muestra cómo en un plugin registrar una PluginSidebar que contiene un Slot llamado MiSidebarSlot. Otros módulos (incluso dentro del mismo bundle) podrán registrar Fills para ese Slot. Así se promueve la extensibilidad.
Paso A — Plugin que declara el Slot dentro de una Sidebar
import { registerPlugin } from @wordpress/plugins import { PluginSidebar } from @wordpress/edit-post import { Slot } from @wordpress/components import { Fragment } from @wordpress/element const MiSidebar = () =gt { return ( ltFragmentgt ltPluginSidebar name=mi-sidebar title=Mi Sidebar Extensible gt { / Declaramos el Slot con nombre mi-sidebar-slot y pasamos una prop / } ltSlot name=mi-sidebar-slot saludo=Hola desde el Slot /gt lt/PluginSidebargt lt/Fragmentgt ) } registerPlugin( mi-sidebar-plugin, { render: MiSidebar } )
Paso B — Otro módulo (o parte del mismo plugin) registra un Fill
import { Fill } from @wordpress/components import { registerPlugin } from @wordpress/plugins const MiFill = () =gt { return ( ltFill name=mi-sidebar-slotgt ltdiv style={{ padding: 8px }}gt ltstronggtContenido añadido por un Filllt/stronggt ltpgtEste Fill recibe props del Slot y puede leer quotsaludoquot.lt/pgt lt/divgt lt/Fillgt ) } registerPlugin( mi-sidebar-fill, { render: MiFill } )
Resultado: cuando la sidebar de Mi Sidebar Extensible esté abierta, todos los Fills registrados con name=mi-sidebar-slot se renderizarán ahí. Esto permite a múltiples componentes insertarse sin modificarse mutuamente.
Ejemplo 2 — Pasando props desde Slot a Fill y controlando el orden
Los Slots pueden pasar props a los Fills (p. ej. funciones, estados). Además, el orden de renderizado de los fills puede controlarse por prioridad si usas wrapper o lógica para ordenarlos por defecto el orden será el de registro o el definido por el renderizado React.
import { Slot, Fill } from @wordpress/components import { registerPlugin } from @wordpress/plugins import { Fragment, useState } from @wordpress/element // Declarador del Slot con una prop onAction const MiComponenteConSlot = () =gt { const [contador, setContador] = useState(0) const onAction = () =gt setContador( c =gt c 1 ) return ( ltdivgt lth4gtContador: {contador}lt/h4gt ltSlot name=slot-con-acciones onAction={ onAction } /gt lt/divgt ) } export const PluginConSlot = () =gt ltMiComponenteConSlot /gt registerPlugin( plugin-con-slot, { render: PluginConSlot } ) // Fill que recibe la prop onAction y la llama export const FillQueAcciona = () =gt ( ltFill name=slot-con-accionesgt { ( { onAction } ) =gt ( ltbutton onClick={ onAction }gtHaz click desde Filllt/buttongt ) } lt/Fillgt ) registerPlugin( plugin-fill-accion, { render: FillQueAcciona } )
Observa que Fill puede ser una función que recibe las props que envía Slot así se permite comunicación unidireccional desde el Slot hacia el Fill sin acoplarlos.
Usar Hooks de datos con SlotFill (useSelect / useDispatch)
A menudo los fills necesitan leer o actualizar datos del store de WordPress (p. ej. contenido del post, metadata). En estos casos emplea los hooks useSelect y useDispatch de @wordpress/data dentro de los fills. De este modo los fills se mantienen reactivos y respetan el flujo de datos global.
import { Fill } from @wordpress/components import { useSelect, useDispatch } from @wordpress/data import { registerPlugin } from @wordpress/plugins const FillConData = () =gt { const title = useSelect( ( select ) =gt select( core/editor ).getEditedPostAttribute( title ), [] ) const { editPost } = useDispatch( core/editor ) const cambiarTitulo = () =gt { editPost( { title: title ✨ } ) } return ( ltFill name=mi-sidebar-slotgt ltdivgt ltpgtTítulo: {title ltvacíogt}lt/pgt ltbutton onClick={ cambiarTitulo }gtAgregar emoji al títulolt/buttongt lt/divgt lt/Fillgt ) } registerPlugin( mi-fill-con-data, { render: FillConData } )
Slots core de Gutenberg: dónde inyectar contenido en la UI del editor
Gutenberg expone múltiples puntos de extensión (slots) a través de distintos paquetes (p. ej. @wordpress/edit-post). Algunos componentes core que facilitan inyectar UI son:
- PluginSidebar: para barras laterales (añades un slot dentro si quieres extensibilidad interna).
- PluginPostStatusInfo: permite añadir info al panel de estado del post.
- PluginMoreMenuItem / PluginDocumentSettingPanel / PluginPrePublishPanel: componentes ya preparados que actúan como wrappers y que internamente usan patterns compatibles con SlotFill.
Nota: los nombres concretos y la lista completa de slots/core components pueden cambiar entre versiones. Revisa la documentación y el código fuente de @wordpress/edit-post para localizar slots core disponibles en tu versión.
Buenas prácticas, rendimiento y accesibilidad
- Evita renderizados costosos en fills: cada Fill se renderiza cuando la zona que contiene el Slot se actualiza. Usa memoización (React.memo) o hooks adecuados para minimizar rerenders.
- Separación de responsabilidades: define Slots con props claras y no expongas implementaciones internas innecesarias.
- Uso responsable de stores: los fills pueden usar useSelect/useDispatch, pero evita lecturas globales sin dependencia adecuada para prevenir renders infinidad de veces.
- Accesibilidad: asegúrate de que los elementos añadidos con Fill siguen pautas ARIA y navegación por teclado. Evita cambios bruscos de foco no anticipados.
- Compatibilidad: documenta el nombre del Slot y las props públicamente si otros desarrolladores van a integrarse con tu plugin.
Ejemplo completo: plugin que declara Slot y otro plugin que lo extiende (registro y CSS)
A continuación se muestra un esquema de los ficheros y código mínimo para un plugin que declara un Slot y otro plugin que añade un Fill. Incluye la parte PHP vista al principio.
/ src/index.js - declarador del Slot / import { registerPlugin } from @wordpress/plugins import { PluginSidebar } from @wordpress/edit-post import { Slot } from @wordpress/components const MiSidebar = () =gt ( ltPluginSidebar name=mi-sidebar title=Mi Sidebar Extensiblegt ltSlot name=mi-sidebar-slot saludo=hola /gt lt/PluginSidebargt ) registerPlugin( mi-sidebar-plugin, { render: MiSidebar } ) / src/fill.js - Fill que se registra (puede estar en su propio bundle o en el mismo) / import { registerPlugin } from @wordpress/plugins import { Fill } from @wordpress/components const MiFill = () =gt ( ltFill name=mi-sidebar-slotgt ltdiv style={{ padding: 12 }}gt ltpgtltstronggtUn Fill internolt/stronggtlt/pgt ltpgtAñade controles o información aquí.lt/pgt lt/divgt lt/Fillgt ) registerPlugin( mi-sidebar-fill, { render: MiFill } )
/ editor.css / .mi-fill-clase { padding: 8px border-left: 2px solid rgba(0,0,0,0.06) }
Solución de problemas comunes
- No veo mi Fill: revisa que el Slot está montado en el árbol React cuando el editor está abierto y que ambos bundles están correctamente encolados y ejecutándose en el editor (console del navegador).
- Props no llegan al Fill: asegúrate de que el Slot las está exponiendo y que el Fill las acepta (cuando Fill es función, recibe props como parámetro).
- Conflictos de CSS: encapcula estilos específicos del editor con selectores o clases para evitar romper la UI de Gutenberg.
- Rendimiento: evita cálculos pesados dentro del Fill usa useMemo y divide en componentes más pequeños.
Conclusión
SlotFill es una herramienta poderosa para extender la interfaz del editor de WordPress de manera modular y mantenible. Definir Slots bien documentados y permitir que Fills se registren de forma desacoplada permite ecosistemas de plugins más integrables y menos propensos a conflictos. Siguiendo las buenas prácticas de rendimiento y accesibilidad lograrás extensiones robustas y fáciles de mantener.
Recursos recomendados
- Documentación oficial del editor (WordPress Developer)
- Referencia Slot/Fill (si existe en tu versión)
|
Acepto donaciones de BAT's mediante el navegador Brave 🙂 |