Topics

On this page

Last updated on Nov 7, 2024

Developing Custom Block Controls

Block controls allow users to customize the appearance, layout, and behavior of blocks in the WordPress Block Editor. These controls provide an interface for users to make adjustments without needing to code, offering flexibility for users while keeping the editing experience simple.

Screenshot-2024-10-23-at-8.00.24 PM
Custom controls for core/cover block to pause/play video

For developers, understanding how to create these controls enables you to build powerful, user-friendly blocks that offer customization options directly in the editor.

Understanding Sidebar (InspectorControls) vs Inline (Block-Level Controls)

In the WordPress Block Editor, controls can be added either in the sidebar or directly within the block itself. Both types of controls serve different purposes and enhance the editing experience in their ways.

InspectorControls (Sidebar Controls)

InspectorControls appear in the right-hand sidebar when editing a block. These controls are used for settings that affect a block’s layout, style, or behavior without directly changing the block’s content. The sidebar is the best place for inputs like color pickers, text inputs, and toggles.

Example: Adding a TextControl and ColorPicker

import { __ } from "@wordpress/i18n";
import { useBlockProps, InspectorControls } from "@wordpress/block-editor";
import { PanelBody, TextControl, ColorPicker } from "@wordpress/components";

const Edit = (props) => {
    const { attributes, setAttributes } = props;
    const { text, backgroundColor } = attributes;

    return (
        <div {...useBlockProps()} style={{ backgroundColor }}>
            <InspectorControls>
                <PanelBody title={__("Block Settings")}>
                    <TextControl
                        label={__("Heading Text")}
                        value={text}
                        onChange={(newText) => setAttributes({ text: newText })}
                    />

                    <ColorPicker
                        label={__("Background Color")}
                        color={backgroundColor}
                        onChange={(colorValue) =>
                            setAttributes({ backgroundColor: colorValue })
                        }
                    />
                </PanelBody>
            </InspectorControls>
            <h2>{text}</h2>
        </div>
    );
};

export default Edit;

Inline (Block-Level Controls)

Also known as the block toolbar, these controls appear directly within or above the block when it is selected. They are designed to give users quick access to essential settings, such as text formatting, alignment, or other immediate adjustments. The block toolbar is all about making fast, in-context changes without navigating away from the block you’re working on.

For a detailed guide on creating and customizing block toolbars, check out the full blog post here.

Dynamic Block Controls: Conditional Controls

Dynamic block controls change based on user input, making blocks more interactive and intuitive. For example, you might show a RangeControl for adjusting font size only if the user has enabled the option for custom font sizes.

Example: Conditionally Showing a Font Size Slider

import { ToggleControl, RangeControl } from "@wordpress/components";

const Edit = (props) => {
    const { attributes, setAttributes } = props;
    const { enableCustomFontSize, fontSize } = attributes;

    return (
        <div>
            <ToggleControl
                label="Enable Custom Font Size"
                checked={enableCustomFontSize}
                onChange={(value) => setAttributes({ enableCustomFontSize: value })}
            />

            {enableCustomFontSize && (
                <RangeControl
                    label="Font Size"
                    value={fontSize}
                    onChange={(value) => setAttributes({ fontSize: value })}
                    min={12}
                    max={100}
                />
            )}
        </div>
    );
};

Saving, Validating, and Rendering Block Controls

When users interact with block controls, their input is saved as block attributes. These attributes are then rendered on the front end to reflect the user’s choices.

Saving Block Controls

Example: Saving and Rendering Block Attributes

const Save = (props) => {
    const { attributes } = props;
    const { text, backgroundColor } = attributes;

    return (
        <div style={{ backgroundColor }}>
            <h2>{text}</h2>
        </div>
    );
};

Save function: This example renders the text and background color chosen by the user. When the content is saved, these attributes ensure the user’s customization appears both in the editor and on the live page.

Validating User Input in Block Controls

Validation ensures that users provide correct and appropriate input in block controls. For instance, you might validate the length of a text field or check if a URL is properly formatted.

Example: Validating Text Input Length

const validateInput = ( value ) => {
    if ( value.length < 5 ) {
        setError( 'Input must be at least 5 characters.' );
    }
};

This function ensures the user provides text input with at least 5 characters, helping avoid invalid or incomplete data.

Optimizing Performance for Block Controls

Reducing Unnecessary Re-Renders

When a block re-renders too often, especially with complex controls, it can degrade performance. To improve performance, ensure that block attributes are only updated when necessary, and avoid expensive state updates.

Example: Using useCallback and useMemo to Optimize Re-Renders

import { useMemo, useCallback } from "react";
import { RangeControl } from "@wordpress/components";

const Edit = (props) => {
    const { attributes, setAttributes } = props;
    const { fontSize } = attributes; // Using useMemo to optimize fontSize range initialization

    const fontSizeRange = useMemo(() => {
        return { min: 12, max: 100 };
    }, []); // Using useCallback to prevent re-creation of the handleFontSizeChange function

    const handleFontSizeChange = useCallback(
        (value) => {
            setAttributes({ fontSize: value });
        },
        [setAttributes]
    );

    return (
        <div>
            <RangeControl
                label="Font Size"
                value={fontSize}
                onChange={handleFontSizeChange}
                min={fontSizeRange.min}
                max={fontSizeRange.max}
            />
        </div>
    );
};

Styling and Accessibility in Block Controls

Using WordPress’s Built-in Component Library

WordPress provides components like TextControl, Button, and ColorPicker to help you maintain a consistent design across blocks. This ensures your custom controls fit naturally into the editor.

.custom-block-control {
    margin: 10px 0;
    padding: 5px;
}

Accessibility Considerations

Make sure your controls are accessible by:

Example: Accessible Toggle Button

<ToggleControl
    label="Enable Feature"
    aria-label="Enable or disable custom feature"
    checked={ isEnabled }
    onChange={ ( value ) => setEnabled( value ) }
/>

By leveraging the power of InspectorControls, dynamic features like conditional controls, validation, and performance optimizations, you can create custom block controls that enhance both the user experience and the flexibility of the WordPress Block Editor. Focusing on performance and accessibility ensures that your blocks not only function well but also offer a seamless experience for all users.


Contributor

Shreya Agarwal

Shreya

Shreya Agarwal

Not Available