Añadir un botón de formato al Toolbar en Gutenberg
En ocasiones puede que queramos añadir un botón de formato a la barra de herramientas (Toolbar) del editor de texto de Gutenberg, la que viene por defecto al escribir un párrafo.
El objetivo es añadir un botón, de tal forma que el texto seleccionado aparezca dentro de una caja con un color de fondo. Le vamos a llamar Boxed y este será el resultado final:
Todo el código está en los siguientes enlaces:
- JavaScript: https://gist.github.com/igmoweb/ef3cc57854f8b8515bca711fad573810
- CSS: https://gist.github.com/igmoweb/a56de97a4c6711b652f828a97d27cf8e
Registrando el formato
const { registerFormatType } = wp.richText;
const formatName = 'igmoweb/boxed-format';
const formatTitle = 'Boxed';
registerFormatType( formatName, {
title: formatTitle,
tagName: 'span',
className: 'boxed',
} );
Para esto hemos importado registerFormatType
que viene ya con Gutenberg y que nos permite de momento registrar el formato pero con esto todavía no tenemos nada. Lo único que hemos hecho es darle un estilo un un título al formato.
Las propiedades tagName
y className
van a definir el HTML en el que el texto seleccionado se envolverá. Al final quedará algo así:
Mira, estoy creando <span class="boxed">mi primer formato</span> en Gutenberg.
Renderizado del botón
Una vez el formato está registrado, necesitamos añadir un botón en el Toolbar:
const { registerFormatType } = wp.richText;
const { RichTextToolbarButton } = wp.blockEditor;
const formatName = 'igmoweb/boxed-format';
const formatTitle = 'Boxed';
const BoxedButton = () => {
return (
<RichTextToolbarButton
icon="archive"
title={ formatTitle }
onClick={ () => console.log( 'apply format' ) }
/>
);
};
registerFormatType( formatName, {
title: formatTitle,
tagName: 'span',
className: 'boxed',
edit: BoxedButton,
} );
El componente RichTextToolbarButton
es el responsable en Gutenberg de añadir un botón a la barra de herramientas. Hace uso del patrón SlotFill para añadirlo al menú que se despliega al hacer click sobre la flecha. Desgraciadamente, no he encontrado manera de ponerlo junto a los botones de cursiva o negrita, seguramente el equipo de Gutenberg intenta que no abusemos de esos botones ya que si cada plugin mete el suyo, la barra de herramientas podría crecer demasiado.
A RichTextToolbarButton
le pasamos un icono (he usado un Dashicon) un título y una función que se ejecuta al hacer click sobre él. De momento sólo muestra un mensaje en la consola JS del navegador. Aquí hay un GIF de ejemplo:
Aplicar el formato
Llega la hora de aplicar realmente el formato. Cuando registramos un formato con registerFormatType
y un componente edit
, este último recibe varios props:
value
: Un objeto con las propiedades del texto seleccionado, dónde empieza y dónde acaba pero también el texto completo y los formatos aplicados.onChange
: Es una función interna al componenteRichText
que utiliza Gutenberg. Sólo tenemos que saber que le tenemos que pasar el objeto formateado cuando queramos aplicar el cambio.isActive
: Si el cursor está actualmente situado en el texto seleccionado.
Además importamos una función desde wp.richText
, toggleFormat
, que es la función para formatear el texto seleccionado con el formato que queramos. Recibe como parámetro value
y devuelve uno igual pero con el formato añadido. En este ejemplo es la única que usamos pero también podríamos utilizar applyFormat
o removeFormat
. El objeto que devuelve es el que le pasaremos a onChange
import './style.scss';
const { toggleFormat, registerFormatType } = wp.richText;
const { RichTextToolbarButton } = wp.blockEditor;
const formatName = 'igmoweb/boxed-format';
const formatTitle = 'Boxed';
const BoxedButton = ( { onChange, value, isActive } ) => {
const toggleBoxedFormat = () => {
onChange( toggleFormat(
value,
{
type: formatName,
attributes: {
'data-type': 'box',
},
}
) );
};
return (
<RichTextToolbarButton
icon="archive"
title={ formatTitle }
onClick={ toggleBoxedFormat }
isActive={ isActive }
/>
);
};
registerFormatType( formatName, {
title: formatTitle,
tagName: 'span',
className: 'boxed',
edit: BoxedButton,
} );
A toggleFormat
le pasamos dos parámetros:
value
: Es directamente lo que viene a través de las props del componente.- Una objeto de opciones, entre ellos vemos el nombre del formato (
formatName
, ahora vemos por qué lo guardé en una variable, para no repetir). Con esto bastaría pero podemos pasarle también unos atributos que luego se reflejarán en el HTML. Aquí pongo `data-type=”box”`, de esta forma, el HTML, al guardar el formato quedaría así:
<span class="boxed" data-type="box">...</span>
También hemos importado style.scss
, para darle estilos al formato. Aquí está el fichero:
.boxed {
vertical-align: baseline;
border: 1px solid #ec8777;
background: linear-gradient(to right, #e5a98c, #f5a593, #f7a6a0);
border-radius: 4px;
padding: 3px 7px;
}