Muitas pessoas reclamam sobre os obstáculos para começar a construir blocos e aplicativos Gutenberg. A curva de aprendizado é íngreme, principalmente devido à dificuldade de instalar e configurar o ambiente de desenvolvimento. Além disso, um sólido conhecimento de JavaScript, Node.js, React e Redux são ingredientes indispensáveis para esta receita bastante complexa.

O Manual Oficial do Editor de Blocos do WordPress fornece aos desenvolvedores uma tremenda quantidade de informações, mas você pode se ver perdido naquele mar de detalhes.

E vale a pena mencionar o que Matías Ventura, arquiteto líder do projeto Gutenberg, relatou em sua entrevista com a WP Tavern:

Enquanto há pessoas que podem aprender rapidamente, ainda é uma grande barreira para as pessoas. Eu acho que há várias camadas para isso; a documentação poderia ser uma ordem de magnitude melhor tanto na organização quanto na apresentação. Eu espero que possamos fazer muito mais lá.

Com isso em mente, nós decidimos fornecer um tutorial passo a passo com o objetivo de ajudar nossos leitores a começar com o desenvolvimento de blocos Gutenberg.

Parece interessante? Vamos mergulhar!

Pré-requisitos para o desenvolvimento de blocos Gutenberg

Para este tutorial, as únicas habilidades necessárias serão um bom conhecimento do desenvolvimento de plugins WordPress e pelo menos um entendimento básico de HTML, CSS, JavaScript e React.

Será que este será um projeto ambicioso? Você pode apostar que sim!

Não foi fácil encontrar o compromisso certo entre completude e simplicidade ou decidir quais tópicos incluir e quais deixar de fora.

Esperamos que os leitores intermediários e avançados nos perdoem por não nos aprofundarmos em certos conceitos, tais como React state, Redux store, componentes de alta ordem, e assim por diante. Estes tópicos requerem espaço e atenção adicionais e provavelmente são muito avançados para iniciar o desenvolvimento em bloco (a menos que você seja um desenvolvedor React).

Pela mesma razão, não vamos cobrir alguns dos tópicos mais avançados relacionados ao desenvolvimento de blocos Gutenberg, tais como blocos dinâmicos e meta boxes.

Com o conhecimento que você ganhará ao final deste artigo, você poderá começar a se divertir e ser produtivo imediatamente.

Uma vez que você começar a construir blocos, você estará pronto para melhorar ainda mais suas habilidades e construir blocos Gutenberg ainda mais avançados por conta própria.

O que é um bloco Gutenberg?

Desde que foi lançado pela primeira vez em dezembro de 2018, o editor de blocos foi muito melhorado em todos os aspectos: APIs mais poderosas, uma interface de usuário mais avançada, melhor usabilidade, uma tonelada de novos blocos, as primeiras implementações do Full site editing (Edição completa do site), e muito mais.

Em resumo, mesmo que o Gutenberg ainda esteja em um desenvolvimento pesado, ele percorreu um longo caminho – e hoje, o editor de blocos é um candidato de pleno direito como um construtor confiável e funcional de páginas e sites.

Do ponto de vista de um desenvolvedor, Gutenberg é um aplicativo de página única (SPA) baseado em reações que permite aos usuários do WordPress criar, editar e excluir conteúdo no WordPress. Entretanto, isto não deve fazer você pensar em uma versão melhorada do editor de conteúdo tradicional.

Nós queremos deixar isso claro:

No Gutenberg, o conteúdo é dividido em blocos, que são “bricks” que os usuários podem usar para criar artigos e páginas ou sites inteiros.

Mas o que tecnicamente é um bloco?

Nós gostamos da definição do WordPress:

“Bloco” é o termo abstrato usado para descrever unidades de marcação que, compostas juntas, formam o conteúdo ou layout de uma página da web. A idéia combina conceitos do que no WordPress de hoje nós conseguimos com atalhos, HTML personalizado e incorporação da descoberta em uma única API consistente e experiência do usuário.

Títulos, parágrafos, colunas, imagens, galerias e todos os elementos que compõem a interface do editor, desde painéis de barra lateral até controles de barra de ferramentas de bloqueio, são componentes React.

Então, o que são componentes React? W3Schools fornece a seguinte definição:

Os componentes são bits de código independentes e reutilizáveis. Eles servem ao mesmo propósito que as funções JavaScript, mas funcionam isoladamente e retornam o HTML através de uma função render().

Trabalhando com blocos Gutenberg no WordPress 5.8.
Trabalhando com blocos Gutenberg no WordPress 5.8.

Enquanto que a experiência de edição fornecida pelo Gutenberg é nova em comparação com o editor WordPress clássico, a maneira como o WordPress armazena suas peças de conteúdo no banco de dados não muda em nada. Isso porque o Gutenberg é um aplicativo que funciona dentro do WordPress, mas não muda a maneira como o CMS funciona em sua essência.

Os artigos (isto inclui artigos, páginas e tipos de artigos personalizados) criados com o Gutenberg ainda são armazenados na tabela wp_posts, exatamente como com o editor clássico.

Mas em um artigo criado com o Gutenberg, você encontrará pedaços adicionais de informação na tabela que representam uma diferença fundamental entre artigos criados através do Editor Clássico vs. Gutenberg. Essas informações se parecem com comentários HTML, e elas têm uma função específica: delimitar blocos:

Um post no blog na visualização do editor de código.
Um artigo no blog na visualização do editor de código.

Os delimitadores de blocos dizem ao WordPress qual bloco deve ser apresentado na tela. Eles também fornecem valores para as propriedades do bloco em um objeto JSON. Esses adereços ditam a forma como o bloco deve ser renderizado na tela:

Um artigo do blog armazenado na tabela wp_posts
Um artigo do blog armazenado na tabela wp_posts.

Configurando seu ambiente de desenvolvimento WordPress

A criação de um ambiente moderno de desenvolvimento JavaScript requer um sólido conhecimento de tecnologias avançadas como Webpack, React e JSX, Babel, ESLint, etc.

Intimidado? Não fique! A comunidade WordPress já chegou ao socorro, fornecendo ferramentas poderosas que permitem evitar um processo de configuração manual bagunçado.

Para manter as coisas simples, não iremos cobrir a transpilação neste artigo (que, no entanto, recomendamos que você se familiarize uma vez que você tenha aprendido as bases do desenvolvimento de blocos). Ao invés disso, vamos introduzir duas ferramentas alternativas que você pode usar para configurar rápidamente e facilmente um ambiente de desenvolvimento moderno em JavaScript em poucos minutos. Cabe a você escolher aquele que você achar mais conveniente para o seu projeto.

A criação de um ambiente de desenvolvimento JavaScript para construir blocos Gutenberg é um processo de três etapas:

  1. Instale o Node.js e npm
  2. Configure o ambiente de desenvolvimento
  3. Configure o plugin do bloco

Vamos começar.

1. Instale Node.js e npm

Antes de instalar seu ambiente de desenvolvimento e registrar seu primeiro bloco, você precisará instalar o Node.js e o gerenciador de pacotes do Node (npm).

Você pode instalar o Node.js e npm de várias maneiras diferentes. Mas primeiro, você pode querer verificar se o software já está instalado em sua máquina.

Para fazer isso, abra o terminal e execute o seguinte comando:

node -v

Se o resultado for command not found, então o Node.js não está instalado em seu computador, e você pode prosseguir com a instalação.

Para este artigo, nós escolhemos a opção de instalação mais fácil, que é o Node Installer. Tudo o que você precisa fazer é baixar a versão correspondente do seu sistema operacional e iniciar o assistente de instalação:

Página de downloads do Node.js
Página de downloads do Node.js

Uma vez instalado o Node.js, execute novamente o comando node -v em seu terminal. Você também pode executar o comando npm -v para confirmar que você tem o pacote npm disponível. Agora você está equipado com as seguintes ferramentas:

  • O gerenciador de pacotes npx do Node.js. Isto permite que você execute um comando npm sem instalá-lo primeiro.
  • O gerenciador de pacotes npm do Node.js (veja a documentação). Isto é usado para instalar dependências e rodar scripts.

O próximo passo é a instalação do ambiente de desenvolvimento.

2. Configure o ambiente de desenvolvimento

Assim que você tiver as últimas versões do Node.js e npm em sua máquina local, você precisará de um ambiente de desenvolvimento para WordPress.

Você pode usar um ambiente de desenvolvimento local como o DevKinsta ou usar a ferramenta oficial do WordPress. Vamos dar uma olhada em ambas as opções.

Opção 1: Ambiente de desenvolvimento Local (DevKinsta)

