サブメニューが開いた状態のドロップダウン項目に選択状態のスタイルを適用
<wa-dropdown-item> でサブメニューが開いている際、ホバー時と同じ視覚的フィードバックが表示されない問題が修正されました。キーボード操作でサブメニューを開いた場合でも、ポインター操作と一貫した選択状態が表示されるようになります。
背景
キーボードナビゲーションとポインターナビゲーションの間で、サブメニューを持つドロップダウン項目の視覚的フィードバックに不一致がありました。ポインターでホバーしてサブメニューを開くと選択状態のスタイルが適用されていた一方、キーボード操作でサブメニューを開いた場合はその視覚的インジケーターが表示されませんでした。
#2279 では、この問題がユーザーにとってサブメニューが開いているかどうかを判別しにくいUX上の問題として報告されています。キーボードユーザーは開いたサブメニューの親項目がどれかを視覚的に確認できない状態でした。
アクセシビリティの観点からも、操作手段によらず一貫した視覚的フィードバックを提供することは重要であり、本修正はその一貫性を担保するものです。
技術的な変更
dropdown-item.styles.ts に2箇所のCSSルールが追加され、submenu-open というカスタム状態(CSS Custom State)を持つホスト要素に選択スタイルが適用されるようになりました。
変更前(サブメニューが開いた状態への選択スタイルなし):
:host(:focus-visible) {
z-index: 1;
outline: var(--wa-focus-ring);
...
}
:host([variant='danger']:focus-visible) {
background-color: var(--wa-color-danger-fill-normal);
color: var(--wa-color-danger-on-normal);
}
変更後(:state(submenu-open) への選択スタイルを追加):
:host(:state(submenu-open)) {
background-color: var(--wa-color-neutral-fill-normal);
}
:host([variant='danger']:state(submenu-open)),
:host([variant='danger']:focus-visible) {
background-color: var(--wa-color-danger-fill-normal);
color: var(--wa-color-danger-on-normal);
}
追加されたルールは2点です。デフォルト状態では :host(:state(submenu-open)) に --wa-color-neutral-fill-normal の背景色を適用し、danger バリアントでは既存の :focus-visible セレクターと同じルールブロックに :state(submenu-open) を追加することで、危険な操作を示す項目にも対応しています。
設計判断
CSS Custom State(:state()) を用いてコンポーネントの内部状態をスタイリングに反映する既存のパターンを踏襲した変更です。
Web Componentsでは ElementInternals.states を通じてカスタム状態を定義し、CSS側から :state() 擬似クラスで参照できます。本変更では submenu-open という状態が既にコンポーネント側で管理されており、スタイル側にそれに対応するCSSルールを追加するだけで完結しています。JavaScriptロジックの変更が不要だった点は、既存の状態管理設計が適切に機能していたことを示しています。
danger バリアントのセレクターは :state(submenu-open) と :focus-visible をカンマ区切りで並記する形を採用しており、同じ視覚スタイルを持つ両状態を1つのルールブロックにまとめることでコードの重複を避けています。
まとめ
本修正は、CSS Custom Stateという既存の仕組みを活用して、操作手段に依存しない一貫した視覚フィードバックを最小限のコード変更で実現しています。コンポーネントの状態管理とスタイリングが適切に分離されていたことで、スタイルのみの変更として問題を解決できた点が特筆されます。