WordPressのブロック開発メモ その5 ツールバーとサイドバー

前回はGutenbergコアのコンポーネントをいくつか紹介しました。

WordPressのブロック開発メモ その4 コンポーネント

今回はツールバーとサイドバーについてです。

ツールバー

ブロックエディタを編集する時にツールバーが出てきます上らへんに出てくるとおもいますが、
まずはそこに追加せずブロックに直接書いてみます。

ツールバーにあるような項目(ツールバーボタン)をブロックに張ってみる。

import React from 'react';
import { useBlockProps } from '@wordpress/block-editor';
import { BlockEditProps } from '@wordpress/blocks';
import { ToolbarButton, ToolbarGroup } from '@wordpress/components';

import { alignLeft, alignCenter, alignRight, alignJustify, alignNone } from '@wordpress/icons';

import KurageExampleBlockProps from './props';
import './editor.scss';

const aligns = {
    Left: alignLeft,
    Center: alignCenter,
    Right: alignRight,
    Justify: alignJustify,
    None: alignNone
};

export default (props: BlockEditProps<KurageExampleBlockProps>) =>
{
    return (
        <div {...useBlockProps()}>
            {
                Object.entries(aligns).map(([label, icon]) => {
                    return <ToolbarButton icon={ icon } label={ label } />;
                })
            }
        </div>
    );
}


ボタンを5個表示しました。

@wordpress/iconsからアイコンを引っ張ってきます。
それをToolbarButtoniconで指定します。
一つ一つ書いていくの面倒なのでリテラルオブジェクトでiconlabelをまとめて定義して一気にレンダリングしてます。

ボタングループ

ボタンを一つのグループに纏めるにはToolbarGroupを使います。

export default (props: BlockEditProps<KurageExampleBlockProps>) =>
{
    return (
        <div {...useBlockProps()}>
            <ToolbarGroup>
            {
                Object.entries(aligns).map(([label, icon]) => {
                    return <ToolbarButton icon={ icon } label={ label } />;
                })
            }
            </ToolbarGroup>
        </div>
    );
}

これでまとまってくれました。

ツールバー完成

最後の仕上げにToolbarで囲みます。

コードが長くなるので大分省略します。
アイコンにlinkcodeを追加します。

import {
    alignLeft,
    alignCenter,
    alignRight,
    alignJustify,
    alignNone,
    link,
    code
} from '@wordpress/icons';

<Toolbar label="てすと">

    <ToolbarGroup>
        <ToolbarButton icon={ link } label="リンク" />
    </ToolbarGroup>

    <ToolbarGroup>
    {
        Object.entries(aligns).map(([label, icon]) => {
            return <ToolbarButton icon={ icon } label={ label } />;
        })
    }
    </ToolbarGroup>

    <ToolbarGroup>
        <ToolbarButton icon={ code } label="コード" />
    </ToolbarGroup>

</Toolbar>

グループ分けで表示されていることが分かります。
若干角も丸い。

ただToolbarlabelを指定しないとこれがまたうまく表示されないんだ。
何でだろ。

ドロップダウンメニュー

import React from 'react';
import KurageExampleBlockProps from './props';
import './editor.scss';
import { useBlockProps } from '@wordpress/block-editor';
import { BlockEditProps } from '@wordpress/blocks';
import { Toolbar, ToolbarGroup, ToolbarDropdownMenu } from '@wordpress/components';
import { useState } from '@wordpress/element';
import {
    alignLeft,
    alignCenter,
    alignRight,
    alignJustify,
    alignNone,
    menu,
} from '@wordpress/icons';

const aligns = {
    Left: alignLeft,
    Center: alignCenter,
    Right: alignRight,
    Justify: alignJustify,
    None: alignNone
};

// 型定義に無いので追加。
declare module '@wordpress/components'
{
    const ToolbarDropdownMenu: any;
}