Com apenas alguns cliques, você pode instalar o WordPress localmente usando DevKinsta, nossa moderna ferramenta de desenvolvimento WordPress local. Ou você pode optar por uma ferramenta de desenvolvimento local diferente, como MAMP ou XAMPP:

Crie um novo site WordPress no DevKinsta
Crie um novo site WordPress no DevKinsta

Opção 2: wp-env

Você também pode optar pela ferramentawp-env oficial , que fornece um ambiente WordPress dev local que você pode lançar diretamente da linha de comando. Noah Alen o define da seguinte forma:

Os ambientes locais de WordPress agora são tão simples quanto rodar um único comando. wp-env é uma ferramenta de configuração zero para ambientes locais de WordPress sem dor de cabeça. Ele fornece decisões sobre opções para que os usuários possam rapidamente rodar o WordPress sem perda de tempo. De fato, o objetivo é tornar estes ambientes facilmente acessíveis a todos – seja você um desenvolvedor, designer, gerente ou qualquer outra pessoa.

Se você decidir tentar, a instalação do wp-env requer um esforço mínimo. Basta seguir estes passos:

Passo 1: Confirme a instalação do Docker e do Node.js

Para atender aos requisitos técnicos, você precisará primeiro ter o Docker e o Node.js instalados no seu computador. Isso porque wp-env cria uma instância do Docker rodando um site WordPress. Quaisquer mudanças feitas no código são imediatamente refletidas na instância do WordPress.

Passo 2: Instale @wordpress/env a partir da Linha de Comando

Com o Docker e o Node.js rodando em seu computador, você pode seguir em frente e instalar o ambiente de desenvolvimento do WordPress. Você pode instalar wp-env tanto global quanto localmente. Para fazê-lo globalmente, você precisará executar o seguinte comando de dentro do diretório de plugins (mais sobre isso na caixa de aviso “Importante” abaixo):

npm install -g @wordpress/env

Vamos analisar isso:

Para confirmar que o wp-env foi instalado com sucesso, execute o seguinte comando:

wp-env --version

Você deve ver a atual versão wp-env, o que significa que agora você pode iniciar o ambiente usando o seguinte comando da pasta do seu plugin:

wp-env start

Você pode acessar o painel de controle do WordPress usando o seguinte endereço:

  • http://localhost:8888/wp-admin/

As credenciais padrão são as seguintes:

  • Nome de usuário: admin
  • Senha: password

Configure o seu plugin de bloco

Agora você precisa de um plugin de bloco de partida para construir. Mas ao invés de criar manualmente um plugin de bloco de desenvolvimento com todos os arquivos e pastas necessários, você pode simplesmente executar uma ferramenta de desenvolvimento fornecendo todos os arquivos e configurações que você precisa para começar com o desenvolvimento de blocos.

Novamente, você tem um par de opções para escolher. Vamos dar uma olhada em cada uma delas.

Opção 1: Configurando um plugin de bloco com @wordpress/create-block

@wordpress/create-block é a ferramenta oficial de configuração zero para a criação de blocos Gutenberg:

Create Block é uma forma oficialmente suportada de criar blocos para registrar um bloco para um plugin WordPress. Ele oferece uma configuração de construção moderna sem nenhuma configuração. Ele gera código PHP, JS, CSS e tudo mais que você precisa para iniciar o projeto.

Ele é inspirado em grande parte pela create-react-app. Parabéns ao @gaearon, toda a equipe do Facebook e a comunidade React.

Uma vez que seu ambiente local esteja pronto e funcionando, você pode configurar um bloco inicial simplesmente executando o comando npx @wordpress/create-block, e ele fornecerá todos os arquivos e pastas que você precisa para criar o plugin scaffolding e registrar um novo bloco.

Vamos fazer um teste para ver como funciona.

Da sua ferramenta de Linha de Comando, navegue para o diretório /wp-content/plugins/ e execute o seguinte comando:

npx @wordpress/create-block my-first-block

Quando for solicitado para confirmar, digite y para prosseguir:

Criando um bloco com @wordpress/create-block
Criando um bloco com @wordpress/create-block

O processo leva poucos momentos. Quando estiver completo, você deve obter a seguinte resposta:

O plugin de bloco foi criado
O plugin de bloco foi criado

E é isso aí!

Agora lance seu ambiente de desenvolvimento WordPress e vá para a tela Plugins no painel do WordPress. Um novo plugin chamado “Meu Primeiro Bloco” deveria ter sido adicionado à sua lista de plugins:

O plugin de bloco foi instalado com sucesso
O plugin de bloco foi instalado com sucesso

Ative o plugin se necessário, crie um novo artigo no blog, desça o inseridor de blocos até a seção Widgets e selecione seu novo bloco:

 

Um bloco de exemplo criado com @wordpress/create-block
Um bloco de exemplo criado com @wordpress/create-block

Agora volte para o terminal e mude o diretório atual para o meu primeiro bloco:

cd my-first-block

Então execute o seguinte comando:

npm start

Isto permite que você execute o plugin no modo de desenvolvimento. Para criar o código de produção, você deve usar o seguinte comando:

npm run build

Opção 2: Configurando um plugin de bloco com create-guten-block

create-guten-block é uma ferramenta de desenvolvimento de terceiros para a construção de blocos Gutenberg:

