Añadir un botón de formato al Toolbar en Gutenberg

17 jun. 2020
·
  • Gutenberg
  • JavaScript
  • What is code
·
  • react

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.

Barra de herramientas autorreferencial 🙂

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:

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:

Demostración gráfica

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 componente RichText 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;
}