export default (props: BlockEditProps<KurageExampleBlockProps>) =>
{
    const [iconTitle, setIconTitle] = useState('');

    return (
        <div {...useBlockProps()}>

            <p>{ iconTitle }</p>
            <Toolbar id="test" label='てすと'>

                <ToolbarGroup
                    icon={ menu }
                    label="整列"
                    controls={
                        Object.entries(aligns).map(([title, icon]) => {
                            return ({ title, icon, onClick: () => setIconTitle(title) })
                        })
                    }
                    />

                <ToolbarDropdownMenu
                    icon={ menu }
                    label="整列"
                    text="整列ドロップダウン"
                    controls={
                        Object.entries(aligns).map(([title, icon]) => {
                            return ({ title, icon, onClick: () => setIconTitle(title) })
                        })
                    }
                    />

            </Toolbar>
        </div>
    );
}

最終仕上げ

これまではツールバーを作成してきましたが表示される場所はブロック内でした。

実際のツールバーはブロックの上に浮上してます。
この浮上したツールバーに追加するにはBlockControlsを使用します。

export default (props: BlockEditProps<KurageExampleBlockProps>) =>
{
    const [iconTitle, setIconTitle] = useState('');

    return (
        <div {...useBlockProps()}>

            <p>ツールバー</p>

            <BlockControls>
                <Toolbar id="test" label='てすと'>

                    <ToolbarGroup
                        icon={ menu }
                        label="整列"
                        controls={
                            Object.entries(aligns).map(([title, icon]) => {
                                return ({ title, icon, onClick: () => setIconTitle(title) })
                            })
                        }
                        />

                    <ToolbarDropdownMenu
                        icon={ menu }
                        label="整列"
                        text="整列ドロップダウン"
                        controls={
                            Object.entries(aligns).map(([title, icon]) => {
                                return ({ title, icon, onClick: () => setIconTitle(title) })
                            })
                        }
                        />

                </Toolbar>
            </BlockControls>
        </div>
    );
}

editコンポーネントにBlockControlsを追加すると、
浮上したツールバーに追加出来ます。
これにはスロットという仕組みが使用されていますが、次回取り上げます。

デフォルトのツールバーボタン

デフォルトで用意してあるツールバーボタンがある。

export default (props: BlockEditProps<KurageExampleBlockProps>) =>
{
    const [vertical, setVertical] = useState<BlockVerticalAlignmentToolbar.Value>('center');
    const [align, setAlign] = useState<string|undefined>();

    return (
        <div {...useBlockProps()}>

            <p>ツールバー</p>

            <BlockControls>

                <AlignmentToolbar value={align} onChange={value => setAlign(value)} />

                <BlockVerticalAlignmentToolbar value={vertical} onChange={value => setVertical(value)} />

            </BlockControls>
        </div>
    );
}

サイドバー

サイドバーに追加するにはInspectorControlsを使います。

import React from 'react';
import KurageExampleBlockProps from './props';
import './editor.scss';
import { AlignmentToolbar, BlockControls, BlockVerticalAlignmentToolbar, InspectorControls, useBlockProps } from '@wordpress/block-editor';
import { BlockEditProps } from '@wordpress/blocks';
import { TextControl, ColorPalette } from '@wordpress/components';
import { useState } from '@wordpress/element';

export default (props: BlockEditProps<KurageExampleBlockProps>) =>
{
    const [vertical, setVertical] = useState<BlockVerticalAlignmentToolbar.Value>('center');
    const [align, setAlign] = useState<string|undefined>();

    const [text, setText] = useState('xxx');
    const [color, setColor] = useState<any>();

    return (
        <div {...useBlockProps()}>

            <p>ツールバー</p>

            <BlockControls>

                <AlignmentToolbar value={align} onChange={value => setAlign(value)} />

                <BlockVerticalAlignmentToolbar value={vertical} onChange={value => setVertical(value)} />

            </BlockControls>

            <InspectorControls>

                    <p>{ text }</p>

                    <TextControl value={text} onChange={value => setText(value)} />

                    <ColorPalette
                        value={color}
                        onChange={value => setColor(value || 'red')}
                        colors={[ { name: '赤', color: '#f00'}, { name: '青', color: '#00f'} ]}
                        />

            </InspectorControls>
        </div>
    );
}

サイドバーにテキストコントロールとカラーパレットが表示されているのが確認できます。

ここにもスロットの仕組みが使用されてます。
次回、スロットについてです。

WordPressのブロック開発メモ その6 スロット

BlockEditor certificate css DataGrid Docker Gutenberg Hyper-V iframe MUI openssl PHP React ReduxToolkit REST ubuntu WordPress オレオレ認証局 フレームワーク