// ———————————————————————-
// Thinker, Infrastructure Overseer,
// Strategic Planner and Tech Operations
// —————————————–

Building the ‘Knighttower’ WordPress Block: A Step-by-Step Tutorial

Introduction

The ‘Knighttower’ block is designed to offer users unparalleled flexibility and control over content presentation. Dive into this tutorial to craft a feature-rich WordPress block, complete with customization options.


Step 1: Initial Setup & Folder Structure
  1. Make sure you have the required setup: https://developer.wordpress.org/block-editor/getting-started/devenv/
  2. Create a new directory named Knighttower (or whatever name you will use) inside your WordPress theme or plugin directory. Alternatively, just run the Wp command (recommended for quick boilerplate, more info here):
    • npx @wordpress/create-block Knighttower
  3. Inside the Knighttower directory, create the following subdirectories:
    • src (will contain our source files for the block)
    • build (will contain compiled files)
Knighttower/
|-- package.json
|-- Knighttower.php
|-- build/
|-- src/
    |-- style.scss
    |-- editor.scss
    |-- block.json
    |-- edit.js
    |-- index.js
    |-- save.js
    
Step 2 – block.json: Block Metadata

Purpose: The metadata acts as the DNA of your block. It provides WordPress with crucial details about the block’s properties and functionalities, ensuring that it integrates seamlessly into the editor.

Approach:

  • Use this file to define the block’s core properties.
  • Define essential properties like name and category.
  • Declare custom attributes to allow user customization.
{
	"$schema": "https://schemas.wp.org/trunk/block.json",
	"apiVersion": 3,
	"name": "custom-block/knighttower",
	"version": "0.1.0",
	"title": "Knightotwer / Custom Content",
	"category": "widgets",
	"icon": "smiley",
	"description": "Example block scaffolded with Create Block tool.",
	"example": {},
	"attributes": {
		"width": {
			"type": "string",
			"default": "100%"
		},
		"padding": {
			"type": "string"
		},
		"margin": {
			"type": "string"
		},
		"minimumHeight": {
			"type": "string"
		}
	},
	"supports": {
		"spacing": {
			"margin": true,
			"padding": true
		},
		"dimensions": {
			"width": true,
			"minimumHeight": true
		},
		"html": false
	},
	"textdomain": "knighttower",
	"editorScript": "file:./index.js",
	"editorStyle": "file:./index.css",
	"style": "file:./style-index.css"
}
Step 3 – style.css & editor.css: Block Styling

Ensure that your block has a consistent appearance on both the frontend and the editor.

style.scss (or css if not using sass)

/**
 * The following styles get applied both on the front of your site
 * and in the editor.
 *
 * Replace them with your own styles or remove the file completely.
 */

.wp-block-custom-block-knighttower {
	background-color: #21759b;
	color: #fff;
	padding: 2px;
}

editor.scss (or css if not using sass)

/**
 * The following styles get applied inside the editor only.
 *
 * Replace them with your own styles or remove the file completely.
 */

.wp-block-custom-block-knighttower {
	border: 2px dotted #f00;
}
step 4 – edit.js: The Block’s Editing Experience

Purpose: This is where you shape the user’s interaction with the block in the editor. By defining UI components, toolbar settings, and nested block capabilities, you offer a dynamic editing experience.

Approach:

  • Implement UI components for custom attributes.
  • Use components like InnerBlocks for nested functionality.
  • Provide toolbar settings for customization.

Note: Out block supports “padding” and “margin”, nested blocks, but it also has a “width” and “height”


/**
 * Lets webpack process CSS, SASS or SCSS files referenced in JavaScript files.
 * Those files can contain any CSS code that gets applied to the editor.
 *
 * @see https://www.npmjs.com/package/@wordpress/scripts#using-css
 */
import './editor.scss';

/**
 * React hook that is used to mark the block wrapper element.
 * It provides all the necessary props like the class name.
 *
 * @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-block-editor/#useblockprops
 */
