logo

Palette - Make it Colorful🎨

Palette - Visual Page Builder, no design degree required.

Live Demo Download Palette

Scroll

新しいPaletteコンポーネントの作成

Single Directory Component(SDC)をPaletteに追加するための実践ガイド。各コンポーネントに必ず含めるべきものと、Style(バリアント)設定の仕組みを解説します。アーキテクチャの概要についてはCLAUDE.mdを、styles.mdを、別のモジュール/テーマからコンポーネントを拡張する方法については参照してください。


1. コンポーネントの構造

各コンポーネントは、components/以下の独自フォルダに配置されます:

components/<id>/
  <id>.component.yml     # required — metadata + prop/slot schema
  <id>.twig              # required — the markup
  <id>.css               # optional — co-located styles
  <id>.js                # optional — co-located behaviour
  • <id>はマシン名(小文字、アンダースコア)です。Paletteはコンポーネントをcanvas_palette:<id>として公開します。
  • コアのSDCは、フォルダを自動検出しライブラリを自動生成します core/components.canvas_palette--<id>。同じ場所に配置した.css/.jsから生成されます。ライブラリを自分で登録する必要はありません

1a. <id>.component.yml — 必須キー

$schema: https://git.drupalcode.org/project/drupal/-/raw/HEAD/core/assets/schemas/v1/metadata.schema.json

name: My Thing              # human label shown in the editor
group: Palette               # category in the component list — always "Palette"
status: experimental         # experimental | stable | deprecated
description: 'One line describing what it does.'

props:
  type: object
  properties:
    # … see below …

slots:
  # … optional, see 1c …

1b. プロパティ(props)

各propはJSONスキーマのプロパティです。このキットでよく使う形は次のとおりです:

props:
  type: object
  properties:
    title:
      type: string
      title: Title
      examples: ['Default title']        # the editor placeholder / seed value

    text:
      type: string
      title: Text
      contentMediaType: text/html         # rich text …
      x-formatting-context: block         # … edited with the block CKEditor
      examples: ['<p>Some copy.</p>']

    count:
      type: integer
      title: Count
      default: 3

    image:
      $ref: json-schema-definitions://canvas.module/image
      type: object
      title: Image

重要なルール(すべてPaletteによって強制されます。間違えるとコンポーネントは黙って自身を無効化し、エディタから消えます):

  • required:プロパティには必ずexamples値が必要です。デフォルトが不要な場合は、空のexampleを与えるのではなく、propをオプションにします(required:から外す)。
  • examples[0]は、新しく配置したインスタンスに初期値として設定される値です。エディタのデフォルト/プレースホルダーとして扱ってください。
  • default:は、propが未設定のときにTwigが参照するランタイムのフォールバックです。
  • Enum propは、人間向けラベルとしてmeta:enumマップを列挙します(§2参照)。
  • オプションのintegerpropは、エディタでクリアするとエラーになります。クリア可能にするのではなく、default: 0を用いて、Twig側で「未設定」として扱うのが望ましいです。

1c. スロット(コンテナコンポーネント)

コンテナコンポーネント(Carousel、Tiles、Stats…)は、子コンポーネントを静的なslotsに保持し、通常は専用の*_itemコンポーネントとペアにします:

slots:
  items:
    title: Items
    description: 'Place one My Item per row.'
    expected: ['canvas_palette:my_item']
    minItems: 1

スロットはTwigで{% block <slot> %}{% endblock %}を使ってレンダリングされます。Paletteはランタイムで動的なスロットを禁止しているため、スロット数は定義時に固定されます。

1d. <id>.twig

通常のSDCのTwigです。propとスロットはトップレベルの変数/ブロックになります:

<div class="cp-my-thing cp-my-thing--{{ style|default('default') }}">
  {% if title %}<h2 class="cp-my-thing__title">{{ title }}</h2>{% endif %}
  {% if text %}<div class="cp-my-thing__body">{{ text }}</div>{% endif %}
  {% block items %}{% endblock %}
</div>

規約: BEMクラス名cp-<id>cp-<id>__elementcp-<id>--modifier

1e. Drupal.behaviorsonce/サードパーティライブラリを使うJS

自動生成されるコンポーネントライブラリにcore/drupalが注入されるのは、コンポーネントがlibraryOverridesを宣言している場合のみです。そのため、.jsDrupal.behaviorsonce()、または共有ライブラリを使うコンポーネントは、依存関係を宣言する必要があります:

libraryOverrides:
  dependencies:
    - core/drupal
    - core/once
    - canvas_palette/glightbox   # third-party libs are attached the same way

これがないと、Drupal/onceは実行時にundefinedになります。(tabsaccordioncarouselの実例を参照してください。)

1f. エディタ専用のUI要素

Paletteエディタのプレビュー内だけで何かを表示する(グラブ用パディング、空の輪郭など)には、Paletteがtwigコンテキストに注入するcanvas_is_previewフラグで制御し、cp-<id>--previewモディファイアを出力します。これは公開ページには決して届きません:

