Gutenbergのツールバーにドロップダウンを追加する

WordPress

Gutenberg(ブロックエディタ)のツールバーにボタンを追加する方法は以前紹介しました。

Gutenbergエディタ(ブロックエディタ)にボタンを追加する
WordPressのバージョンが5.0になり、エディタが新しくなりました。これまでのTinyMCEとは異なりReactを利用したモダンな実装になっており、エディタへの機能の追加方法も大きく変わりました。ここでは選択した文字列を特定のクラスを

ただ、この方法の場合はドロップダウンでまとめることはできません。

Gutenberg プラグイン v5.3 または WordPress v5.2 からはデフォルトのボタンとともにドロップダウンにまとまるようになりましたが、独自のボタンだけでまとめたいこともあるでしょう。

Gutenberg v5.3 からリッチテキストのツールバーはドロップダウンにまとまります
2019/3/30 に Gutenberg v5.3 がリリースされました。使用するブロックを管理する機能やカバーブロックの機能改善などの修正が含まれています。現在はプラグインでのみ試すことができますが、近々Wo...

ここでは独自のドロップダウンに追加する方法を紹介します。

BlockFormatControls

ボタンなどを追加できる場所はいくつか用意されています。

Gutenbergの Slot と Fill を理解する
Gutenberg(ブロックエディタ)の開発において Slot と Fill の理解は重要です。RichTextToolbarButton で追加したものがリッチテキストのツールバーに表示されるInspectorControls ...

ツールバーへ追加するには『BlockControls』または『BlockFormatControls』を使用します。

デフォルトのツールバーボタンよりも後ろに追加する場合は『BlockFormatControls』を使用します。

registerFormatType は RichText.ToolbarControls Slot を利用するための Fill を生成するようにプログラムされています。

WordPress/gutenberg
The Block Editor project for WordPress and beyond. Plugin is available from the official repository. - WordPress/gutenberg

『BlockControls』や『BlockFormatControls』はそれぞれの Slot を利用するための Fill となるので、通常のコンポーネントを利用するのと同じ様に使用できます。

ドロップダウンを追加する

ここからは実際にフォーマットの付け外しを行う複数のボタンをひとつのドロップダウンにまとめる方法を解説します。

方針

registerFormatType は 使用するフォーマットの情報 (title(フォーマット名)や tag名、class名) とそれの付け外しの手段 (edit) を登録します。

この edit で通常は RichTextToolbarButton を使用し、押されたときに toggleFormat によってフォーマットの付け外しが行われるボタンを追加します。

ただ実際は RichTextToolbarButtonRichText.ToolbarControls という Fill に ToolbarButton を登録する関数で、これ自体はボタンの実体ではありません。

WordPress/gutenberg
The Block Editor project for WordPress and beyond. Plugin is available from the official repository. - WordPress/gutenberg

その後 RichText.ToolbarControls という Slot で登録されたボタンが取り出され、DropdownMenu に渡されて表示されます。

WordPress/gutenberg
The Block Editor project for WordPress and beyond. Plugin is available from the official repository. - WordPress/gutenberg

これと同じような仕組みを用意することで簡単にドロップダウン化することが可能です。

Slot と Fill の詳細は次の記事を参考にしてください。

実装1

webpack でのビルド環境などの準備の説明は省きます。

constant.js

使用する定数を定義します。

export const PLUGIN_NAME = 'my-dropdown';

components

いくつかのコンポーネントを用意します。

components/my-dropdown-controls.js

Slot と Fill を利用するためのヘルパーです。

const { createSlotFill } = wp.components;

const { Fill, Slot } = createSlotFill( 'MyDropdownControls' );

const MyDropdownControls = Fill;
MyDropdownControls.Slot = Slot;

export default MyDropdownControls;
components/my-dropdown.js

MyDropdownControls で登録される Fill を使用して DropdownMenu を生成します。

ツールバーの Slot を利用するための BlockFormatControls でラップすることでツールバーに表示されます。

