この記事は Snow Monkey / unitone Advent Calendar 2024 4日目の記事です。まだまだ空きがたくさんあるので、ぜひお気軽にご参加ください!
ColorGradientSettingsDropdown
ブロックに色の設定を追加したいときってありますよね。色の設定を追加するときは ColorGradientSettingsDropdown
コンポーネントを使うのが簡単です。
こんな感じで使用できます。
block.json
{
...省略...
attributes: {
"iconColor": {
"type": "string"
}
},
...省略...
}
Edit コンポーネント
import {
InspectorControls,
useBlockProps,
useInnerBlocksProps,
__experimentalColorGradientSettingsDropdown as ColorGradientSettingsDropdown,
__experimentalUseMultipleOriginColorsAndGradients as useMultipleOriginColorsAndGradients,
} from '@wordpress/block-editor';
import { __ } from '@wordpress/i18n';
function Edit( { attributes, setAttributes, clientId } ) {
const { iconColor } = attributes;
const blockProps = useBlockProps();
const innerBlocksProps = useInnerBlocksProps( blockProps );
return (
<>
<InspectorControls group="color">
<ColorGradientSettingsDropdown
__experimentalIsRenderedInSidebar
settings={ [
{
label: __( 'Icon Color' ),
colorValue: iconColor,
onColorChange: ( newValue ) => {
setAttributes( {
iconColor: newValue,
} );
},
},
] }
panelId={ clientId }
{ ...useMultipleOriginColorsAndGradients() }
gradients={ [] }
disableCustomGradients
/>
</InspectorControls>
<div { ...innerBlocksProps } />
</>
);
}
export default Edit;
ColorGradientSettingsDropdown
は、クリックするとカラーパレットが表示され、色を選ぶと attributes.iconColor
にその色が保存されます。
この初期バージョンの問題点
ここで、例えば theme.json
で下記のようなカラーパレットが定義されていたとします。
{
"$schema": "https://schemas.wp.org/trunk/theme.json",
"version": 3,
"settings": {
"color": {
"palette": [
{
"slug": "my-accent",
"color": "#f00",
"name": "My アクセントカラー"
},
]
}
}
}
そして、ColorGradientSettingsDropdown
で「My アクセントカラー」を選択したとします。すると、attributes.iconColor
には #f00
が保存されます。まーこれでも良いっちゃ良いのですが、例えば後で「My アクセントカラー」の色を #000
から変更したいと思い、theme.json
を変更し、#00f
にしたとします。そしたら、既にブロックに設定済みの「My アクセントカラー」も自動的に #00f
になって欲しいですよね?
でも、残念ながらそうはなりません…(TT)
なぜならば、attributes.iconColor
にはそのまま #f00
というカラーコードが保存されてしまっているからです。
例えば保存されるのがカラーコードではなく、my-accent
のような色のスラッグであれば、カラーコードが直接保存されているわけではないので、裏で WordPress がよしなにやってくれます。実際、コアの文字色や背景色の設定ではそのようなスラッグが保存されるようになっています。
じゃあカラーコードではなくてスラッグで保存してみようとなるわけですが、そのためには onColorChange
のときに渡ってきた値(カラーコード)を、カラーパレットの各色と比較して、カラーパレットに定義されている色なのか、それとも独自に入力されたカラーコードなのかを判別し、もしカラーパレットに定義されている色なのであればスラッグを取得する、という処理が必要になります。……めんどい……。
withColors を使ってみる
そういう色々な面倒をよしなに処理してくれるのが withColors
という高階コンポーネントです。
block.json の変更
withColors
を使う場合、attributes
の調整が必要になります。色の attribute
の名前が iconColor
だとしたら、前に custom
を付けた customIconColor
を追加します。
{
...省略...
attributes: {
"iconColor": {
"type": "string"
},
"customIconColor": {
"type": "string"
}
},
...省略...
}
Edit コンポーネントの変更
withColors
は高階コンポーネントなので Edit
コンポーネントをラップする形で使用します。ラップすると、Edit
の props
に attributes.iconColor
の代わりに使用する props.iconColor
と、setAttributes
の変わりに使用する props.setIconColor
が追加されます。
props.iconColor
はオブジェクトで、下記のようなデータが格納されます。
// カラーパレットの色を選択した場合
{
class: "has-my-accent-color",
color: "#00f",
name: "My アクセントカラー",
slug: "unitone-dark-red"
}
// カラーコードを入力した場合
{
class: undefined,
color: "#881616"
}
では、先程のコードを withColors
を使った形に変更してみます。
import {
InspectorControls,
useBlockProps,
useInnerBlocksProps,
withColors,
__experimentalColorGradientSettingsDropdown as ColorGradientSettingsDropdown,
__experimentalUseMultipleOriginColorsAndGradients as useMultipleOriginColorsAndGradients,
} from '@wordpress/block-editor';
import { __ } from '@wordpress/i18n';
function Edit( { clientId, iconColor, setIconColor } ) {
const blockProps = useBlockProps();
const innerBlocksProps = useInnerBlocksProps( blockProps );
return (
<>
<InspectorControls group="color">
<ColorGradientSettingsDropdown
__experimentalIsRenderedInSidebar
settings={ [
{
label: __( 'Icon Color' ),
colorValue: iconColor.color,
onColorChange: setIconColor,
},
] }
panelId={ clientId }
{ ...useMultipleOriginColorsAndGradients() }
gradients={ [] }
disableCustomGradients
/>
</InspectorControls>
<div { ...innerBlocksProps } />
</>
);
}
// キーに attribute の名前、値にコンテキストなオブジェクトを引数として渡す。
// コンテキストは文字色として使うなら color、背景色として使うなら background-color を指定する。
export default withColors( {
iconColor: 'color',
} )( Edit ); // Edit コンポーネントをラップ
これでカラーピッカーで規定の色を選択した場合は attributes.iconColor
に色のスラッグ(ここでは my-accent
)が、規定の色から選択せずにカラーコードを入力した場合は attributes.customIconColor
にカラーコードが保存されるようになります。
後は props.iconColor.class
があるときはそれを className
に追加すれば自動的に文字色として反映されるようになりますし、あるいは props.iconColor.slug
を使って var(--wp--preset--color--${ props.iconColor.slug } )
を style
に追加しても良いですし、好きな形で反映させれば OK です。
コメントを残す