Badgeコンポーネントにstartとendスロットを追加
Web Awesome の <wa-badge> コンポーネントは、アイコンなどの装飾要素を配置するための start と end スロットを新たに提供します。これまでCSSのみで実装されていたスロット内アイコンのスタイリングを廃止し、明示的なスロット指定による確実な配置制御を可能にした変更です。
背景
従来の実装では、::slotted(wa-icon) セレクタを使用してデフォルトスロット内のアイコンに自動的にマージンを適用していました。しかしこのアプローチには2つの問題がありました。
第一に、マージン適用が一方向のみを想定していました。margin-inline-end: var(--wa-space-2xs, 0.25em) の指定は、アイコンが常にバッジコンテンツの先頭に配置されることを前提としており、末尾に配置する場合には対応できません。
第二に、CSSの :first-child と :last-child による条件付きスタイリングが機能しませんでした。<wa-tab> などの他のコンポーネントでは以下のような実装を試みていました:
::slotted(wa-icon:first-child) {
margin-inline-end: 0.5em;
}
::slotted(wa-icon:last-child) {
margin-inline-start: 0.5em;
}
しかし、デフォルトスロットにテキストノードとアイコンが混在する場合、アイコン要素は :first-child と :last-child の両方にマッチしてしまい、意図しない両側へのマージン適用が発生していました。#2072 がこの問題を指摘しています。
技術的な変更
packages/webawesome/src/components/badge/badge.ts において、レンダリングロジックが3つのスロットを持つ構成に変更されました。
変更前:
render() {
return html` <slot part="base" role="status"></slot>`;
}
変更後:
render() {
return html`
<slot name="start" part="start"></slot>
<slot part="base" role="status"></slot>
<slot name="end" part="end"></slot>
`;
}
スタイルシートでは、::slotted(wa-icon) への自動スタイリングを削除し、名前付きスロットへの明示的なマージン指定に置き換えました:
/* Slots */
slot[name='start']::slotted(*) {
margin-inline-end: 0.375em;
}
slot[name='end']::slotted(*) {
margin-inline-start: 0.375em;
}
また、バッジ要素自体に vertical-align: middle を追加し、内部コンテンツに依存しない一貫した垂直配置を実現しています。従来の実装では、スロット内アイコンのサイズ調整(height: 0.85em)によって配置を制御していましたが、この方法では他のコンテンツタイプに対応できませんでした。
使用例として、以下のようにアイコンを配置できます:
<wa-badge>
<wa-icon slot="start" name="acorn"></wa-icon>
Start
</wa-badge>
<wa-badge>
<wa-icon slot="end" name="tree-deciduous"></wa-icon>
End
</wa-badge>
<wa-badge>
<wa-icon slot="start" name="cow"></wa-icon>
<wa-icon slot="end" name="ufo-beam"></wa-icon>
Both
</wa-badge>
start と end はCSSパーツとしても公開されているため、プロジェクト固有のスタイルカスタマイズが可能です。
設計判断
明示的なスロット指定によるオプトイン方式が採用されました。
PRの説明では、CSSのみでの自動スタイリングを「needlessly opinionated and fragile(不必要に独断的で壊れやすい)」と評価しています。:first-child や :last-child の擬似クラスは、Shadow DOMのスロット投影とテキストノードの組み合わせにおいて予測可能な動作を保証できません。
名前付きスロットの導入により、開発者は装飾要素の配置を明示的に制御できるようになりました。これは、デフォルトスロットへの暗黙的なスタイル適用よりも予測可能で、他のコンテンツタイプ(テキスト、カスタム要素など)との競合を回避できます。
PR作成者は「Slots give us much more reliable control of spacing」と述べており、この判断は <wa-tab> など他のコンポーネントへの適用も検討されています。Web Componentsのスロットメカニズムを活用した、より堅牢なAPI設計への移行といえます。
本PRは、CSS擬似クラスの限界を認識し、Web Componentsの機能を適切に活用してAPIの予測可能性を高めた変更です。暗黙的なスタイリングルールを削除し、明示的なスロット指定に置き換えることで、開発者はバッジ内の装飾要素の配置を確実に制御できるようになりました。