2

How can we mimic the columns block in Gutenberg to instead be list elements? I wish I can provide an example, but I have 0 clue on a starting point for this one.

Here's my best explanation...Instead of the columns generating div elements that depend on custom class logic like so...

<div class="wp-block-column block-editor-block-list__block wp-block block-core-columns block-editor-block-list__layout">

I just want the wrapping element to be an <li> for each inner block, with a single parent <ul> to wrap the entire custom block.

Where do I start my journey in building something like this?

Is it possible to duplicate the core functionality that is powered by wp/wp-includes/columns/block.json and some how store that in a plugin as a custom block that does what I am describing above.

My Reasoning

For my client projects we use bullet lists to provide instructions to various students. Many of these bullet lists repeat the same sections (i.e. a warning section, an info section, a guide section, over and over again). So instead of writing the same thing over and over again and posting these "alerts" into lists, we are taking advantage of "Reusable Blocks" and "Block Patterns" to simply grab these alerts in post them into our lists. But the existing list block does not allow users to add inner blocks into their list items. If there was a way for us developers to have the ability to generate a list with inner blocks, that will help solve this issue.

The question is how.

4
  • why do you want to do this? Context will help get you better answers faster and avoid confusion. Have you built blocks before? If so have you used nested blocks?
    – Tom J Nowell
    Jul 21, 2021 at 22:32
  • My reasoning is posted
    – klewis
    Jul 21, 2021 at 23:07
  • 1
    Ah, you want inner blocks that are list items, that makes much more sense
    – Tom J Nowell
    Jul 21, 2021 at 23:50
  • I would do anything to learn how to build something like this. Been looking at twenty twenty one theme all day in vscode just studying it.
    – klewis
    Jul 21, 2021 at 23:53

1 Answer 1

2

This is fairly easy to achieve with two custom blocks: (1) for the wrapper <ul>...</ul> element and (2) another for the <li>...</li> items. Each would use InnerBlocks to allow you to place any blocks within the <li> items.

Basic example to get you started:

import { __ } from '@wordpress/i18n';
import { registerBlockType } from '@wordpress/blocks';
import {
    useBlockProps,
    InnerBlocks,
    __experimentalUseInnerBlocksProps as useInnerBlocksProps,
} from '@wordpress/block-editor';

// List block
registerBlockType('pb/list', {
    apiVersion: 2,

    title: __('List', 'pb'),

    category: 'text',

    edit: (props) => {
        const blockProps = useBlockProps();

        const innerBlocksProps = useInnerBlocksProps(blockProps, {
            allowedBlocks: ['pb/list-item'],
        });

        return (
            <ul { ...innerBlocksProps } />
        );
    },

    save: () => {
        const blockProps = useBlockProps.save();

        return (
            <ul { ...blockProps }>
                <InnerBlocks.Content />
            </ul>
        );
    },
});

// List item block
registerBlockType('pb/list-item', {
    apiVersion: 2,

    title: __('List Item', 'pb'),

    parent: ['pb/list'],

    category: 'text',

    edit: (props) => {
        const blockProps = useBlockProps();

        const innerBlocksProps = useInnerBlocksProps(blockProps);

        return (
            <li { ...innerBlocksProps } />
        );
    },

    save: () => {
        const blockProps = useBlockProps.save();

        return (
            <li { ...blockProps }>
                <InnerBlocks.Content />
            </li>
        );
    },
});
1
  • Thanks, good to know of __experimentalUseInnerBlocksProps +1
    – birgire
    Jul 22, 2021 at 16:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.