フローティング UI
トリガーに対して相対的に配置されるすべてのインタラクティブ要素には、@floating-ui/dom を使用してください。ドロップダウン、ポップオーバー、メニュー、コンボボックスリスト、ツールチップにおいて、座標を手動で計算したり、CSSの絶対オフセットに依存したりしないでください。
必須構造
- オーバーレイは
createPortal(..., document.body)を介してレンダリングし、レイアウトや重ね合わせコンテキストによってクリップされないようにします。 autoUpdate内でcomputePositionを使用して配置します。オーバーレイが閉じるかアンマウントされるときに、autoUpdateが返す関数をクリーンアップします。apps/desktop/src/components/uiにある最も近い既存のコントロールから始めてください。インタラクションに意図的な差異が必要でない限り、そのplacement、offset、flip、shift、sizeミドルウェアに一致させます。- 計算された
left、top、幅、および利用可能な高さを React 状態に格納します。その状態をポータルのルート要素に適用します。要素のスタイルを直接変更しないでください。 - 参照要素の幅やビューポートの高さによってオーバーレイが制約される場合は、
sizeを使用します。拡大する可能性のあるリストはcomponents/virtual/VirtualList.tsxを使用する必要があります。固定のヘッダーとフッターは仮想ビューポートの外側に維持します。
インタラクションの不変条件
- フォーカスがポータル化されたオーバーレイ内にある間は、トリガーの開いている/フォーカスを示す境界線を表示したままにします。
- 外部のポインター操作または Escape キーで閉じ、その後フォーカスをトリガーに戻します。
- 外部クリックのチェックには、トリガーとオーバーレイの両方を含める必要があります。ネストされたポータル化されたオーバーレイは、そのポインターイベントが親の外部クリックリスナーに到達するのを防ぐ必要があります。これにより、子メニューと対話しても親メニューが閉じることはありません。
- トリガーの状態を
aria-expanded、aria-controls、および適切なaria-haspopupで公開します。オーバーレイには、一致する menu、listbox、dialog、または tooltip セマンティクスを付与します。 - すべてのビューポート端付近の配置、ネストされたオーバーレイのクリック、キーボードによる解除、仮想スクロール、および固定フッターの動作を検証します。