1. ホーム
  2. WordPress

【WordPress】PanelColorSettings と ColorPalette の使い方|カスタムブロックに色設定を追加する方法

Share

カスタムブロックを作っていると、「見出しの色をユーザーが選べるようにしたい」「ボックスの背景色を設定サイドバーから変えたい」という要望が出てきます。ブロックエディターには色を選ぶための専用コンポーネントが用意されていて、ColorPalettePanelColorSettings を使えば、コアブロックと同じ見た目の色設定 UI を自分のブロックにも追加できます。この記事では、単体で使う ColorPalette の基本から、設定サイドバーに複数の色をまとめる PanelColorSettings、選んだ色をフロントエンドに反映させる保存方法までを順に解説します。

カスタムブロックに色を付ける2つの道

ブロックに色設定を持たせる方法は、大きく分けて2つあります。ひとつは block.jsonsupports"color" を書いて、WordPress が用意している色 UI をまるごと借りる方法です。もうひとつが、この記事で扱う ColorPalettePanelColorSettings を使って、自分で色のコントロールを組み立てる方法です。

方法向いているケース
supportscolor「文字色」「背景色」という一般的な用途。クラス名やスタイルの出力も WordPress が自動で行う
PanelColorSettings「見出しの色」「枠線の色」「アイコンの色」など、ブロック独自の意味を持つ色を複数持たせたいとき

文字色と背景色を1組だけ設定できれば十分なら supports を使うほうが圧倒的に簡単です。一方で「タイトルの色」と「本文の色」と「枠線の色」を別々に持たせたい、といったブロック固有の色supports では表現できません。そこで自前のコントロールを置くことになります。

ColorPalette の基本の使い方

ColorPalette@wordpress/components が提供する、色見本の一覧と「カスタムカラー」ボタンだけを描画するコンポーネントです。ラベルもパネルの枠も付かない、いちばん小さな部品だと考えてください。

最低限必要なのは、選択肢となる色の配列 colors、現在選ばれている値 value、選択時に呼ばれる onChange の3つです。

src/edit.js(抜粋)
import { ColorPalette } from '@wordpress/components';

// 選択肢として並べる色。name はホバー時に表示される名前
const MY_COLORS = [
    { name: '赤', color: '#e2401c' },
    { name: '青', color: '#0693e3' },
    { name: '黒', color: '#111111' },
];

<ColorPalette
    colors={ MY_COLORS }
    value={ attributes.boxTextColor }
    onChange={ ( value ) => setAttributes( { boxTextColor: value } ) }
/>

onChange に渡ってくるのは #e2401c のような色の文字列です。colors の配列そのものではなく、選ばれた色の値だけが来ると覚えておくとつまずきません。また、色見本の右上にある「クリア」を押したときは undefined が渡されます。属性に undefined が入ると保存時にその属性ごと消えるので、あとで説明する save 側では「色が指定されていない場合」を必ず考慮しておきます。

よく使うプロパティ