create-guten-block é um dev-toolkit de configuração zero (#0CJS) para desenvolver blocos Gutenberg do WordPress em questão de minutos sem configurar React, webpack, ES6/7/8/Next, ESLint, Babel, etc.

Assim como a ferramenta oficial create-block, create-guten-block é baseado em create-react-app e pode ajudar você a gerar seu primeiro plugin de bloco sem complicações.

O kit de ferramentas fornece tudo o que você precisa para criar um plugin WordPress moderno, incluindo o seguinte:

  • React, JSX e ES6 suporte de sintaxe.
  • webpack processo de desenvolvimento/produção por trás do cenário.
  • Extras de linguagem além do ES6 como o operador de propagação de objetos.
  • CSS auto-prefixado, então você não precisa de -webkit ou outros prefixos.
  • Um script de construção para agrupar JS, CSS e imagens para produção com source-maps.
  • Atualizações sem complicação para as ferramentas acima com uma única dependência cgb-scripts.

Observe a seguinte advertência:

A contrapartida é que estas ferramentas são pré-configuradas para funcionar de uma forma específica. Se o seu projeto precisa de mais personalização, você pode “ejetar” e personalizá-lo, mas então você precisará manter esta configuração.

Uma vez que você tenha um site WordPress local em mãos, abra sua ferramenta de Linha de Comando, navegue para a pasta /wp-content/plugins da sua instalação, e execute o seguinte comando:

npx create-guten-block my-first-block

Você terá que esperar um ou dois minutos enquanto a estrutura do projeto é criada e as dependências são baixadas:

Criando um bloco Gutenberg com create-guten-block
Criando um bloco Gutenberg com create-guten-block

Quando o processo estiver completo, você deve ver a seguinte tela:

Bloco Gutenberg criado com sucesso com create-guten-block
Bloco Gutenberg criado com sucesso com create-guten-block

Esta próxima imagem mostra a estrutura do projeto com o terminal rodando com o Visual Studio Code:

O plugin de bloco no Visual Studio Code
O plugin de bloco no Visual Studio Code

Agora volte para o seu painel do WordPress. Um novo item deve ser listado na tela Plugins – que é o plugin my-first-block:

A tela de Plugins com um novo plugin criado com create-guten-block
A tela de Plugins com um novo plugin criado com create-guten-block

Ative o plugin e volte para o terminal. Mude o diretório atual para my-first-block, então execute npm start:

cd my-first-block
npm start

Você deve obter a seguinte resposta:

npm começou.
npm começou.

Novamente, isto permite que você execute o plugin no modo de desenvolvimento. Para criar o código de produção, você deve usar:

npm run build

Ative o plugin e crie um novo artigo ou página, depois navegue pelos seus blocos e selecione o seu novo bloco Gutenberg:

Um novo bloco criado com create-guten-block
Um novo bloco criado com create-guten-block

Para uma visão mais aprofundada ou em caso de erros, consulte a documentação fornecida por Ahmad Awais.

Uma Introdução rápida do bloco scaffolding

Qualquer uma das duas ferramentas de desenvolvimento – create-block ou create-guten-block – que você optar, você agora tem bloco scaffolding que você pode usar como ponto de partida para construir um plugin de bloco. Mas o que é exatamente um bloco scaffolding?

Bloco scaffolding é um termo curto que descreve a estrutura de diretório de suporte que você precisa para que o WordPress reconheça um bloco. Tipicamente esse diretório inclui arquivos como index.php, index.js, style.css e outros – que, por sua vez, seguram chamadas como register_block_type.

Nós optamos pela ferramenta oficial Create Block dev-tool, como é usada no Manual do Editor de Blocos. Mas mesmo que você decida ir com uma ferramenta de terceiros como create-guten-block, sua experiência não será muito diferente.

Com isso dito, vamos ver detalhadamente a  ferramentacreate-block.

Uma visão detalhada do Bloco Dev-Tool Create

Como mencionamos acima, Create Block é a ferramenta oficial da linha de comando para criar blocos do Gutenberg. Executando @wordpress/create-block em seu terminal, você gera os arquivos PHP, JS e SCSS e o código necessário para registrar um novo tipo de bloco:

npx @wordpress/create-block [options] [slug]
  • [slug] (opcional) – usado para atribuir a slug do bloco e instalar o plugin
  • [options] (opcional) – opções disponíveis

Por padrão, um modelo ESNext é atribuído. Isto significa que você receberá a próxima versão do JavaScript, com a adição da sintaxe JSX.

Se você omitir o nome do bloco, o comando é executado em modo interativo, permitindo que você personalize várias opções antes de gerar os arquivos:

npx @wordpress/create-block
Executando Create Block em modo interativo
Executando Create Block em modo interativo

A imagem abaixo mostra a estrutura de arquivo de um plugin de bloco criado com a ferramenta oficial Create Block:

Arquivos e pastas de um plugin de bloco criado com @wordpress/create-block
Arquivos e pastas de um plugin de bloco criado com @wordpress/create-block

Com isso dito, vamos ver os principais arquivos e pastas do nosso novo plugin de blocos.

O arquivo do Plugin

Com o arquivo principal do plugin você registra o bloco no servidor:

<?php
/**
 * Plugin Name:       Kinsta Academy Block
 * Plugin URI:        https://kinsta.com/
 * Description:       An example block for Kinsta Academy students
 * Requires at least: 5.9
 * Requires PHP:      7.0
 * Version:           0.1.0
 * Author:            Kinsta Students
 * License:           GPL-2.0-or-later
 * License URI:       https://www.gnu.org/licenses/gpl-2.0.html
 * Text Domain:       ka-example-block
 *
 * @package           ka-example-block
 */

/**
 * Registers the block using the metadata loaded from the `block.json` file.
 * Behind the scenes, it registers also all assets so they can be enqueued
 * through the block editor in the corresponding context.
 *
 * @see https://developer.wordpress.org/reference/functions/register_block_type/
 */
function ka_example_block_ka_example_block_block_init() {
	register_block_type( __DIR__ . '/build' );
}
add_action( 'init', 'ka_example_block_ka_example_block_block_init' );

A função register_block_type registra um tipo de bloco no servidor usando os metadados armazenados no arquivo block.json.

A função leva dois parâmetros:

  • O nome do tipo de bloco incluindo o namespace, ou um caminho para a pasta onde o arquivo block.json está localizado, ou um objeto WP_Block_Type completo
  • Um conjunto de argumentos do tipo bloco

No código acima, a constante mágica __DIR__ retorna a pasta atual. Isso significa que o arquivo block.json reside na subpasta /build.

O arquivo package.json

O arquivo package.json define as propriedades e scripts JavaScript para o seu projeto. Aqui é onde você pode instalar as dependências do seu projeto.

Para entender melhor para que serve este arquivo, abra-o com seu editor de código favorito:

{
	"name": "ka-example-block",
	"version": "0.1.0",
	"description": "An example block for Kinsta Academy students",
	"author": "Kinsta Students",
	"license": "GPL-2.0-or-later",
	"homepage": "https://kinsta.com/",
	"main": "build/index.js",
	"scripts": {
		"build": "wp-scripts build",
		"format": "wp-scripts format",
		"lint:css": "wp-scripts lint-style",
		"lint:js": "wp-scripts lint-js",
		"packages-update": "wp-scripts packages-update",
		"plugin-zip": "wp-scripts plugin-zip",
		"start": "wp-scripts start"
	},
	"devDependencies": {
		"@wordpress/scripts": "^24.1.0"
	},
	"dependencies": {
		"classnames": "^2.3.2"
	}
}

A propriedade scripts é um dicionário que contém comandos que são executados em vários momentos do ciclo de vida de um pacote usando npm run [cmd].

Neste artigo, nós estaremos usando os seguintes comandos:

  • npm run build – cria uma estrutura de produção (comprimida)
  • npm run start ou npm start – cria uma estrutura de desenvolvimento (sem compressão)

dependencies e devDependencies são dois objetos que mapeiam um nome de pacote para uma versão. dependencies são necessários na produção, enquanto devDependences são necessários apenas para o desenvolvimento local (leia mais).

A única dependência padrão do dev é o pacote @wordpress/scripts, que é definido como “uma coleção de scripts reutilizáveis feitos sob medida para o desenvolvimento do WordPress”.

O arquivo block.json

Começando com o WordPress 5.8, o arquivo de metadados block.json é a forma canônica de registrar os tipos de blocos.

Ter um arquivo block.json oferece vários benefícios, incluindo melhor desempenho e melhor visibilidade no Diretório de Plugins do WordPress:

De uma perspectiva de desempenho, quando os temas suportam ativos de lazy loading (carregamento preguiçoso), os blocos registrados no block.json terão sua fila de consulta de ativos otimizada fora da caixa. O frontend CSS e os ativos JavaScript listados nas propriedades style ou script só serão consultados quando o bloco estiver presente na página, resultando na redução do tamanho da página.

A execução do comando @wordpress/create-block gera o seguinte arquivo block.json:

{
	"$schema": "https://schemas.wp.org/trunk/block.json",
	"apiVersion": 2,
	"name": "ka-example-block/ka-example-block",
	"version": "0.1.0",
	"title": "Kinsta Academy Block",
	"category": "widgets",
	"icon": "superhero-alt",
	"description": "An example block for Kinsta Academy students",
	"supports": {
		"html": false
	},
	"textdomain": "ka-example-block",
	"editorScript": "file:./index.js",
	"editorStyle": "file:./index.css",
	"style": "file:./style-index.css"
}

Aqui está a lista completa de propriedades padrão:

  • apiVersion – a versão da API usada pelo bloco (a versão atual é 2)
  • name – um identificador único para um bloco incluindo um namespace
  • version – a versão atual de um bloco
  • title – um título de exibição para um bloco
  • category – uma categoria de bloco
  • icon – uma slug Dashicon ou um ícone SVG personalizado
  • description – uma breve descrição visível no inspetor de bloco
  • supports – um conjunto de opções para controlar os recursos usados no editor
  • textdomain – o domínio de texto do plugin
  • editorScript – definição do script do editor
  • editorStyle – definição do estilo do editor
  • style – fornece estilos alternativos para um bloco

Além das propriedades listadas acima, você pode (e provavelmente irá) definir um objeto attributes fornecendo informações sobre os dados armazenados pelo seu bloco. Em seu block.json você pode definir qualquer número de atributos em pares chave/valor, onde a chave é o nome do atributo e o valor é a definição do atributo.

Dê uma olhada no seguinte exemplo de definições de atributos:

"attributes": {
	"content": {
		"type": "array",
		"source": "children",
		"selector": "p"
	},
	"align": {
		"type": "string",
		"default": "none"
	},
	"link": { 
		"type": "string", 
		"default": "https://kinsta.com" 
	}
},

Veremos com mais detalhes o arquivo block.json mais tarde no artigo, mas você também pode querer verificar o Manual do Editor de Blocos para informações mais detalhadas sobre os metadados e atributos do block.json.

A pasta src

A pasta src é onde o desenvolvimento acontece. Nessa pasta, você encontrará os seguintes arquivos:

  • index.js
  • edit.js
  • save.js
  • editor.scss
  • style.scss

index.js

O arquivo index.js é o seu ponto de partida. Aqui você irá importar dependências e registrar o tipo de bloco no servidor:

import { registerBlockType } from '@wordpress/blocks';

import './style.scss';

import Edit from './edit';
import save from './save';
import metadata from './block.json';

registerBlockType( metadata.name, {
	/**
	 * @see ./edit.js
	 */
	edit: Edit,

	/**
	 * @see ./save.js
	 */
	save,
} );

A primeira declaração importa a função registerBlockType do pacote @wordpress/blocks. As seguintes instruções de importação importam a folha de estilo com as funções Edit e save, e um objeto de metadados do arquivo block.json.

A função registerBlockType registra o componente no cliente. A função toma dois parâmetros: um nome de bloco e um objeto de configuração de bloco.

A função Edit fornece a interface do bloco como renderizado no editor de blocos, enquanto a função save fornece a estrutura que será serializada e salva no banco de dados (leia mais).

edit.js

edit.js é onde você irá construir a interface de administração do bloco:

import { __ } from '@wordpress/i18n';
import { useBlockProps } from '@wordpress/block-editor';
import './editor.scss';

export default function Edit() {
	return (
		<p {...useBlockProps()}>
			{__('My First Block – hello from the editor!', 'my-first-block')}
		</p>
	);
}

Primeiro, ele importa a função __ do pacote @wordpress/i18n (este pacote contém uma versão JavaScript das funções de tradução), o hook de Reação useBlockProps, e o arquivo editor.scss.

Depois disso, ele exporta o componente React (leia mais sobre declarações de importação e exportação ).

save.js

O arquivo save.js é onde nós construímos a estrutura do bloco a ser salvo no banco de dados:

import { __ } from '@wordpress/i18n';
import { useBlockProps } from '@wordpress/block-editor';

export default function save() {
	return (
		<p {...useBlockProps.save()}>
			{__(
				'My First Block – hello from the saved content!',
				'my-first-block'
			)}
		</p>
	);
}

editor.scss e style.scss

Além dos scripts, dois arquivos SASS residem nas pastas src. O arquivo editor.scss contém os estilos aplicados ao bloco no contexto do editor, enquanto o arquivo style.scss contém os estilos do bloco para exibição no frontend, bem como no editor. Vamos analisar mais a fundo estes arquivos na segunda parte deste guia.

O node_modules e o build folders

A pasta node_modules contém módulos node e suas dependências. Não entraremos nesse assunto sobre os pacotes para o node, pois está além do escopo deste artigo, mas você pode ler mais neste artigo sobre onde o npm instala os pacotes.

A pasta build contém os arquivos JS e CSS resultantes do processo de construção. Você pode ler mais sobre o processo de construção nos guias ESNext syntax e JavaScript Build Setup.

O Projeto: Construindo seu primeiro bloco do Gutenberg

É hora de sujar nossas mãos. Esta seção ensinará a você como criar um plugin fornecendo um bloco CTA chamado Kinsta Academy Block.

O bloco será composto de duas colunas, com uma imagem à esquerda e um parágrafo de texto à direita. Um botão com um link customizável será colocado abaixo do texto:

O tipo de bloco que você aprenderá a construir neste guia.
O tipo de bloco que você aprenderá a construir neste guia.

Este é apenas um exemplo simples, mas nos permite cobrir o básico do desenvolvimento de blocos Gutenberg. Uma vez que você tenha uma compreensão clara do básico, você pode ir em frente e criar blocos Gutenberg cada vez mais complexos com a ajuda do Manual do Editor de Blocos e qualquer outro dos vastos recursos disponíveis lá fora.

Assumindo que você tenha a última versão do WordPress rodando no seu ambiente de desenvolvimento local, aqui está o que você vai aprender daqui em diante:

Prontos… prontos… vamos!

Como configurar o Plugin Starter Block

Inicie sua ferramenta de linha de comando e navegue até a pasta /wp-content/plugins:

Novo terminal em pasta no Mac OS
Novo terminal em pasta no Mac OS

Agora, execute o seguinte comando:

npx @wordpress/create-block

Este comando gera os arquivos PHP, SCSS e JS para registrar um bloco em modo interativo, permitindo que você adicione facilmente os dados necessários para o seu bloco. Para nosso exemplo vamos usar os seguintes detalhes:

  • Variante do modelo: estático
  • Bloco: ka-example-block
  • Internal namespace: ka-example-block
  • Título do bloco de exibição: Bloco da Kinsta Academy
  • Breve descrição do bloco: Um bloco de exemplo para estudantes da Kinsta Academy
  • Dashicon: super-hero-alt
  • Nome da categoria: widgets
  • Você quer personalizar o plugin de WordPress?: sim
  • A página inicial do plugin: Kinsta® Hospedagem na Nuvem para todos os seus projetos Web
  • Versão atual do plugin: 0.1.0
  • Autor do plugin: seu nome
  • Licença:
  • Link para o texto da licença:
  • Caminho de domínio personalizado para traduções:

A instalação do plugin e de todas as dependências leva alguns minutos. Quando o processo estiver completo, você verá a seguinte resposta:

O bloco de exemplo foi instalado e registrado para desenvolvimento.
O bloco de exemplo foi instalado e registrado para desenvolvimento.

Agora, execute o seguinte comando da pasta /wp-content/plugins:

cd ka-example-block
Executando comandos a partir do Visual Studio Code Terminal
Executando comandos a partir do Visual Studio Code Terminal

Finalmente, de dentro da pasta do seu plugin (ka-example-block no nosso exemplo), você pode começar o desenvolvimento com:

npm start

Agora abra a tela Plugins para encontrar e ativar o plugin Kinsta Academy Block:

Ativar o bloco de exemplo
Ativar o bloco de exemplo

Crie um novo artigo, abra o inseridor de blocos e desça até a categoria Design. Clique para adicionar o Kinsta Academy Block:

Um bloco inicial construído com @wordpress/create-block
Um bloco inicial construído com @wordpress/create-block

block.json em ação

Como mencionamos anteriormente, o registro do bloco do lado do servidor ocorre no arquivo principal .php. Entretanto, nós não vamos definir as configurações no arquivo .php. Ao invés disso, nós estaremos usando o arquivo block.json. Então, abra o block.json novamente e dê uma olhada mais de perto nas configurações padrão:

{
	"$schema": "https://schemas.wp.org/trunk/block.json",
	"apiVersion": 2,
	"name": "ka-example-block/ka-example-block",
	"version": "0.1.0",
	"title": "Kinsta Academy Block",
	"category": "widgets",
	"icon": "superhero-alt",
	"description": "An example block for Kinsta Academy students",
	"supports": {
		"html": false
	},
	"textdomain": "ka-example-block",
	"editorScript": "file:./index.js",
	"editorStyle": "file:./index.css",
	"style": "file:./style-index.css"
}

Scripts e estilos

editorScript , editorStyle, e style propriedades fornecem os caminhos relativos aos scripts e estilos frontend e backend. Você não precisa registrar manualmente os scripts e estilos definidos aqui porque estes são automaticamente registrados e consultados pelo WordPress. Para provar isso, abra o inspetor do navegador e abra a aba Rede:

Inspeção de recursos DevTools no Chrome DevTools.
Inspeção de recursos DevTools no Chrome DevTools.

Como você pode ver na imagem acima, nosso script index.js residente na pasta de construção tem sido regularmente consultado sem a necessidade de adicionar qualquer código PHP.

Etiquetas UI

As propriedades title e description fornecem etiquetas necessários para identificar o bloco no editor:

 

Nome e descrição do bloco na barra lateral do bloco
Nome e descrição do bloco na barra lateral do bloco

Palavras-chave

Como mencionamos anteriormente, você pode configurar com precisão suas configurações de bloco usando propriedades e atributos. Por exemplo, você pode adicionar um ou mais keywords para ajudar os usuários a pesquisar blocos:

"keywords": [ 
		"kinsta", 
		"academy", 
		"superhero" 
	],

Se você agora inserir “kinsta”, “academy” ou “superhero” no inseridor rápido, o editor irá sugerir a você o bloco de Kinsta Academy:

Procura de um bloco usando uma palavra-chave no inseridor rápido
Procura de um bloco usando uma palavra-chave no inseridor rápido

 

Localização

Se você está se perguntando como a localização das strings no arquivo JSON acontece, aqui está a resposta:

Em JavaScript, você pode usar agora o método registerBlockTypeFromMetadata do pacote @wordpress/blocks para registrar um tipo de bloco usando os metadados carregados do arquivo block.json. Todas as propriedades localizadas são automaticamente envolvidas em _x (do pacote @wordpress/i18n ) chamadas de função similares a como funciona em PHP com register_block_type_from_metadata. O único requisito é definir a propriedade textdomain no arquivo block.json.

Aqui nós estamos usando a função registerBlockType ao invés de registerBlockTypeFromMetadata, pois esta última foi depreciada desde o Gutenberg 10.7, mas o mecanismo é o mesmo.

Usando componentes incorporados: O componente RichText

Os elementos que compõem um bloco do Gutenberg são os componentes React, e você pode acessar esses componentes através da variável global wp. Por exemplo, tente digitar wp.editor no console do seu navegador. Isto lhe dará a lista completa dos componentes incluídos no módulo wp.editor. Percorra a lista e adivinhe para que componentes são destinados por seus nomes. Da mesma forma, você pode verificar a lista de componentes incluídos no módulo wp.components:

Componentes do WP
Componentes do WP

Agora volte para o arquivo edit.js e dê uma olhada mais de perto no script:

import { __ } from '@wordpress/i18n';
import { useBlockProps } from '@wordpress/block-editor';
import './editor.scss';

export default function Edit() {
	return (
		<p { ...useBlockProps() }>
			{ __(
				'Kinsta Academy Block – hello from the editor!',
				'ka-example-block'
			) }
		</p>
	);
}

Este código gera um bloco estático com texto simples e não editável. Mas nós podemos mudar as coisas facilmente:

O bloco de partida no editor de código
O bloco de partida no editor de código

Para tornar o texto editável, você terá que substituir a tag <p> atual por um componente que torne o conteúdo de entrada editável. Para isso, o Gutenberg fornece o componente RichText embutido.

Adicionar um componente incorporado ao seu bloco é um processo de 5 passos:

  1. Importe os componentes necessários de um pacote WordPress
  2. Inclua os elementos correspondentes em seu código JSX
  3. Defina os atributos necessários no arquivo block.json
  4. Defina os manipuladores de eventos
  5. Salve os dados

Passo 1: Importe os componentes necessários de um pacote WordPress

Agora abra o arquivo edit.js e mude o seguinte comando import:

import { useBlockProps } from '@wordpress/block-editor';

…para:

import { useBlockProps, RichText } from '@wordpress/block-editor';

Desta forma, você está importando a função useBlockProps e o componente RichText do pacote @wordpress/block-editor.

useBlockProps

O useBlockProps e o hook de reação marca o elemento de invólucro do bloco:

Ao usar a API versão 2, você deve usar o novo hook useBlockProps na função edit do bloco para marcar o elemento de invólucro do bloco. O hook irá inserir atributos e manipuladores de eventos necessários para habilitar o comportamento do bloco. Quaisquer atributos que você queira passar para o elemento de bloco devem ser passados por useBlockProps e o valor retornado deve ser espalhado para o elemento.

Para simplificar, useBlockProps atribui automaticamente atributos e classes ao elemento invólucro (o elemento p em nosso exemplo):

Elementos e classes gerados pelo usoBlockProps
Elementos e classes gerados pelo usoBlockProps

Se você remover useBlockProps do elemento do pacote, você terá uma simples sequência do texto sem acesso à funcionalidade e estilo de bloqueio:

O mesmo bloco sem usarBlockProps
O mesmo bloco sem usarBlockProps

Como explicaremos mais tarde, você também pode passar para useBlockProps um objeto de propriedades para personalizar a saída.

RichText

O componente RichText fornece uma entrada de conteúdo que permite aos usuários editar e formatar o conteúdo. Você encontrará o componente documentado no GitHub em gutenberg/packages/block-editor/src/components/rich-text/README.md.

Passo 2: Inclua os elementos correspondentes em seu código JSX

...

const blockProps = useBlockProps();

return (
	<RichText 
		{ ...blockProps }
		tagName="p"
		onChange={ onChangeContent }
		allowedFormats={ [ 'core/bold', 'core/italic' ] }
		value={ attributes.content }
		placeholder={ __( 'Write your text...' ) }
	/>
);

Vamos comentar sobre o código linha por linha:

  • tagName – o nome da tag do elemento HTML editável
  • onChange – função chamada quando o conteúdo do elemento muda
  • allowedFormats – um conjunto de formatos permitidos. Por padrão, todos os formatos são permitidos
  • value – a string HTML para tornar editável
  • placeholder – texto do espaço reservado para mostrar quando o elemento estiver vazio

Passo 3: Defina os atributos necessários no arquivo block.json

Atributos fornecem informações sobre os dados armazenados por um bloco, tais como conteúdo rico, cor de fundo, URLs, etc.

Você pode definir um número arbitrário de atributos dentro de um objeto attributes em pares chave/valor, onde a chave é o nome do atributo e o valor é a definição do atributo.

Agora abra o arquivo block.json e adicione o seguinte attributes prop:

"attributes": {
	"content": {
		"type": "string",
		"source": "html",
		"selector": "p"
	}
},

O atributo content permite armazenar o texto digitado pelo usuário no campo editável:

  • type indica o tipo de dados armazenados pelo atributo. O tipo é requerido, a menos que você defina uma propriedade enum.
  • source define como o valor do atributo é extraído do conteúdo do artigo. Em nosso exemplo, é o conteúdo HTML. Note que se você não fornecer uma propriedade fonte, os dados são armazenados no delimitador de bloco (leia mais).
  • selector é uma tag HTML ou qualquer outro seletor, tal como um nome de classe ou um atributo id.

Nós iremos passar a função Edit como objeto de propriedades. Então, volte para o arquivo edit.js e faça a seguinte mudança:

export default function Edit( { attributes, setAttributes } ) { ... }

Etapa 4: Defina os manipuladores de eventos

O elemento RichText tem um atributo onChange, fornecendo uma função a ser chamada quando o conteúdo do elemento muda.

Vamos definir essa função e ver todo o script do edit.js:

import { __ } from '@wordpress/i18n';
import { useBlockProps, RichText } from '@wordpress/block-editor';
import './editor.scss';

export default function Edit( { attributes, setAttributes } ) {
	const blockProps = useBlockProps();

	const onChangeContent = ( newContent ) => {
		setAttributes( { content: newContent } )
	}

	return (
		<RichText 
			{ ...blockProps }
			tagName="p"
			onChange={ onChangeContent }
			allowedFormats={ [ 'core/bold', 'core/italic' ] }
			value={ attributes.content }
			placeholder={ __( 'Write your text...' ) }
		/>
	);
}

Agora salve o arquivo e volte ao seu painel de controle do WordPress, crie um novo artigo ou página e adicione seu bloco personalizado:

A saída do componente RichText no Editor de Blocos.
A saída do componente RichText no Editor de Blocos.

Adicione algum texto e mude para a visualização de código. Aqui está como seu código deve ser:

<!-- wp:ka-example-block/ka-example-block -->
<p class="wp-block-ka-example-block-ka-example-block">Kinsta Academy Block – hello from the saved content!</p>
<!-- /wp:ka-example-block/ka-example-block -->

Como você pode ver, se você mudar para o Editor de Código, o conteúdo do seu bloco mudou. Isso porque você tem que modificar o arquivo save.js para armazenar a entrada do usuário no banco de dados quando o artigo é salvo.

Passo 5: Salve os dados

Agora abra o arquivo save.js e mude o script da seguinte forma:

import { __ } from '@wordpress/i18n';
import { useBlockProps, RichText } from '@wordpress/block-editor';

export default function save( { attributes } ) {
	const blockProps = useBlockProps.save();
	return (
		<RichText.Content 
			{ ...blockProps } 
			tagName="p" 
			value={ attributes.content } 
		/>
	);
}

Isso é o que estamos fazendo aqui:

  • Importe o componente RichText a partir do pacote block-editor.
  • Passe várias propriedades através de um argumento de objeto para a função save (neste exemplo, nós estamos apenas passando a propriedadeattributes)
  • Devolva o conteúdo do componente RichText
O conteúdo do bloco foi salvo no banco de dados
O conteúdo do bloco foi salvo no banco de dados

Você pode ler mais sobre o componente RichText no Block Editor Handbook e encontrar a lista completa de adereços no Github. Agora vamos dar um passo adiante.

Na próxima seção, você aprenderá como adicionar controles à barra de ferramentas do bloco.

Adicionando controles à barra de ferramentas de bloqueio

A barra de ferramentas do bloco contém um conjunto de controles que permite aos usuários manipularem partes do conteúdo do bloco. Para cada controle da barra de ferramentas, você encontrará um componente:

 

A barra de ferramentas do bloco de parágrafos centrais
A barra de ferramentas do bloco de parágrafos centrais

Por exemplo, você poderia adicionar um controle de alinhamento de texto para o seu bloco. Tudo o que você precisa fazer é importar dois componentes do pacote @wordpress/block-editor.

Nós vamos passar pelos mesmos passos do exemplo anterior:

  1. Importe os componentes necessários de um pacote WordPress
  2. Inclua os elementos correspondentes em seu código JSX
  3. Defina os atributos necessários no arquivo block.json
  4. Defina os manipuladores de eventos
  5. Salve os dados

Passo 1: Importação de componentes BlockControls e AlignmentControl de @wordpress/block-editor

Para adicionar um controle de alinhamento à barra de ferramentas do bloco, você precisa de dois componentes:

  • BlockControls torna uma barra de ferramentas dinâmica de controles (indocumentada).
  • AlignmentControl torna um menu suspenso que exibe opções de alinhamento para o bloco selecionado (leia mais)

Abra o arquivo edit.js e edite a declaração import como mostrado abaixo:

import { 
	useBlockProps, 
	RichText, 
	AlignmentControl, 
	BlockControls 
} from '@wordpress/block-editor';

Passo 2: Adicione elementos BlockControls e AlignmentControl

Vá para a função Edit e insira o elemento <BlockControls /> no mesmo nível que <RichText />. Depois adicione e <AlignmentControl /> dentro do <BlockControls />:

export default function Edit( { attributes, setAttributes } ) {
	const blockProps = useBlockProps();
	return (
		<>
			<BlockControls>
				<AlignmentControl
					value={ attributes.align }
					onChange={ onChangeAlign }
				/>
			</BlockControls>
			<RichText 
				{ ...blockProps }
				tagName="p"
				onChange={ onChangeContent }
				allowedFormats={ [ 'core/bold', 'core/italic' ] }
				value={ attributes.content }
				placeholder={ __( 'Write your text...' ) }
				style={ { textAlign: attributes.align } }
			/>
		</>
	);
}

No código acima, <> e </> são a breve sintaxe para declarar fragmentos do React, que é como retornamos múltiplos elementos no React.

Neste exemplo, AlignmentControl tem dois atributos:

  • value fornece o valor atual para o elemento
  • onChange fornece um manipulador de eventos para executar quando o valor muda

Nós também definimos atributos adicionais para o elemento RichText (veja a lista completa de atributos com exemplos)

Passo 3: Defina o atributo de alinhamento no block.json

Agora vá para o arquivo block.json e adicione o atributo align:

"align": {
	"type": "string",
	"default": "none"
}

Quando terminar, volte ao editor de blocos, atualize a página e selecione o bloco. Você deve ver uma mensagem de erro dentro do seu bloco.

O bloco exibe uma mensagem de erro
O bloco exibe uma mensagem de erro

A razão é que ainda não definimos nosso organizador de eventos.

Passo 4: Defina os manipuladores de eventos

Agora defina onChangeAlign:

const onChangeAlign = ( newAlign ) => {
	setAttributes( { 
		align: newAlign === undefined ? 'none' : newAlign, 
	} )
}

Se newAlign é undefined, então nós definimos newAlign para none. Caso contrário, nós usamos newAlign.

Nosso script edit.js deve estar completo (por enquanto):

export default function Edit( { attributes, setAttributes } ) {
	const blockProps = useBlockProps();
	const onChangeContent = ( newContent ) => {
		setAttributes( { content: newContent } )
	}
	const onChangeAlign = ( newAlign ) => {
		setAttributes( { 
			align: newAlign === undefined ? 'none' : newAlign, 
		} )
	}
	return (
		<>
			<BlockControls>
				<AlignmentControl
					value={ attributes.align }
					onChange={ onChangeAlign }
				/>
			</BlockControls>
			<RichText 
				{ ...blockProps }
				tagName="p"
				onChange={ onChangeContent }
				allowedFormats={ [ 'core/bold', 'core/italic' ] }
				value={ attributes.content }
				placeholder={ __( 'Write your text...' ) }
				style={ { textAlign: attributes.align } }
			/>
		</>
	);
}

Agora você pode voltar para o editor e alinhar o conteúdo do bloco. Seu bloco deve agora exibir orgulhosamente uma Barra de Ferramentas de Alinhamento.

Nosso bloco agora tem uma Barra de Ferramentas de Alinhamento
Nosso bloco agora tem uma Barra de Ferramentas de Alinhamento

Mas se você salvar o artigo, verá que o conteúdo do seu bloco não está alinhado no frontend como está no editor do bloco. Isso porque precisamos modificar a função de save para armazenar o conteúdo e os atributos do bloco no banco de dados.

Passo 5: Salve os dados

Abra o save.js e mude a função save da seguinte forma:

export default function save( { attributes } ) {
	const blockProps = useBlockProps.save();
	return (
		<RichText.Content 
			{ ...blockProps } 
			tagName="p" 
			value={ attributes.content } 
			style={ { textAlign: attributes.align } }
		/>
	);
}

Finalmente, para tornar o código mais legível, você pode extrair as propriedades individuais do objeto attribute usando a sintaxe de atribuição de desestruturação:

export default function save( { attributes } ) {
	const blockProps = useBlockProps.save();
	const { content, align } = attributes;
	return (
		<RichText.Content 
			{ ...blockProps } 
			tagName="p" 
			value={ content } 
			style={ { textAlign: align } }
		/>
	);
}

Você pode fazer o mesmo no arquivo edit.js.

Agora salve o arquivo e mude para o Editor de Código. O código do bloco deve ser algo parecido com isto:

<!-- wp:ka-example-block/ka-example-block {"align":"right"} -->
<p class="wp-block-ka-example-block-ka-example-block" style="text-align:right">This is my first editable <strong>Gutenberg</strong> <em>block</em> 😎</p>
<!-- /wp:ka-example-block/ka-example-block -->
Verificação dos controles da barra de ferramentas do bloco
Verificação dos controles da barra de ferramentas do bloco

E é isso! Você acabou de adicionar um controle de alinhamento à barra de ferramentas do seu bloco 🤓

Você pode ler mais sobre os controles da barra de ferramentas de blocos no Manual do Editor de Blocos.

Personalizando a barra lateral de configurações de blocos

Você também pode adicionar controles ao bloco configurações da barra lateral (ou até mesmo criar uma nova barra lateral para o seu aplicativo).

A API fornece um componenteInspectorControls para isso.

O Manual do Editor de Blocos explica como usar a Barra Lateral de Configurações:

A Barra lateral de configurações é usada para exibir configurações menos utilizadas ou configurações que requerem mais espaço na tela. A Barra lateral de configurações deve ser usada somente para configurações de nível de bloco.

Se você tem configurações que afetam apenas o conteúdo selecionado dentro de um bloco (exemplo: a configuração “negrito” para o texto selecionado dentro de um parágrafo): não o coloque dentro da barra lateral de configurações. A Barra lateral de configurações é exibida mesmo quando se edita um bloco no modo HTML, então ela só deve conter configurações de nível de bloco.

Novamente:

  1. Importe os componentes necessários de um pacote WordPress
  2. Inclua os elementos correspondentes em seu código JSX
  3. Defina os atributos necessários no arquivo block.json
  4. Defina os manipuladores de eventos
  5. Salve os dados

Passo 1. Importe os componentes InspectorControls e PanelColorSettings do @wordpress/block-editor

Você pode adicionar vários controles para permitir que os usuários personalizem aspectos específicos do bloco. Por exemplo, você pode fornecer um painel de controle colorido. Para fazer isso, você precisará importar os componentes InspectorControls e PanelColorSettings do módulo block-editor:

import { 
	useBlockProps, 
	RichText, 
	AlignmentControl, 
	BlockControls,
	InspectorControls,
	PanelColorSettings
} from '@wordpress/block-editor';

Passo 2: Inclua os elementos correspondentes em seu código JSX

Agora você pode adicionar os elementos correspondentes ao JSX retornado pela função Edit:

export default function Edit( { attributes, setAttributes } ) {
	const blockProps = useBlockProps();

	const { content, align, backgroundColor, textColor } = attributes;

	const onChangeContent = ( newContent ) => {
		setAttributes( { content: newContent } )
	}
	const onChangeAlign = ( newAlign ) => {
		setAttributes( { 
			align: newAlign === undefined ? 'none' : newAlign, 
		} )
	}
	return (
		<>
			<InspectorControls>
				<PanelColorSettings 
					title={ __( 'Color settings', 'ka-example-block' ) }
					initialOpen={ false }
					colorSettings={ [
						{
						  value: textColor,
						  onChange: onChangeTextColor,
						  label: __( 'Text color', 'ka-example-block' )
						},
						{
						  value: backgroundColor,
						  onChange: onChangeBackgroundColor,
						  label: __( 'Background color', 'ka-example-block' )
						}
					] }
				/>
			</InspectorControls>
			<BlockControls>
				<AlignmentControl
					value={ align }
					onChange={ onChangeAlign }
				/>
			</BlockControls>
			<RichText 
				{ ...blockProps }
				tagName="p"
				onChange={ onChangeContent }
				allowedFormats={ [ 'core/bold', 'core/italic' ] }
				value={ content }
				placeholder={ __( 'Write your text...' ) }
				style={ { textAlign: align, backgroundColor: backgroundColor, color: textColor } }
			/>
		</>
	);
}

Note que nós também atualizamos o atributo style do elemento RichText:

<RichText 
	 { ...blockProps }
	 tagName="p"
	 onChange={ onChangeContent }
	 allowedFormats={ [ 'core/bold', 'core/italic' ] }
	 value={ content }
	 placeholder={ __( 'Write your text...' ) }
	 style={ { textAlign: align, backgroundColor: backgroundColor, color: textColor } }
/>

Passo 3: Defina os atributos necessários no block.json

Agora defina os atributos backgroundColor e textColor no arquivo block.json:

"attributes": {
	"content": {
		"type": "string",
		"source": "html",
		"selector": "p"
	},
	"align": {
		"type": "string",
		"default": "none"
	},
	"backgroundColor": {
		"type": "string"
	},	 
	"textColor": {
		"type": "string"
	}
},

Etapa 4: Defina os manipuladores de eventos

Agora você precisa definir duas funções para atualizar backgroundColor e textColor na entrada do usuário:

const onChangeBackgroundColor = ( newBackgroundColor ) => {
	setAttributes( { backgroundColor: newBackgroundColor } )
}
const onChangeTextColor = ( newTextColor ) => {
	setAttributes( { textColor: newTextColor } )
}

Passo 5: Salve os dados

Um último passo: Abra o arquivo save.js e mude o script como a seguir:

export default function save( { attributes } ) {
	const blockProps = useBlockProps.save();
	const { content, align, backgroundColor, textColor } = attributes;
	return (
		<RichText.Content 
			{ ...blockProps } 
			tagName="p" 
			value={ content } 
			style={ { textAlign: align, backgroundColor: backgroundColor, color: textColor } }
		/>
	);
}

Salve o arquivo e verifique o bloco no editor. Você pode encontrar uma surpresa indesejada: uma mensagem de erro informando que o bloco contém conteúdo inesperado ou inválido.

Mensagem de erro de conteúdo inesperado ou inválido
Mensagem de erro de conteúdo inesperado ou inválido

Isso acontece porque o arquivo save.js é alterado e o código salvo no banco de dados não corresponde ao código usado no editor.

Para corrigir isso, atualize a página, apague qualquer instância do seu bloco e adicione-a novamente ao seu artigo:

O painel Configurações de cores no bloco Configurações da barra lateral
O painel Configurações de cores no bloco Configurações da barra lateral

Faça suas mudanças, salve o artigo e visualize-o no frontend. Agora as mudanças que você fez no editor de blocos devem ser refletidas no site.

O bloco personalizado agora funciona corretamente no frontend.
O bloco personalizado agora funciona corretamente no frontend.

Nesta seção, você irá adicionar novos componentes ao seu tipo de bloco:

  • Um componente ExternalLink que permite aos usuários adicionar um link customizável ao seu bloco personalizado
  • Vários controles da barra lateral permitindo aos usuários personalizar as configurações dos links

Passo 1. Importe os componentes do @wordpress/componentes

Agora você precisa importar vários componentes do @wordpress/components. Abra seu arquivo edit.js e adicione a seguinte declaração import:

import {
	TextControl,
	PanelBody,
	PanelRow,
	ToggleControl,
	ExternalLink
} from '@wordpress/components';
  • PanelBody adiciona um contêiner colapsável à barra lateral de ajustes.
  • PaneRow produz um recipiente genérico para controles da barra lateral.
  • TextControl fornece um controle de entrada de texto.
  • ToggleControl fornece uma chave que permite aos usuários ativar/desativar uma opção específica.
  • ExternalLink é um componente simples para adicionar um link externo.

Passo 2. Inclua os elementos correspondentes em seu código JSX

Primeiro você adicionará o elemento ExternalLink no mesmo nível que o RichText em um contêiner div:

<div { ...blockProps }>
	<RichText 
		...
	/>
	<ExternalLink 
		href={ kaLink }
		className="ka-button"
		rel={ hasLinkNofollow ? "nofollow" : "" }
	>
			{ linkLabel }
	</ExternalLink>

</div>

O componente ExternalLink não está documentado, então nós nos referimos ao próprio componente para obter a lista de atributos disponíveis. Aqui nós estamos usando os atributos href, className e rel.

Por padrão, o valor do atributo rel está definido para noopener noreferrer. Nosso código irá adicionar a palavra-chavenofollow ao atributo rel da tag a resultante quando o controle de alternância estiver ligado.

Agora você pode adicionar configurações de link à barra lateral do bloco.

Primeiro, você adicionará um elemento PanelBody dentro de InspectorControls no mesmo nível do PanelColorSettings:

<InspectorControls>
	<PanelColorSettings 
	...
	/>
	<PanelBody 
		title={ __( 'Link Settings' )}
		initialOpen={true}
	>
	...
	</PanelBody>
</InspectorControls>

Aqui está o que estamos fazendo com isto:

  1. O atributo title fornece o título do painel.
  2. initialOpen define se o painel está ou não inicialmente aberto.

Em seguida, vamos adicionar dois elementos PanelRow dentro de PanelBody, e um elemento TextControl dentro de cada PanelRow:

<PanelBody 
	title={ __( 'Link Settings', 'ka-example-block' )}
	initialOpen={true}
>
	<PanelRow>
		<fieldset>
			<TextControl
				label={__( 'KA link', 'ka-example-block' )}
				value={ kaLink }
				onChange={ onChangeKaLink }
				help={ __( 'Add your Academy link', 'ka-example-block' )}
			/>
		</fieldset>
	</PanelRow>
	<PanelRow>
		<fieldset>
			<TextControl
				label={__( 'Link label', 'ka-example-block' )}
				value={ linkLabel }
				onChange={ onChangeLinkLabel }
				help={ __( 'Add link label', 'ka-example-block' )}
			/>
		</fieldset>
	</PanelRow>
</PanelBody>

O código acima deve agora parecer bastante simples. Os dois controles de texto permitem que os usuários definam o rótulo e a URL do link.

Nós também adicionaremos um adicional PanelRow com um ToggleControl para ligar/desligar uma opção específica, como a inclusão ou não de um atributo:

<PanelRow>
	<fieldset>
		<ToggleControl
			label="Add rel = nofollow"
			help={
				hasLinkNofollow
					? 'Has rel nofollow.'
					: 'No rel nofollow.'
			}
			checked={ hasLinkNofollow }
			onChange={ toggleNofollow }
		/>
	</fieldset>
</PanelRow>

Passo 3: Defina os atributos necessários no block.json

Agora defina os atributos kaLink, linkLabel, e hasLinkNofollow no arquivo block.json:

"kaLink": {
	"type": "string",
	"default": ""
},
"linkLabel": {
	"type": "string",
	"default": "Check it out!"
},
"hasLinkNofollow": {
	"type": "boolean",
	"default": false
}

Nada mais a acrescentar aqui! Vamos passar para a definição das funções de tratamento de eventos.

Passo 4: Defina os manipuladores de eventos

Volte para o arquivo edit.js, adicione os novos atributos ao objeto de atributos, e adicione as seguintes funções:

const { content, align, backgroundColor, textColor, kaLink, linkLabel, hasLinkNofollow } = attributes;

const onChangeKaLink = ( newKaLink ) => {
	setAttributes( { kaLink: newKaLink === undefined ? '' : newKaLink } )
}

const onChangeLinkLabel = ( newLinkLabel ) => {
	setAttributes( { linkLabel: newLinkLabel === undefined ? '' : newLinkLabel } )
}

const toggleNofollow = () => {
	setAttributes( { hasLinkNofollow: ! hasLinkNofollow } )
}

Estas funções atualizam os valores dos atributos correspondentes na entrada do usuário.

Passo 5: Salve os dados

Por último, temos que atualizar a função save no save.js:

export default function save( { attributes } ) {
	
	const { content, align, backgroundColor, textColor, kaLink, linkLabel, hasLinkNofollow } = attributes;

	const blockProps = useBlockProps.save( {
		className: `has-text-align-${ align }`
	} );
	
	return (
		<div 
			{ ...blockProps }
			style={ { backgroundColor: backgroundColor } }
		>
			<RichText.Content 
				tagName="p" 
				value={ content } 
				style={ { color: textColor } }
			/>
			<p>
				<a 
					href={ kaLink }
					className="ka-button"
					rel={ hasLinkNofollow ? "nofollow" : "noopener noreferrer" }
				>
					{ linkLabel }
				</a>
			</p>
		</div>
	);
}

Note que aqui nós usamos um elemento regular a ao invés de ExternalLink.

Você pode ver o resultado na imagem abaixo.

A barra lateral de configurações de link no bloco
A barra lateral de configurações de link no bloco

Adicionando múltiplos estilos de bloco

Em uma seção anterior, você aprendeu como adicionar um controle de barra de ferramentas de bloco permitindo que os usuários alinhem a entrada do usuário. Nós podemos adicionar mais controles de estilo à barra de ferramentas do bloco, mas também podemos fornecer um conjunto de estilos de bloco predefinidos que o usuário pode escolher com um único clique.

Para este propósito, nós vamos usar um recurso útil do API do Bloco: Estilos de Bloco.

Tudo o que você precisa fazer é definir a propriedade block.json styles e declarar os estilos correspondentes no stylesheets (folhas de estilo).

Por exemplo, você pode adicionar a seguinte gama de estilos:

"styles": [
	{
		"name": "default",
		"label": "Default",
		"isDefault": true
	},
	{
		"name": "border",
		"label": "Border"
	}
],

Com isso, você acabou de adicionar um estilo padrão e um estilo adicional chamado border. Agora volte para o editor de blocos:

Dois estilos de blocos pré-construídos.
Dois estilos de blocos pré-construídos.

Os estilos estarão disponíveis para o usuário clicando na chave de bloco e depois procurando pelo Styles panel na Block Settings Sidebar.

Selecione um estilo e verifique as classes aplicadas ao elemento p. Clique com o botão direito do mouse sobre o bloco e Inspect. Uma nova classe foi adicionada com um nome estruturado como a seguir:

is-style-{style-name}

Se você verificou o estilo “Border”, então uma classe is-style-border será adicionada ao elemento p. Se você marcou o estilo “Default”, então uma classe is-style-default será adicionada ao invés disso.

Agora você só tem que declarar as propriedades do CSS. Abra o arquivo editor.scss e substitua os estilos atuais com o seguinte:

.wp-block-ka-example-block-ka-example-block {
    padding: 4px;
}

Agora você pode fazer o mesmo com style.scss. Como mencionamos acima, os estilos definidos em style.scss são aplicados tanto no frontend quanto no editor:

.wp-block-ka-example-block-ka-example-block {
	&.is-style-default{
		border: 0;
        background-color: #FFE2C7;
	}
	&.is-style-border{
		border: 2px solid #000;
        border-radius: 16px;
        background-color: #F6F6F6;
	}
}

E é isso aí! Refresque a página, e divirta-se com seus novos estilos de blocos:

Estilos de blocos comparados
Estilos de blocos comparados

Agrupando blocos Gutenberg com o componente InnerBlocks

Embora totalmente funcional, nosso bloco personalizado ainda não é muito atrativo. Para torná-lo mais atrativo para o público, poderíamos acrescentar uma imagem.

Isto pode acrescentar uma camada de complexidade ao nosso bloco, mas felizmente, você não precisa reinventar a roda porque Gutenberg fornece um componente específico que você pode usar para criar uma estrutura de blocos agrupados.

O componente InnerBlocks é definido da seguinte forma:

OInnerBlocks exporta um par de componentes que podem ser usados em implementações de blocos para permitir o conteúdo de blocos agrupados.

Primeiro, você precisará criar um novo arquivo .js na pasta src. Em nosso exemplo, nós chamaremos este arquivo container.js.

Agora você precisará importar o novo recurso para o arquivo index.js:

import './container';

Volte para container.js e importe os componentes necessários:

import { registerBlockType } from "@wordpress/blocks";
import { __ } from "@wordpress/i18n";
import {
	useBlockProps, 
	InnerBlocks 
} from "@wordpress/block-editor";

O próximo passo é definir um modelo fornecendo a estrutura dentro da qual os blocos serão colocados. No exemplo a seguir, definimos um modelo que consiste em duas colunas contendo um bloco de imagem central e nosso bloco personalizado:

const TEMPLATE = [ [ 'core/columns', { backgroundColor: 'yellow', verticalAlignment: 'center' }, [
	[ 'core/column', { templateLock: 'all' }, [
		[ 'core/image' ],
	] ],
	[ 'core/column', { templateLock: 'all' }, [
		[ 'ka-example-block/ka-example-block', { placeholder: 'Enter side content...' } ],
	] ],
] ] ];

O modelo é estruturado como um conjunto de tipos de bloco (nome do bloco e atributos opcionais).

No código acima, usamos vários atributos para configurar as Colunas e Blocos de Colunas. Especificamente, o atributo templateLock: 'all' bloqueia os blocos de colunas para que o usuário não adicione, reordene ou exclua blocos existentes. templateLock pode assumir um dos seguintes valores:

  • allInnerBlocks está bloqueado, e nenhum bloco pode ser adicionado, reordenado ou removido.
  • insert – Os blocos só podem ser reordenados ou removidos.
  • false – O modelo não está bloqueado.

O modelo é então designado para o elemento InnerBlocks:

<InnerBlocks
	template={ TEMPLATE }
	templateLock="all"
/>

Para evitar qualquer problema de compatibilidade, nós também adicionamos um atributo templateLock ao componente InnerBlocks (veja também o número #17262 e o número #26128).

Aqui está nosso arquivo final container.js:

registerBlockType('ka-example-block/ka-example-container-block', {
	title: __( 'KA Container block', 'ka-example-block' ),
	category: 'design',

	edit( { className } ) {
		
		return(
			<div className={ className }>
				<InnerBlocks
					template={ TEMPLATE }
					templateLock="all"
				/>
			</div>
		)
	},

	save() {
		const blockProps = useBlockProps.save();
		return(
			<div { ...blockProps }>
				<InnerBlocks.Content />
			</div>
		)
	},
});
O bloco final no editor de blocos
O bloco final no editor de blocos

Melhorias adicionais

Nosso bloco é totalmente funcional, mas nós poderíamos melhorá-lo um pouco com algumas pequenas mudanças.

Nós atribuímos o atributo backgroundColor ao parágrafo gerado pelo componente RichText. Entretanto, podemos preferir atribuir a cor de fundo ao recipiente div:

Então, mude o arquivo edit.js e salve.js divs da seguinte forma:

<div 
	{ ...blockProps }
	style={ { backgroundColor: backgroundColor } }
>
...
</div>

Isto permitirá que o usuário mude o fundo do bloco inteiro.

Por outro lado, uma mudança mais relevante envolve o método useBlockProps. No código original, nós definimos a constante blockProps como segue:

const blockProps = useBlockProps();

Mas nós podemos usar o useBlockProps mais efetivamente passando um conjunto de propriedades. Por exemplo, nós podemos importar classnames do módulo classnames e definir o nome da classe do pacote de acordo.

No exemplo a seguir, nós atribuímos um nome de classe baseado no valor do atributo align (edit.js).

import classnames from 'classnames';

...

export default function Edit( { attributes, setAttributes } ) {
	...
	
	const onChangeAlign = ( newAlign ) => {
		setAttributes( { 
			align: newAlign === undefined ? 'none' : newAlign, 
		} )
	}

	const blockProps = useBlockProps( {
		className: `has-text-align-${ align }`
	} );
	...
}

Nós faremos a mesma mudança no arquivo save.js:

import classnames from 'classnames';

...

export default function save( { attributes } ) {
	...
	const { content, align, backgroundColor, textColor, kaLink, linkLabel, hasLinkNofollow } = attributes;

	const blockProps = useBlockProps.save( {
		className: `has-text-align-${ align }`
	} );
	...
}

E isso é um final! Agora você pode executar o desenvolvimento para produção:

npm run build

Resumo

E aqui estamos nós, no final desta incrível jornada! Nós começamos com a configuração do ambiente de desenvolvimento e acabamos criando um tipo de bloco completo.

Como mencionamos na introdução, um conhecimento sólido do Node.js, Webpack, Babel e React é essencial para criar blocos Gutenberg avançados e se posicionar no mercado como um desenvolvedor Gutenberg profissional.

Mas você não precisa ter experiência de React estabelecida para começar a se divertir com o desenvolvimento de blocos. O desenvolvimento de blocos pode lhe dar motivação e objetivos para ganhar habilidades cada vez mais amplas nas tecnologias por trás dos blocos Gutenberg.

Este guia, portanto, está longe de ser completo. É apenas uma introdução a uma grande variedade de tópicos que irão ajudá-lo a começar a construir seus primeiros blocos Gutenberg.

Por esta razão, nós recomendamos que você aprofunde seu conhecimento lendo cuidadosamente a documentação e os guias online. Entre os muitos recursos disponíveis lá fora, nós recomendamos o seguinte:

Se você está apenas começando com o desenvolvimento do WordPress, você pode querer entender os conceitos básicos de desenvolvimento frontend. Aqui está uma lista rápida de recursos que podem ajudar você a começar:

E lembre-se que o código completo dos exemplos deste guia está disponível no Gist.

Agora é à sua vez: Você já desenvolveu algum bloco Gutenberg? Quais são as principais dificuldades que você experimentou até agora? Informe-nos sobre à sua experiência nos comentários!

Carlo Daniele Kinsta

Carlo is a passionate lover of webdesign and front-end development. He has been playing with WordPress for more than 20 years, also in collaboration with Italian and European universities and educational institutions. He has written hundreds of articles and guides about WordPress, published both on Italian and international websites, as well as on printed magazines. You can find him on LinkedIn.