【WordPressブロック開発】サイドパネルを設定しよう

サイドバーに設定パネルを追加する

edit.jsを編集、InspectorControlsを追加

import {
	RichText,
	useBlockProps,
	InspectorControls,
} from "@wordpress/block-editor";

export default function Edit({ attributes, setAttributes }) {
	const { title, content } = attributes;

	return (
		<>
			<div {...blockProps()}>
				<InspectorControls>Sidebar</InspectorControls>
			</div>
			<div {...useBlockProps()}>

PanelBody を追加

import { PanelBody } from "@wordpress/components";
import "./editor.scss";

export default function Edit({ attributes, setAttributes }) {
	const { title, content } = attributes;
	return (
		<div {...useBlockProps()}>
			<InspectorControls>
				<PanelBody>Sidebar</PanelBody>
			</InspectorControls>

パネルのタイトルとして「設定」を追加

			<InspectorControls>
				<PanelBody title="設定">Sidebar</PanelBody>
			</InspectorControls>

初期状態で開く設定のため、ToggleControlを追加

import { PanelBody, ToggleControl } from "@wordpress/components";
…
			<InspectorControls>
				<PanelBody title="設定">
					<ToggleControl />
				</PanelBody>
			</InspectorControls>

トグルにラベルを設定

			<InspectorControls>
				<PanelBody title="設定">
					<ToggleControl label="初期状態で開く" />
				</PanelBody>
			</InspectorControls>

トグルを操作を有効にする

			<InspectorControls>
				<PanelBody title="設定">
					<ToggleControl label="初期状態で開く" checked={true} />
				</PanelBody>
			</InspectorControls>

attributes定義をblock.jsonに記述します。selectorがクラス名の場合は値の先頭にドットを忘れないようにします。

	"attributes": {
		"title": {
			"type": "string",
			"default": "タイトル",
			"selector": ".wp-block-create-block-dojo-block__title",
			"source": "html"
		},
		"content": {
			"type": "string",
			"default": "コンテンツ",
			"selector": ".wp-block-create-block-dojo-block__content",
			"source": "html"
		},
		"isInitialOpen": {
			"type": "boolean",
			"default": false
		}
	},

edit.js

export default function Edit({ attributes, setAttributes }) {
	const { title, content, isInitialOpen } = attributes;

	return (
		<>
			<div {...useBlockProps()}>
				<InspectorControls>
					<PanelBody title="設定">
						<ToggleControl
							label="初期状態で開く"
							checked={isInitialOpen}
							onChange={() => {
								setAttributes({ isInitialOpen: !isInitialOpen });
							}}
						/>
					</PanelBody>
				</InspectorControls>
			</div>

チェックボックス有効化

			<InspectorControls>
				<PanelBody title="設定">
					<ToggleControl
						label="初期状態で開く"
						checked={isInitialOpen}
						onChange={() => {
							setAttributes({ isInitialOpen: !isInitialOpen });
						}}
					/>
				</PanelBody>
			</InspectorControls>

フロントエンドに反映する

save.js

export default function save({ attributes }) {
	const { title, content, isInitialOpen } = attributes;
	return (
		<details {...useBlockProps.save()} open={isInitialOpen}>
			<RichText.Content
				className="wp-block-create-block-my-block__title"
				tagName="summary"
				value={title}
			/>
			<RichText.Content
				className="wp-block-create-block-my-block__content"
				tagName="p"
				value={content}
			/>
		</details>
	);
}

完成コード

block.json

{
	"supports": {
		"html": false,
		"color": {
			"background": true,
			"text": true
		}
	},
	"attributes": {
		"title": {
			"type": "string",
			"default": "タイトル",
			"selector": ".wp-block-create-block-my-block__title",
			"source": "html"
		},
		"content": {
			"type": "string",
			"default": "コンテンツ",
			"selector": ".wp-block-create-block-my-block__content",
			"source": "html"
		},
		"isInitialOpen": {
			"type": "boolean",
			"default": false
		}
	},
}

edit.js

import {
	RichText,
	useBlockProps
	InspectorControls
} from "@wordpress/block-editor";
import { PanelBody, ToggleControl } from "@wordpress/components";

export default function Edit({ attributes, setAttributes }) {
	const { title, content, isInitialOpen } = attributes;

	return (
		<>
			<InspectorControls>
				<PanelBody title="設定">
					<ToggleControl
						label="初期状態で開く"
						checked={isInitialOpen}
						onChange={() => {
							setAttributes({ isInitialOpen: !isInitialOpen });
						}}
					/>
				</PanelBody>
			</InspectorControls>

			<div {...useBlockProps()}>
				<RichText
					className="wp-block-create-block-my-block__title"
					placeholder="ここにタイトル"
					value={title}
					onChange={(value) => {
						setAttributes({ title: value });
					}}
				/>
				<RichText
					className="wp-block-create-block-dojo-block__content"
					placeholder="ここにコンテンツ"
					tagName="p"
					value={content}
					onChange={(value) => {
						setAttributes({ content: value });
					}}
				/>
			</div>
		</>
	);
}

save.js

import { RichText, useBlockProps } from "@wordpress/block-editor";

export default function save({ attributes }) {
	const { title, content, isInitialOpen } = attributes;
	return (
		<details {...useBlockProps.save()} open={isInitialOpen}>
			<RichText.Content
				className="wp-block-create-block-my-block__title"
				tagName="summary"
				value={title}
			/>
			<RichText.Content
				className="wp-block-create-block-my-block__content"
				tagName="p"
				value={content}
			/>
		</details>
	);
}

子要素にブロックを挿入する

edit.jsを編集、useInnerBlocksPropsをインポート

import {
	RichText,
	useBlockProps,
	useInnerBlocksProps,
	InspectorControls,
} from "@wordpress/block-editor";
import { PanelBody, ToggleControl } from "@wordpress/components";

export default function Edit({ attributes, setAttributes }) {
	const { title, content, isInitialOpen } = attributes;

	return (
		<>
			<InspectorControls>
				<PanelBody title="設定">
					<ToggleControl
						label="初期状態で開く"
						checked={isInitialOpen}
						onChange={() => {
							setAttributes({ isInitialOpen: !isInitialOpen });
						}}
					/>
				</PanelBody>
			</InspectorControls>

			<div {...useBlockProps()}>
				<RichText
					className="wp-block-create-block-my-block__title"
					placeholder="ここにタイトル"
					value={title}
					onChange={(value) => {
						setAttributes({ title: value });
					}}
				/>
				<div {...useInnerBlocksProps()} />
			</div>
		</>
	);
}

save.jsを編集、保存処理を書く

import {
	RichText,
	useBlockProps,
	useInnerBlocksProps,
} from "@wordpress/block-editor";

export default function save({ attributes }) {
	const { title, content, isInitialOpen } = attributes;
	return (
		<details {...useBlockProps.save()} open={isInitialOpen}>
			<RichText.Content
				className="wp-block-create-block-my-block__title"
				tagName="summary"
				value={title}
			/>
			<div {...useInnerBlocksProps.save()} />
		</details>
	);
}

リファクタリング

block.json、edit.js、save.jsから”content”を削除します。またインナーブロックにもクラスを付与します。

ファイルの記述内容

block.json

{
	"$schema": "https://schemas.wp.org/trunk/block.json",
	"apiVersion": 3,
	"name": "create-block/my-block",
	"version": "0.1.0",
	"title": "My Block",
	"category": "widgets",
	"icon": "smiley",
	"description": "Example block scaffolded with Create Block tool.",
	"example": {},
	"supports": {
		"html": false,
		"color": {
			"background": true,
			"text": true
		}
	},
	"attributes": {
		"title": {
			"type": "string",
			"default": "タイトル",
			"selector": ".wp-block-create-block-my-block__title",
			"source": "html"
		},
		"isInitialOpen": {
			"type": "boolean",
			"default": false
		}
	},
	"textdomain": "my-block",
	"editorScript": "file:./index.js",
	"style": "file:./style-index.css"
}

edit.js

import {
	RichText,
	useBlockProps,
	useInnerBlocksProps,
	InspectorControls,
} from "@wordpress/block-editor";
import { PanelBody, ToggleControl } from "@wordpress/components";

export default function Edit({ attributes, setAttributes }) {
	const { title, isInitialOpen } = attributes;

	return (
		<>
			<InspectorControls>
				<PanelBody title="設定">
					<ToggleControl
						label="初期状態で開く"
						checked={isInitialOpen}
						onChange={() => {
							setAttributes({ isInitialOpen: !isInitialOpen });
						}}
					/>
				</PanelBody>
			</InspectorControls>

			<div {...useBlockProps()}>
				<RichText
					className="wp-block-create-block-my-block__title"
					placeholder="ここにタイトル"
					value={title}
					onChange={(value) => {
						setAttributes({ title: value });
					}}
				/>
				<div
					{...useInnerBlocksProps({
						className: "wp-block-create-block-my-block__content",
					})}
				/>
			</div>
		</>
	);
}

save.js

import {
	RichText,
	useBlockProps,
	useInnerBlocksProps,
} from "@wordpress/block-editor";

export default function save({ attributes }) {
	const { title, isInitialOpen } = attributes;
	return (
		<details {...useBlockProps.save()} open={isInitialOpen}>
			<RichText.Content
				{...useBlockProps.save()}
				className="wp-block-create-block-my-block__title"
				tagName="summary"
				value={title}
			/>
			<div
				{...useInnerBlocksProps.save({
					className: "wp-block-create-block-my-block__content",
				})}
			/>
		</details>
	);
}

マークアップ

エディター側

<div class="wp-block-create-block-my-block">
  <div class="wp-block-create-block-my-block__title">
    これはタイトルです。
  </div>
  <div class="wp-block-create-block-my-block__content">
    <p>これはコンテンツです。</p>
  </div>
</div>

フロントエンド

<details class="wp-block-create-block-my-block" open="">
  <summary class="wp-block-create-block-my-block__title">
    これはタイトルです。
  </summary>
  <div class="wp-block-create-block-my-block__content">
    <p>これはコンテンツです。</p>
  </div>
</details>

アコーディオンブロックが完成しました。

参考