プロパティ説明
colors色見本の配列。{ name, color } の形で指定する
value現在選択されている色。属性の値を渡す
onChange色が選ばれたときに呼ばれる関数。引数は色の文字列(クリア時は undefined
disableCustomColorstrue にするとカラーピッカーを隠し、用意した色見本だけに限定する
clearablefalse にすると「クリア」ボタンを消す
enableAlphatrue にすると透明度(アルファ値)のスライダーが使える

ブランドカラー以外を使わせたくない、というケースでは disableCustomColors が役に立ちます。逆に半透明のオーバーレイを作らせたいときは enableAlpha を有効にすると、値が rgba(...) の形式で返ってきます。

PanelColorSettings で設定サイドバーにまとめる

実際のブロック開発でよく使うのは、@wordpress/block-editorPanelColorSettings のほうです。こちらは折りたたみ可能なパネルと、色ごとのラベル付き行をまとめて描画してくれるコンポーネントで、コアブロックの「色」パネルとまったく同じ見た目になります。

まずは属性を block.json に定義します。ここでは文字色と背景色を持つ簡単なボックスブロックを作ります。

src/block.json
{
  "$schema": "https://schemas.wp.org/trunk/block.json",
  "apiVersion": 3,
  "name": "my-blocks/color-box",
  "title": "カラーボックス",
  "category": "design",
  "icon": "art",
  "textdomain": "my-blocks",
  "attributes": {
    "content": {
      "type": "string",
      "source": "html",
      "selector": "p",
      "default": ""
    },
    "boxTextColor": {
      "type": "string"
    },
    "boxBackgroundColor": {
      "type": "string"
    }
  },
  "editorScript": "file:./index.js",
  "style": "file:./style-index.css"
}

属性名を textColorbackgroundColor ではなく boxTextColor / boxBackgroundColor にしているのには理由があります。supportscolor を有効にすると、WordPress 側が textColorbackgroundColor という名前の属性を自動的に追加します。同じ名前を自分でも使うと、あとから supports を足したときに値の取り合いになり、原因の分かりにくい不具合につながります。自前の色属性には、ブロック独自の接頭辞を付けておくと安全です。

edit.js に色パネルを置く

PanelColorSettingsInspectorControls の中に置きます。色の設定は colorSettings という配列にまとめ、1色につき { value, onChange, label } の3点セットを渡します。

src/edit.js
import { __ } from '@wordpress/i18n';
import {
    useBlockProps,
    InspectorControls,
    PanelColorSettings,
    RichText,
} from '@wordpress/block-editor';

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

    // エディター側のプレビューにも色をそのまま反映させる
    const blockProps = useBlockProps( {
        style: {
            color: boxTextColor,
            backgroundColor: boxBackgroundColor,
        },
    } );

    return (
        <>
            <InspectorControls>
                <PanelColorSettings
                    title={ __( '色設定', 'my-blocks' ) }
                    initialOpen={ true }
                    colorSettings={ [
                        {
                            value: boxTextColor,
                            onChange: ( value ) =>
                                setAttributes( { boxTextColor: value } ),
                            label: __( '文字色', 'my-blocks' ),
                        },
                        {
                            value: boxBackgroundColor,
                            onChange: ( value ) =>
                                setAttributes( { boxBackgroundColor: value } ),
                            label: __( '背景色', 'my-blocks' ),
                        },
                    ] }
                />
            </InspectorControls>

            <div { ...blockProps }>
                <RichText
                    tagName="p"
                    value={ content }
                    onChange={ ( value ) => setAttributes( { content: value } ) }
                    placeholder={ __( 'テキストを入力', 'my-blocks' ) }
                />
            </div>
        </>
    );
}

ポイントは colorSettings に渡す配列の中身です。value には現在の属性値、onChange にはその属性を更新する関数、label にはパネル内に表示される名前を書きます。この3点セットを増やせば、色の行がそのまま増えます。枠線の色を足したければ4つ目の要素を追加するだけです。

colors プロパティを渡していない点にも注目してください。PanelColorSettings は色見本を省略すると、テーマや WordPress 本体が定義しているカラーパレットを自動で読み込みますtheme.json でパレットを定義しているテーマなら、そのテーマの色がそのまま候補として並ぶので、サイト全体で色味を揃えたい場合は指定しないほうが自然に仕上がります。

色見本を自分で用意する場合

そのブロックだけで使う専用の色を並べたいときは、colors プロパティに配列を渡します。あわせて disableCustomColorstrue にすると、指定した色以外は選べなくなります。

src/edit.js(抜粋)
<PanelColorSettings
    title={ __( '色設定', 'my-blocks' ) }
    colors={ [
        { name: 'ブランドカラー', color: '#1a73e8', slug: 'brand' },
        { name: 'アクセント', color: '#f5a623', slug: 'accent' },
    ] }
    disableCustomColors={ true }
    colorSettings={ [ /* 略 */ ] }
/>

テーマのパレットを取得して加工したい場合は、@wordpress/block-editoruseSettings フックが使えます。WordPress 6.5 で追加されたフックで、複数の設定をまとめて配列で返します。

src/edit.js(抜粋)
import { useSettings } from '@wordpress/block-editor';

// 戻り値は配列。第1要素が color.palette の値
const [ themePalette ] = useSettings( 'color.palette' );

WordPress 6.4 以前の環境も対象にする場合は、単数形の useSetting( 'color.palette' ) を使います。こちらは配列ではなく値そのものを返す点が異なります。現在は非推奨扱いなので、新しく書くコードでは useSettings を選んでください。

選んだ色をフロントエンドに出力する

エディターで色を選べても、save 側で出力しなければ公開ページには何も反映されません。自前の色属性は WordPress が面倒を見てくれないので、インラインスタイルとして自分で書き出すのがいちばん確実です。

src/save.js
import { useBlockProps, RichText } from '@wordpress/block-editor';

