DigiPress

Highly Flexible WordPress Theme

メニュー

[WP]BorderBoxControl でボーダー周りの設定を実装する

[WP]BorderBoxControl でボーダー周りの設定を実装する

WordPress のブロックエディターにカスタムブロックを追加し、そのブロックでボーダー周り(枠線の太さ、色、線の種類)のカスタマイズを実装したい場合、WordPress 6.0 より実装された BorderBoxControl コンポーネントのみで一括で設定が可能になりました。
従来のように RangeControlColorPalette などそれぞれ別のコンポーネントを組み合わせる必要がなくなっただけでなく、視認性にも優れているためとても便利になっています。

このコンポーネントは、現時点では実験段階での実装として位置づけられているため、今後仕様が大きく変わる可能性があります。

BorderBoxControl

BorderBoxControl コンポーネントを利用するには、まず @wordpress/components からインポートします。

import { __experimentalBorderBoxControl as BorderBoxControl } from '@wordpress/components'

基本的な BorderBoxControl コンポーネントの使い方はこのような形です。

import { __experimentalBorderBoxControl as BorderBoxControl } from '@wordpress/components'

const edit = props => {
	const {
		setAttributes,
		attributes,
	} = props

	const { borderValue } = attributes

	// プリセットカラー
	const presetColors = [
		{
			color: '#3c434a',
			name: 'Gray 70'
		},
		{
			color: '#101517',
			name: 'Gray 100'
		},
		{
			color: '#72aee6',
			name: 'Blue 20'
		},
		{
			color: '#3582c4',
			name: 'Blue 40'
		},
		{
			color: '#0a4b78',
			name: 'Blue 70'
		},
	]

	// デフォルトの枠線
	const defaultBorder = {
		color: '#72aee6',
		style: 'dashed',
		width: '1px'
	}

	return (
		<InspectorControls>
			<BorderBoxControl
				colors={ presetColors }	// プリセットカラー
				defaultBorder={ defaultBorder }	// デフォルトの枠線
				disableCustomColors	// 枠線の色のユーザーカスタマイズを無効(プリセットのみにする)
				enableAlpha	// 枠線のカラーの不透明度の変更を有効
				enableStyle	// 枠線のスタイル(solid, dotted, dashed)のカスタマイズを有効
				popoverPlacement="right-start"	// ポップアップ(色、枠線のスタイル)の表示位置
				label="Borders"	// 先頭に表示するラベル
				onChange={ value => setAttributes( { borderValue: value } ) }	// 保存処理
				value={ borderValue }
			/>
		</InspectorControls>
		...
}

ブロックのエディター側(edit.js)で利用する前提にて、 onChange には setAttributes で保存を行い、格納する変数(attributes 内)が borderValue であった場合のサンプルです。

表示例
一括指定モードのとき
個別指定モードのとき

BorderBoxControl コンポーネントを試すにはこちら

プリセットカラーについて

ここで問題になるのが、BorderBoxControlcolors プロパティにプリセットのカラーパターンを渡しておかないと、枠線のカラーを変更する際、プリセットが何もなく、毎回ユーザーがカラーパレットで1から配色を決めないといけなくなります。

しかし、プリセットのカラーパターンをブロック(プラグイン)内で独自に用意してしまうと、WordPress 側で用意されているデフォルトのカラーパターン、または利用しているブロックテーマの theme.json で定義されているカラーパターンとは異なるため、カラーパレットなど他の配色用のコンポーネントとの統一性がなくなり、かえってユーザビリティを低下させてしまいます。

そこで、colors プロパティには、テーマ(theme.json)側でカラーパターンが用意されている場合はそれを利用し、ない場合は WordPress のデフォルトのカラーパターンを渡すようにします。

プリセットカラーの値
import { useSetting } from '@wordpress/block-editor'

const edit = props => {
	...

	// テーマのカラーパターン
	const themeColors = useSetting( 'color.palette.theme' )

	// WordPress のデフォルトカラーパターン
	const defaultColors = useSetting( 'color.palette.default' )

	...

	return (
		<InspectorControls>
			<BorderBoxControl
				colors={ themeColors || defaultColors }	// テーマのカラーパターンがなければデフォルトのカラーパターンを渡す
				...
			/>
		</InspectorControls>

		<div { ...blockProps }>
			...
		</div>
	)
}

useSetting( 'color.palette.theme' ) でテーマでプリセットされているカラーパターンを取得し、useSetting( 'color.palette.default' ) とすると WordPress のデフォルトのカラーパターンが取得できます。

戻り値のパース

BorderBoxControl からの戻り値( サンプルのborderValue に入る値)は Object型 で返されますが、ボーダーを一括で指定した場合と個別に指定した場合では構造(ネスト状態)が異なるため、実際の style 属性のスタイルとして適用するためには、少々面倒な変換処理をする必要があります。

一括指定した場合の戻り値

一括指定した場合は、ボーダーのカラー、スタイル、太さの3つのデータが入ったオブジェクトが返されます。

{
  color: "#2fc4cf",
  style: "solid",
  width: "1px"
}
個別指定した場合の戻り値

個別指定した場合は、4辺(上下左右)ごとに分けられたボーダーのカラー、スタイル、太さのデータが返されます。

{
  bottom: {
    color: "#2fc4cf",
    style: "solid",
    width: "1px"
  },
  left: {
    color: "#2fc4cf",
    style: "dotted",
    width: "3px"
  },
  right: {
    color: "#2fc4cf",
    style: "dashed",
    width: "2px"
  },
  top: {
    color: "#2fc4cf",
    style: "double",
    width: "4px"
  }
}

React コンポーネントで style を渡すには、オブジェクトがネストした上記のままでは渡せないため、1つ(1階層)のオブジェクトにマージする必要があります。

さらに、HTML の style 属性に合うように、一括指定の場合は border-{prop}、個別指定の場合は border-{position}-{prop} というキー名に変更する必要があります。

これを実現するために、以下の関数を用意して解析し、そのまま渡せばいい状態に変換します。

style 用にパースする関数
const parseBorderStyle = borders => {
	if ( typeof borders === 'object' ) {
		const style = Object.keys( borders ).map( ( key ) => {
			if ( typeof borders[ key ] === 'object' ) {
				// 個別指定の場合はさらにループ
				return Object.assign( {}, ...Object.keys( borders[ key ] ).map( ( key2 ) => {
					return { [`border-${ key }-${ key2 }`]: `${ borders[ key ][ key2 ] }` }
				} ) )
			} else {
				// 一括指定の場合は Object 型にして返す
				return { [`border-${ key }`]: `${ borders[ key ] }` }
			}
		} )

		return Object.assign( {}, ...style )
	}
}

BorderBoxControl から受け取ったボーダーのデータをこの関数でパースすることで、以下のように変換されます。

変換後の Object一括指定の場合
{
    "border-color": "#2fc4cf",
    "border-style": "dashed",
    "border-width": "1px"
}
変換後の Object個別指定の場合
{
    "border-top-color": "#9fe5e5",
    "border-top-style": "solid",
    "border-top-width": "4px",
    "border-right-color": "#2fc4cf",
    "border-right-style": "solid",
    "border-right-width": "4px",
    "border-bottom-color": "#2fc4cf",
    "border-bottom-style": "solid",
    "border-bottom-width": "4px",
    "border-left-color": "#2fc4cf",
    "border-left-style": "solid",
    "border-left-width": "4px"
}

あとは parseBorderStyle 関数で変換した値(Object)を style にそのまま渡せばOKです。

import { useBlockProps } from '@wordpress/block-editor'
...
const edit = props => {
  ...
  const parseBorderStyle = borders => {
    ...
  }

  const blockProps = useBlockProps( {
    style: parseBorderStyle( borderValues ),
  } )

  return (
    <InspectorControls>
      ...
    </InspectorControls>

    <div { ...blockProps }>
      ...
    </div>
  )
}
公式ドキュメント

その他、ブロックや特定の要素の余白(パディング、マージン)の設定に便利な BoxControl コンポーネント、角丸の度合いの設定に利用できる BorderRadiusControl コンポーネントなどがありますが、これらはまた次回試してみたいと思います。

Share / Subscribe
Facebook Likes
Tweets
Hatena Bookmarks
Pinterest
Pocket
Feedly
Send to LINE