リンクボタンに disabled 属性のサポートを追加
Web Awesome のボタンコンポーネントにおいて、リンク(<a> 要素)として描画されるボタンが disabled 属性を正しく処理できるようになりました。これにより、ボタンタイプに関わらず一貫した無効化の挙動が実装されています。
背景
これまで <wa-button> コンポーネントでは、href 属性を指定してリンクとして機能させた場合、disabled 属性が実質的に無視されていました。#106 で報告されているように、リンクボタンは disabled 状態でもクリック可能な状態のままでした。
HTML 標準では <a> 要素に disabled 属性が存在しないため、ボタン(<button> 要素)とリンク(<a> 要素)で異なる無効化の実装が必要です。この制約により、両者で一貫した disabled の挙動を提供することが課題となっていました。
技術的な変更
inert 属性の活用により、リンクボタンの無効化を実現しています。button.ts では、<a> 要素として描画される場合に inert 属性を設定するようになりました。
変更前:
?disabled=${ifDefined(isLink ? undefined : this.disabled)}
変更後:
?disabled=${ifDefined(isLink ? undefined : this.disabled)}
?inert=${ifDefined(isLink ? this.disabled : undefined)}
inert 属性は HTML 標準の機能で、要素をインタラクティブでない状態にします。リンクの場合は inert を、ボタンの場合は従来通り disabled を使用することで、要素タイプによらず無効化が機能します。
スタイル定義も、クラスセレクタから属性セレクタベースに変更されました。button.styles.ts では、.button.disabled から :host([disabled]) へ移行しています。
変更前:
.button.disabled {
opacity: 0.5;
cursor: not-allowed;
}
.button.disabled * {
pointer-events: none;
}
変更後:
:host([disabled]) {
opacity: 0.5;
cursor: not-allowed;
.button {
pointer-events: none;
}
}
ホスト要素の disabled 属性を直接参照することで、内部の要素タイプ(<button> または <a>)に関わらず統一されたスタイリングが適用されます。
設計判断
ホストレベルでの無効化という設計が採用されました。
PR では、disabled 状態のスタイリングを .button クラスではなく :host([disabled]) で制御する方式に変更されています。この判断により、コンポーネントの disabled 属性が shadow DOM 内の要素タイプに依存しない形で機能するようになりました。
inert 属性の選択も重要な設計判断です。aria-disabled や tabindex="-1" といった代替手段も存在しますが、inert はフォーカス不可・クリック不可・スクリーンリーダーからの除外を一度に実現できる点で、より宣言的なアプローチとなっています。
ドキュメントには、リンクボタンの無効化例が追加されました。通常のリンク、新規ウィンドウで開くリンク、ダウンロードリンクの3パターンが示されており、すべてのリンクタイプで disabled が機能することを明示しています。
まとめ
本 PR は、inert 属性を活用してリンクボタンの無効化を実現した変更です。要素タイプに応じた適切な無効化手段(<button> には disabled、<a> には inert)を使い分けることで、ボタンコンポーネントの API を変更せずに一貫した挙動を提供しています。