import {
	InnerBlocks,
	BlockControls,
	BlockVerticalAlignmentToolbar,
	AlignmentToolbar,
	InspectorControls,
	useBlockProps,
	store as blockEditorStore
} from '@wordpress/block-editor';

import {
	__experimentalUseCustomUnits as useCustomUnits,
	PanelBody,
	__experimentalUnitControl as UnitControl
} from '@wordpress/components';
import { useDispatch } from '@wordpress/data';
import { __ } from '@wordpress/i18n';

/**
 * The edit function describes the structure of your block in the context of the
 * editor. This represents what the editor will render when the block is used.
 *
 * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-edit-save/#edit
 *
 * @return {WPElement} Element to render.
 */
function Edit({ attributes, setAttributes }) {
	const { width, verticalAlignment, align, paddingTopBottom, paddingLeftRight, marginTopBottom, marginLeftRight, minimumHeight } = attributes;

	// Define available units.
	const units = useCustomUnits({
		availableUnits: ['%', 'px', 'em', 'rem', 'vw']
	});

	const { updateBlockAttributes } = useDispatch(blockEditorStore);

	// Define styles and classes for the block.
	const blockProps = useBlockProps({
		style: {
			width: width,
			padding: `${paddingTopBottom} ${paddingLeftRight}`,
			margin: `${marginTopBottom} ${marginLeftRight}`,
			minHeight: minimumHeight
		}
	});

	// ... (rest of the imports and beginning of the Edit function)

	return (
		<>
			<BlockControls>
				<AlignmentToolbar
					value={align}
					onChange={(newAlign) => setAttributes({ align: newAlign })}
				/>
				<BlockVerticalAlignmentToolbar
					onChange={(value) => {
						setAttributes({ verticalAlignment: value });
					}}
					value={verticalAlignment}
				/>
			</BlockControls>

			<InspectorControls>
				<PanelBody title={__("Knighttower Block Settings")}>
					<UnitControl
						label={__("Width")}
						labelPosition="edge"
						__unstableInputWidth="80px"
						value={width || ''}
						onChange={(nextWidth) => {
							setAttributes({ width: nextWidth });
						}}
						units={units}
					/>

					<UnitControl
						label={__("Minimum Height")}
						labelPosition="edge"
						__unstableInputWidth="80px"
						value={minimumHeight || ''}
						onChange={(nextMinHeight) => {
							setAttributes({ minimumHeight: nextMinHeight });
						}}
						units={units}
					/>

					{/* ... (add other controls here as needed) */}
				</PanelBody>
			</InspectorControls>

			<div {...blockProps}>
				<InnerBlocks />
			</div>
		</>
	);
}

export default Edit;
step 5 – index.js: Block Registration

Purpose: This acts as your block’s passport, introducing it to WordPress. By registering the block, you ensure that WordPress recognizes and accepts your custom block code.

Approach:

  • Import required functions and components.
  • Register the block with its attributes and functionalities.
/**
 * Registers a new block provided a unique name and an object defining its behavior.
 *
 * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/
 */
import { registerBlockType } from '@wordpress/blocks';

/**
 * Lets webpack process CSS, SASS or SCSS files referenced in JavaScript files.
 * All files containing `style` keyword are bundled together. The code used
 * gets applied both to the front of your site and to the editor.
 *
 * @see https://www.npmjs.com/package/@wordpress/scripts#using-css
 */
import './style.scss';

/**
 * Internal dependencies
 */
import Edit from './edit';
import Save from './save';
import metadata from './block.json';

/**
 * Every block starts by registering a new block type definition.
 *
 * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/
 */
registerBlockType( metadata.name, {
	/**
	 * @see ./edit.js
	 */
	edit: Edit,

	/**
	 * @see ./save.js
	 */
	save: Save,
} );
step 6 – save.js: Block’s Output