const { BlockFormatControls } = wp.editor;
const { Toolbar, DropdownMenu } = wp.components;
import MyDropdownControls from './my-dropdown-controls';

const MyDropdown = () => <BlockFormatControls>
	<div className="editor-format-toolbar block-editor-format-toolbar">
		<Toolbar>
			<MyDropdownControls.Slot>
				{ fills => <DropdownMenu
					icon='admin-customizer'
					position="bottom left"
					label='dropdown'
					controls={ fills.map( ( [ { props } ] ) => props ) }
				/> }
			</MyDropdownControls.Slot>
		</Toolbar>
	</div>
</BlockFormatControls>;

export default MyDropdown;

ここでは icon‘admin-customizer’ とハードコーディングしていますが、これがツールバーに表示されるアイコンになるので適宜変更します。

Dashicons | WordPress Developer Resources

他の設定も含めて色々変更できるようにしておくと便利かもしれません。

components/index.js

import の記述を減らしたり利用できる components を把握するためだけに用意しています。

import MyDropdown from './my-dropdown';
import MyDropdownControls from './my-dropdown-controls';

export { MyDropdown, MyDropdownControls };

utils

いくつかの便利関数を用意します。

utils/rich-text.js

リッチテキスト用の関数を用意します。

ここでは registerFormatType で渡す引数の生成ヘルパーを用意しています。

フォーマット名 (name) と component生成関数 (create)、 追加した順番 (index) を渡すとregisterFormatType に必要な引数を返します。

const { Fragment } = wp.element;

import { PLUGIN_NAME } from '../constant';
import { MyDropdown, MyDropdownControls } from '../components';

/**
 * @param {string} name name
 * @param {number} index index
 * @param {function} create create component function
 * @param {object} setting setting
 * @returns {array} setting
 */
export const getRichTextSetting = ( { name, create, setting = {} }, index ) => {
	const formatName = PLUGIN_NAME + '/' + name;
	const component = args => <MyDropdownControls>
		{ create( { args, name, formatName } ) }
	</MyDropdownControls>;

	setting.title = setting.title || name;
	setting.tagName = setting.tagName || 'span';
	setting.className = setting.className || name;
	setting.edit = args => {
		if ( ! index ) {
			return <Fragment>
				{ component( args ) }
				<MyDropdown/>
			</Fragment>;
		}
		return component( args );
	};
	return [ formatName, setting ];
};

肝となるのは以下の個所です。

if ( ! index ) {
	...
}

それぞれのフォーマットで MyDropdownControls を使用して Fill を登録しますが、どれか一つのフォーマットでドロップダウンを追加で生成します。

ここでは ! index 、つまり最初に追加したフォーマットの edit の時にそれを行っています。

これは一番最後や途中でも問題はありません。

utils/toolbar-button.js

ツールバーボタン生成用のヘルパーを用意します。

const { toggleFormat } = wp.richText;
const { ToolbarButton } = wp.components;

/**
 * @param {object} args args
 * @param {string} name name
 * @param {string} formatName format name
 * @returns {{onClick: onClick, icon: *, title: *, isActive: boolean}} toolbar button properties
 */
const getToolbarButtonProps = ( { args, name, formatName } ) => {
	return {
		icon: 'admin-customizer',
		title: <div className={ name }>
			{ name }
		</div>,
		onClick: () => {
			args.onChange( toggleFormat( args.value, {
				type: formatName,
			} ) );
		},
		isActive: args.isActive,
	};
};

/**
 * @param {object} args args
 * @param {string} name name
 * @param {string} formatName format name
 * @returns {*} toolbar button
 */
export const createToolbarButton = ( { args, name, formatName } ) => <ToolbarButton { ...getToolbarButtonProps( { args, name, formatName } ) } />;

icon‘admin-customizer’ としていますが、これがドロップダウン内で表示されるボタンのアイコンになるので適宜変更します。

utils/index.js
export { createToolbarButton } from './toolbar-button';
export { getRichTextSetting } from './rich-text';

