`<wa-copy-button>`にカスタムトリガーのスロット対応を追加
<wa-copy-button>のデフォルトスロットに任意のボタン要素を差し込めるようになりました。これにより、アイコンボタン固定だった制約を破り、<wa-button>や<button>など任意のインタラクティブ要素をコピー操作のトリガーとして使えます。
背景
従来の<wa-copy-button>はアイコンのみのボタンを内部に持つ固定UIで、サイズや見た目を他のボタンと統一する手段がありませんでした。#1327では「<wa-copy-button>を他の<wa-button>と並べると縦位置やサイズが合わない」というフィードバックが報告され、その解決策として2つのアプローチが検討されました。
1つ目はsizeやappearanceなどのボタン属性を<wa-copy-button>自身に追加して機能を増やし続ける方法です。2つ目はデフォルトスロットを用意してユーザーが任意のボタンを差し込める構造に変える方法です。実装コストと柔軟性のトレードオフを考慮した結果、後者が採用されました。スロット方式であれば<wa-button>のすべての属性を再実装することなく、既存の<wa-button>の機能がそのまま使えます。
技術的な変更
copy-button.tsにHasSlotControllerが導入され、デフォルトスロットに要素が挿入されているかどうかを検知できるようになりました。これにより、スロットが空のときは従来のアイコンボタンを、スロットに要素があるときはそちらをトリガーとして扱う分岐が実現しています。
具体的には以下のインポートとコントローラーの追加が行われました。
import { HasSlotController } from '../../internal/slot.js';
import { watch } from '../../internal/watch.js';
import hostStyles from '../../styles/component/host.styles.js';
// クラス内
private readonly hasSlotController = new HasSlotController(this, '[default]');
さらに、@watch('status')デコレータを使ったハンドラーが追加され、コピー操作の結果をCSSカスタムステート(:state(success) / :state(error))として反映するようになりました。
@watch('status')
handleStatusChange() {
this.customStates.set('success', this.status === 'success');
this.customStates.set('error', this.status === 'error');
}
スタイル面では、copy-button.styles.tsに.copy-button__triggerクラスが追加されています。display: inline-flexを指定することで、スロットされた要素のインラインレイアウトが適切に機能します。また、static cssにhostStylesが追加され、ホスト要素のスタイル基盤が整備されました。
カスタムトリガーを使う場合の記述例は以下の通りです。
<wa-copy-button value="You can copy anything with a custom trigger!">
<wa-button appearance="filled">Copy to Clipboard</wa-button>
</wa-copy-button>
<wa-copy-button value="Native buttons work too!">
<button type="button" class="wa-filled">Copy to Clipboard</button>
</wa-copy-button>
設計判断
後方互換性の維持を最優先にした設計が選ばれています。デフォルトスロットが空の場合は従来のアイコンボタン動作をそのまま維持し、既存の<wa-copy-button>ユーザーへの影響はありません。PR本文にも「existing copy buttons will continue to work just fine」と明記されています。
カスタムトリガーを使う場合はデフォルトのツールチップとアイコンフィードバックが表示されなくなりますが、代わりにwa-copy・wa-errorイベントやCSSカスタムステートでフィードバックを実装できます。また、copy-icon・success-icon・error-iconの既存スロットを維持するためにHasSlotControllerを導入したことがPR本文で明示されており、単純なフォールバックスロットではなくコントローラーを使った設計になった理由がここにあります。
まとめ
この変更は、<wa-copy-button>のUI固定という制約をデフォルトスロットの追加だけで解消したもので、既存APIへの変更を最小限に抑えながら柔軟性を大きく向上させています。CSSカスタムステートの採用により、カスタムトリガー使用時のフィードバック実装もWeb標準の手法で対応できるようになりました。