Purpose: This is your block’s public face. It defines how the block appears on the website after being edited in WordPress. Ensuring a consistent appearance between the editor and frontend is crucial for user trust.

/**
 * React hook that is used to mark the block wrapper element.
 * It provides all the necessary props like the class name.
 *
 * @see https://developer.wordpress.org/block-editor/reference-guides/packages/packages-block-editor/#useblockprops
 */
import { useBlockProps, InnerBlocks } from '@wordpress/block-editor';

/**
 * The save function defines the way in which the different attributes should
 * be combined into the final markup, which is then serialized by the block
 * editor into `post_content`.
 *
 * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-edit-save/#save
 *
 * @return {WPElement} Element to render.
 */
export default function Save( { attributes } ) {
    const styles = {
        width: attributes.width,
        padding: `${attributes.paddingTopBottom} ${attributes.paddingLeftRight}`,
        margin: `${attributes.marginTopBottom} ${attributes.marginLeftRight}`,
        minHeight: attributes.minimumHeight
    };

    return (
        <div { ...useBlockProps.save() } style={styles}>
            <InnerBlocks.Content />
        </div>
    );
}
step 7 – Custom Attributes

Purpose: Attributes act as adjustable settings for your block. By defining custom attributes, you offer users the power to tweak the block’s appearance and behavior without altering its core code.

Approach:

  • Use the block metadata (block.json) to define custom attributes.
  • Implement UI components in edit.js for users to adjust these attributes. For instance, a slider could be used for width adjustment, while dropdowns or input boxes might be suitable for padding and margin.
  • Utilize these attributes in the block’s editing (edit.js) and saving (save.js) functionalities to dynamically adjust the block’s appearance based on user input.
step 8 – Toolbar Settings

Purpose: Toolbars are user’s toolkits. They offer handy customization options right at the user’s fingertips, ensuring a smooth editing experience.

Approach:

  • Integrate alignment options for content positioning within the block.
  • Add a lock button to prevent accidental edits or changes.
<BlockControls>
    <AlignmentToolbar value={align} onChange={(newAlign) => setAttributes({ align: newAlign })} />
    <BlockVerticalAlignmentToolbar
        onChange={(value) => {
            setAttributes({ verticalAlignment: value });
        }}
        value={verticalAlignment}
    />
</BlockControls>
step 9 – Nested Blocks

Purpose: Nested blocks elevate your block from a static element to a dynamic container. They allow users to insert additional blocks within yours, leading to richer content structures.

Approach:

  • Use the <InnerBlocks /> component, allowing users to add other blocks inside the ‘Knighttower’ block.
<div {...blockProps}>
    <InnerBlocks />
</div>
step 10 – Knighttower.php

Purpose: This PHP script is the bridge between your block’s frontend styles, its editor scripts, and WordPress. It registers the block, ensuring WordPress can utilize it.

Approach:

  • Use the register_block_type function to tell WordPress about your block and link it to the necessary styles and scripts.
<?php
/**
 * Plugin Name:       Knighttower / Custom Block
 * Description:       Example block scaffolded with Create Block tool.
 * Requires at least: 6.1
 * Requires PHP:      7.0
 * Version:           0.1.0
 * Author:            The WordPress Contributors
 * License:           GPL-2.0-or-later
 * License URI:       https://www.gnu.org/licenses/gpl-2.0.html
 * Text Domain:       knighttower
 *
 * @package           custom-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 knighttowerBlockInit()
{
    register_block_type(__DIR__ . '/build');
}
add_action('init', 'knighttowerBlockInit');
Final Step: Code Overview

package.json

{
	"name": "knighttower",
	"version": "0.1.0",
	"description": "Example block scaffolded with Create Block tool.",
	"author": "The WordPress Contributors",
	"license": "GPL-2.0-or-later",
	"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": "^26.10.0"
	}
}

Run “npm run build” to compile the block, that’s it!

Sources:


Posted

in

by

Comments

Let us know your opinion!