index.js

ここまでで追加されたヘルパーを使用して実際に使用するフォーマットを登録します。

const { registerFormatType } = wp.richText;

import { createToolbarButton, getRichTextSetting } from './utils';

[
	{
		name: 'test1',
		create: createToolbarButton,
	},
	{
		name: 'test2',
		create: createToolbarButton,
	},
	{
		name: 'test3',
		create: createToolbarButton,
	},
].forEach( ( { name, create, setting = {} }, index ) => registerFormatType( ...getRichTextSetting( { name, create, setting }, index ) ) );

ここでは3つのフォーマットを作成しました。

動作確認

ビルドしたものを wp_enqueue_script で読み込ませます。

  • wp-components
  • wp-editor
  • wp-element
  • wp-rich-text

に依存していることを忘れないようにしてください。

複数の名前の Fill と Slot を用意して使用すれば複数のドロップダウンを追加することも可能です。

実装2

実装1の Fill と Slot と同じ方法でライブラリ化したのでそれを使用してみます。

@technote-space/register-grouped-format-type
gutenberg's helper to register format type

install

npm install --save @technote-space/register-grouped-format-type

require で読み込むと wp.richTextregisterFormatTypeGroupregisterGroupedFormatType が追加されます。

registerFormatTypeGroup

この関数はグループ化されたフォーマットの登録に使用します。

/**
 * @param {string} name name
 * @param {string} title title
 * @param {string} tagName tag name
 * @param {string} className class name
 * @param {function} create create component function
 * @param {string} group group
 */
registerGroupedFormatType( {
	name,
	title = name,
	tagName = 'span',
	className = name,
	create,
	group,
} )
registerGroupedFormatType

この関数はグループの設定の登録に使用します。

/**
 * @param {string} name group name
 * @param {object} setting setting
 * @returns {object} registered setting
 */
registerFormatTypeGroup( name, setting = {} )

特に設定されなかった項目はデフォルト値が使用されます。

{
	icon: 'admin-customizer',
	position: 'bottom left',
	label: name,
	menuLabel: name,
	className: undefined,
}

index.js

ライブラリによって追加された関数を実際に使用して追加してみます。

require( '@technote-space/register-grouped-format-type' );

const { ToolbarButton } = wp.components;
const { toggleFormat, registerFormatTypeGroup, registerGroupedFormatType } = wp.richText;

const getProps = ( group, name ) => {
	return {
		name,
		group,
		create: ( { args, formatName } ) => <ToolbarButton
			icon='admin-customizer'
			title={ <div className={ name }>{ name }</div> }
			onClick={ () => args.onChange( toggleFormat( args.value, { type: formatName } ) ) }
			isActive={ args.isActive }
		/>,
	};
};

registerFormatTypeGroup( 'test1', {
	icon: 'admin-network',
} );

registerGroupedFormatType( getProps( 'test1', 'dropdown2-test1' ) );
registerGroupedFormatType( getProps( 'test2', 'dropdown2-test2' ) );
registerGroupedFormatType( getProps( 'test2', 'dropdown2-test3' ) );

test1 グループはアイコンを変更して1つフォーマットを登録、test2 グループには2つのフォーマットを登録しました。

動作確認

ビルドしたものを wp_enqueue_script で読み込ませます。

このライブラリは

  • wp-components
  • wp-editor
  • wp-element
  • wp-rich-text
  • wp-hooks

に依存しています。

このライブラリで追加されたドロップダウンはデフォルトのボタンの左側に表示されます。

まとめ

公式で用意された方法がないため、まだ他にもいろいろな方法が考えられます。

実際、公開しているいくつかのプラグインでは全く違うアプローチをとっています。

今回は SlotFill を活用してツールバーボタンのドロップダウン化を実装しましたが、これももっといろいろな使い方ができそうです。

https://github.com/technote-space/gutenberg-samples

コメント

タイトルとURLをコピーしました