export default function save( { attributes } ) {
    const { content, boxTextColor, boxBackgroundColor } = attributes;

    // 未設定(undefined)のときはスタイルを出力しない
    const blockProps = useBlockProps.save( {
        style: {
            color: boxTextColor,
            backgroundColor: boxBackgroundColor,
        },
    } );

    return (
        <div { ...blockProps }>
            <RichText.Content tagName="p" value={ content } />
        </div>
    );
}

React は style オブジェクトの値が undefined のプロパティを出力しないので、色が未設定のときは style 属性そのものが空になります。「クリア」で色を外したときにスタイルが残ってしまう心配はありません。

ここで大切なのは、editsave で同じ色の出力方法を使うことです。片方だけ CSS クラスで、もう片方はインラインスタイルで、といった食い違いがあると見た目がずれます。上の例では両方とも style にまとめているので、エディターのプレビューと公開ページが一致します。

テーマの色をクラス名で保存したい場合

コアブロックは、テーマパレットから選んだ色を has-brand-color のようなクラス名で保存し、カスタムカラーのときだけインラインスタイルを使い分けています。同じ仕組みを自分のブロックで実現したい場合は、@wordpress/block-editorgetColorClassNamegetColorObjectByColorValue を組み合わせるか、withColors という高階コンポーネントを使います。

ただし、クラス名で保存するとあとからテーマのパレットを変えたときに色も追従するという利点がある反面、実装は一段階複雑になります。ブロック独自の装飾色であればインラインスタイルで十分なことが多いので、まずは上の書き方から始めて、必要になったら移行するとよいでしょう。なお、save の出力を変える改修はブロック検証エラーの原因になるため、公開済みのブロックを書き換えるときは deprecated の登録を忘れないでください。

色パネルが表示されない・色が反映されないとき

import 元のパッケージが違う

名前が似ているので混同しやすいのですが、ColorPalette@wordpress/componentsPanelColorSettings@wordpress/block-editor にあります。PanelColorSettings@wordpress/components から読み込むと undefined になり、描画しようとした時点でエディターが真っ白になります。ブラウザーのコンソールに「type is invalid」といったエラーが出ていたら、まず import 元を確認してください。

colorSettings の形が違う

colorSettingsオブジェクトの配列です。色がひとつしかないときにうっかり配列で包み忘れると、パネルの中身が何も表示されません。また、onChangesetAttributes( { boxTextColor: value } ) を直接書いてしまう(関数ではなく実行結果を渡してしまう)ミスも起きがちです。( value ) => setAttributes( ... ) のようにアロー関数で包むのが正しい書き方です。

エディターでは付くのに公開ページで色が出ない

edit.js にだけ style を書いて、save.js に反映し忘れているケースです。属性は保存されているので、エディターを開き直すと色は残っています。フロントエンドの HTML を確認して style 属性が出力されているかを見れば、どちら側の問題かすぐ分かります。

ビルド後にブロック検証エラーが出る

色の出力方法を途中で変えると、すでに投稿に保存されている HTML と新しい save の出力が食い違い、「このブロックには、想定されていないエラーが含まれています」と表示されます。開発中で記事がまだ無いなら、該当ブロックを一度削除して置き直すのが手っ取り早い解決です。公開済みの記事がある場合は deprecated に古い save を登録して移行します。

テーマの色が候補に出てこない

colors を指定していないのに WordPress 標準の色しか出ない場合は、テーマ側の theme.jsonsettings.color.palette が定義されていないか、クラシックテーマで add_theme_support( 'editor-color-palette', ... ) を書いていない可能性があります。パレットはテーマから供給されるものなので、ブロック側のコードではなくテーマの設定を確認してください。

まとめ

カスタムブロックに色設定を付けるときは、設定サイドバーに置く PanelColorSettings が基本形です。colorSettings{ value, onChange, label } の組を並べるだけで、色の数だけ行が増えます。colors を渡さなければテーマのカラーパレットが自動で使われ、渡せばそのブロック専用の色見本に差し替えられます。色見本だけを単体で置きたいときは @wordpress/componentsColorPalette を直接使います。選んだ色は save 側で useBlockProps.savestyle に渡して出力し、editsave で同じ方法を使うことを徹底すれば、エディターと公開ページの見た目がずれません。属性名は supportscolor と衝突しないよう、ブロック独自の接頭辞を付けておくと安心です。

参考ページ