{% set classes = ['cp-my-thing', canvas_is_preview ? 'cp-my-thing--preview' : ''] %}

JS側の同等の方法はwindow.frameElement?.dataset?.canvasPreview === 'true'です。


2. Style設定の仕組み

「Style」設定は、コンポーネントのバリアントに対するPalette唯一の規約です。スタイルごとのTwigやJSの分岐はありません — 1つのenum propをCSSクラスに変換するだけです。

2a. styleprop

ほとんどのコンポーネントは、styleという名前の単一のenum文字列propを宣言します(ラベルは「Style」、ときに「Layout」/「Columns」):

    style:
      type: string
      title: Style
      default: default
      enum:
        - default
        - colorful
      meta:enum:
        default: Default
        colorful: Colorful
      examples: [default]
  • enum — マシン値。
  • meta:enum — セレクトに表示される人間向けラベル。
  • defaultexamples — 開始値。

2b. TwigがBEMモディファイアに補間する

Twigはその値をそのままモディファイアクラスとしてルート要素に書き込みます:

<div class="cp-my-thing cp-my-thing--{{ style|default('default') }}">

つまり、style: colorfulclass="cp-my-thing cp-my-thing--colorful"をレンダリングします。

2c. CSSはモディファイアをキーにする

各スタイルは、.cp-<id>--<value>をキーにした単なるCSSルールセットです:

.cp-my-thing--colorful {
  background: linear-gradient(135deg, #0973f2, #7333e5);
  color: #fff;
}

これがすべての仕組みです: enum値 → cp-<id>--<value>クラス → CSS。

2d. エディタフォームの先頭に浮上する

canvas_palette_move_style_prop_first()は、styleという名前のpropに非常に低い#weightを与えるので、Styleセレクタは常にコンポーネント入力サイドバーの先頭に表示されます。これはcanvas_palette_form_component_instance_form_alter()から、すべてのsdc.canvas_palette.*コンポーネントに対して実行されます。propにstyleと名付けるだけで自動的に適用されます。(propを再重み付けするカスタム入力フォームハンドラを持つコンポーネントも、styleを先頭に残す必要があります。)

2e. 既存コンポーネントに新しいStyle値を追加する

enum値の追加は、追加的で安全な変更です:

  1. 値をenum:に、ラベルをmeta:enum:に追加します。
  2. .cp-<id>--<value>のCSSを追加します。
  3. リビルドします(§3参照)。新しい値は、新しく配置したインスタンスと、エディタのハードリロード後に表示されます。既存のインスタンスは固定されたバージョンを保持します。

このキットで共有されるスタイル規約(正確なトークン値はCLAUDE.md参照):colorful値と、オプションのeyebrowキッカーprop。ランディングページのデザインシステムに合わせてスタイル設定されています。新しい色を考案せず、そこにあるハードコードされたトークン値を再利用してください。


3. ビルドとバージョニングの注意点

コンポーネントを追加・編集したら、サイトルートからリビルドします:

php vendor/drush/drush/drush.php cr

このOSPanelスタックでは、CLIのdrush cr届かないことがよくあります。Web経由でフラッシュしてください(管理画面のConfiguration → Development → Performance → Clear all caches、または使い捨てのweb/flush.php)。CLAUDE.mdの「Local environment quirk」を参照してください。

Canvasは各コンポーネントのスキーマを、バージョン管理された設定エンティティ(sdc.canvas_palette.<id>)として凍結します。その結果:

  • *.component.ymlを編集しても、配置済みのインスタンスはライブ更新されません。 新しいprop/enum値は、新しく配置したインスタンスと、エディタのハードリロード後に表示されます。
  • 追加的な変更は安全です(新しいenum値、新しいオプションprop)。既存propのフィールドを変更するのは安全ではありません — エラーを投げ、コンポーネント全体を無効化します。型を元に戻すと復元されます。
  • 変更後にコンポーネントが無効化された場合は、再生成して再有効化します:

    \Drupal::service('Drupal\canvas\ComponentSource\ComponentSourceManager')
      ->generateComponents();
    $c = \Drupal::entityTypeManager()->getStorage('component')
      ->loadUnchanged('sdc.canvas_palette.<id>');
    if ($c && !$c->status()) { $c->enable()->save(); }

    コンポーネントが2回目の生成でも有効なままであることを確認してください。手動での再有効化1回しか持たない修正は、本当の修正ではありません。


新しいコンポーネントのチェックリスト

components/<id>/<id>.component.yml$schemanamegroup: Palettestatusdescriptionを含む)。

propを定義。すべてのrequiredpropにexamplesがある。

<id>.twigcp-<id>のBEMクラスを含む)。

styleenum prop(+meta:enum)をバリアントがある場合に用意し、cp-<id>--{{ style }}と対応するCSSに接続する。

libraryOverrides.dependencies(JSがDrupal.behaviorsonce/サードパーティライブラリを使う場合)。

スロット+ペアの*_itemコンポーネント(コンテナの場合)。

(Web経由で)リビルド済み。コンポーネントが2回の生成にわたってENABLEDと表示される。