`wa-tab-group` の `body` パートをスロット直接指定からラッパー `div` に変更

shoelace-style/webawesome

wa-tab-groupbody CSS パートが <slot> 要素自体ではなく、スロットを内包する <div> ラッパーに移動されました。これにより、wa-dialogwa-card と同じ構造に統一されます。

背景

wa-tab-group は従来、パネル領域を <slot part="body"> として直接スロット要素にパートを指定していました。一方、wa-dialogwa-card では body パートをスロットの外側のラッパー要素に持つ設計を採用しており、コンポーネント間で構造の不一致が生じていました。

#2198wa-card が同様のリファクタリングを受けており、<slot part="body"> から <div part="body"><slot></slot></div> へと変更されています。本 PR はその流れを wa-tab-group にも適用し、コンポーネントライブラリ全体での構造的一貫性を実現します。

::part(body) セレクターはパート名が同じため、既存のテーマやスタイルカスタマイズはそのまま動作します。パートが「スロット要素」から「コンテナ div」に変わった点のみが差異です。

技術的な変更

マークアップ・内部クエリ・スタイルセレクターの3箇所が連動して変更されています。

マークアップの変更 (tab-group.ts)

render() メソッド内のパネル領域が、スロット要素に直接パートを指定する形式からラッパー div を用いる形式へ変わりました。

変更前:

<slot part="body" class="body" @slotchange=${this.syncTabsAndPanels}></slot>

変更後:

<div part="body" class="body"><slot @slotchange=${this.syncTabsAndPanels}></slot></div>

内部クエリの変更 (tab-group.ts)

@query デコレーターのターゲットが .body(スロット要素)から .body slot(ラッパー内のスロット要素)へ変更され、プロパティ名も body から defaultSlot にリネームされました。これに伴い、getAllPanels() メソッドも this.defaultSlot.assignedElements() を参照するよう更新されています。公開 API(<wa-tab-panel> を配置するデフォルトスロット)は変わりません。

スタイルセレクターの変更 (tab-group.styles.ts)

wa-tab-panel へのパディング指定が、4方向(top・bottom・start・end)すべてで更新されています。

変更前:

.tab-group-top ::slotted(wa-tab-panel) { --padding: var(--wa-space-xl) 0; }
.tab-group-bottom ::slotted(wa-tab-panel) { --padding: var(--wa-space-xl) 0; }
.tab-group-start ::slotted(wa-tab-panel) { --padding: 0 var(--wa-space-xl); }
.tab-group-end ::slotted(wa-tab-panel) { --padding: 0 var(--wa-space-xl); }

変更後:

.tab-group-top .body slot::slotted(wa-tab-panel) { --padding: var(--wa-space-xl) 0; }
.tab-group-bottom .body slot::slotted(wa-tab-panel) { --padding: var(--wa-space-xl) 0; }
.tab-group-start .body slot::slotted(wa-tab-panel) { --padding: 0 var(--wa-space-xl); }
.tab-group-end .body slot::slotted(wa-tab-panel) { --padding: 0 var(--wa-space-xl); }

セレクターに .body slot を挟むことで、ラッパー経由の ::slotted() として正しく機能します。

設計判断

スロット要素をパート指定の対象から外す方針 が、コンポーネントライブラリ全体で統一されています。

Web Components において ::slotted() はスロットに割り当てられた直接の子要素にしか適用できません。スロット自体にレイアウト役割(displaypadding 等)を持たせると、スロット要素のデフォルト display 値(contents 相当)との干渉が起きやすく、アクセシビリティ上も意図しない影響を与える可能性があります。ラッパー div を挟む構造にすることで、コンテナとしての CSS 制御がスロット要素に依存しなくなります。

また、::part(body) のパート名を維持したまま対象要素のみを切り替えているため、テーマ作成者への影響は最小限です。スロット要素より div の方が displaybox model の制御が直感的であり、スタイルのカスタマイズ容易性も向上します。

まとめ

本 PR は wa-card での変更に続き、wa-tab-groupbody パートをコンテナ div に統一した変更です。::part(body) の名称を保ちつつ対象要素を div ラッパーへ移すことで、公開 API の互換性を維持しながら wa-dialogwa-card と同一の構造パターンを確立しています。

記事メタデータ

Generated by:
Claude Sonnet 4.6 for DiffDaily
LLM Trace:
9a1b4fc6

この記事はAIによって自動生成されています。内容の正確性については、必ずソースコードやPRを確認してください。

品質レビュー結果

Review Status:
承認済み
Review Count:
1回
Reviewed by:
Gemini 2.5 Pro for DiffDaily

Review Criteria:

記事構成 ✓ PASS

Title, Context, Technical Detailの存在と明確さ

リード文(総論)→背景・技術詳細・設計判断(各論)→まとめ(結論)という「総論→各論→結論」の構成が明確に適用されており、模範的です。

カスタムMarkdown構文 ✓ PASS

シンタックスハイライト・GitHubリンク記法の正確性

ファイル名付きのシンタックスハイライト(`言語:ファイルパス`)およびPR番号のリンク記法(`[#...](URL)`)が正しく使用されています。

対象読者への適合性 ✓ PASS

エンジニア向けの適切な技術レベルと表現

Web Componentsや関連ライブラリの知識を持つエンジニアを対象としており、専門用語の使用や説明の粒度が適切です。

パラグラフ・ライティング ✓ PASS

トピックセンテンス・1段落1トピック・段落長

各セクションが「総論→各論→結論」の構造を持ち、各パラグラフがトピックセンテンスで始まるなど、パラグラフ・ライティングの原則に準拠しており、非常に読みやすいです。

Diff内容との照合 ✓ PASS

コードブロックとDiff内容の一致

記事内で引用されているコードブロックは、提供されたDiff情報と完全に一致しており、変更内容を正確に反映しています。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

`::part`, `::slotted`, `slot`などのWeb Components関連の技術用語が正確かつ適切に使用されています。

説明の技術的正確性 ✓ PASS

技術的主張の正確性と論理性

マークアップ、内部クエリ、スタイルの変更に関する説明は技術的に正確で、Diffの内容と完全に整合しています。設計判断の背景説明も論理的です。

事実の突合 ✓ PASS

PR情報による主張の裏付け(ハルシネーション検出)

記事内の主張はすべてPRのDescriptionやDiffの内容で裏付けられており、ハルシネーション(捏造)は見られません。

数値・固有名詞の確認 ✓ PASS

PR番号・コミットID・バージョン等の正確性

PR番号(#2212, #2198)やコンポーネント名、コード内の固有名詞が正確に記載されています。

タイトル・説明との一致 ✓ PASS

記事タイトル・説明とPR内容の一致

記事のタイトルはPRのタイトル「Tab Group: Body Part Wrapper」の内容を的確に要約しており、主題の相違はありません。

外部知識の正確性 ✓ PASS

PRに記載のない外部知識(LTS、サポート状況など)の不使用

PR情報に記載のないバージョン情報やリリース日程などの外部知識は含まれておらず、事実に基づいた記述が徹底されています。

時間表現の正確性 ✓ PASS

時間表現がPR情報と一致しているか

変更内容を過去の事実として記述しており、時間表現の歪曲や誤解を招く表現はありません。