Search code examples
wordpresswordpress-gutenberg

How to set different text alignments for each text component in a wordpress plugin?


In this example, each text component should have its own text-align style setting, but the <AlignmentToolbar> seems to only provide one alignment value. Is there way to get more than one alignment setting within the same plugin?

        <div {...blockProps}>
        <BlockControls>
            <AlignmentToolbar
                value={attributes.title_align}
                onChange={(val) => setAttributes({ title_align: val })}
            />
        </BlockControls>
        <article>
            <TextControl
                className="title"
                allowedFormats={['core/bold', 'core/italic']}
                style={{ textAlign: attributes.title_align }}
                onChange={(val) => setAttributes({ title: val })}
                value={attributes.title}
                placeholder={ __( 'Title...' ) }
            />
        </article>

        <article>
            <RichText
                tagName="div"
                className="message"
                allowedFormats={['core/bold', 'core/italic', 'core/link']}
                style={{ textAlign: attributes.title_align }}
                value={attributes.message}
                onChange={(val) => setAttributes({ message: val })}
                placeholder={ __( 'Message...' ) }
            />
        </article>
    </div>

Solution

  • The way <alignmentToolbar> (alignmentControl) works is by providing alignment options per block, so unfortunately you cannot have more than one per a block. A possible alternative way to accomplish this could be done with InnerBlocks which control each supported blocks alignment independently, eg:

    import { registerBlockType } from '@wordpress/blocks';
    import { InnerBlocks, useBlockProps } from '@wordpress/block-editor';
    
    registerBlockType('my-plugin/plugin-name', {
        edit: () => {
            const blockProps = useBlockProps();
    
            // Create a template of InnerBlocks with predefined attributes
            const MY_TEMPLATE = [
                ['core/heading', // Heading Block already implements RichText component
                    {
                        placeholder: 'Title...',
                        level: 3,
                        className: 'title'
                    }
                ],
                ['core/paragraph', // Paragraph allows multiple lines to be created
                    {
                        placeholder: 'Message...',
                        className: 'message',
                    }
                ]
            ];
    
            return (
                <div {...blockProps}>
                    <InnerBlocks
                        template={MY_TEMPLATE}
                        templateLock="insert"
                    />
                </div>
            );
        },
    
        save: () => {
            const blockProps = useBlockProps.save();
    
            return (
                <div {...blockProps}>
                    <InnerBlocks.Content />
                </div>
            );
        },
    });
    

    By using the existing core blocks that already implement the RichText component, the style/alignment is done for you. To extend on this, if your block needs to be wrapped in <article>, you can create another custom block that contains just one <RichText> component to save your custom markup. Next, use the additional custom block within a InnerBlock template to enable custom text alignment per block.