プロンプトメニューの表示方向を強制指定する `vertical-direction` 属性を追加
lexxy-prompt 要素に vertical-direction 属性が追加され、プロンプトメニューの開く方向を top(上向き)または bottom(下向き)に強制指定できるようになりました。固定要素やフローティング要素がビューポート内の領域を視覚的に覆っているレイアウトでも、意図した方向にメニューを表示できます。
背景
Lexxy はデフォルトで、ウィンドウのビューポートに基づいてプロンプトメニューの表示方向を自動計算します。しかし、固定配置やフローティング配置の要素が画面の一部を覆っている場合、ビューポートの境界内にあるにもかかわらずメニューが隠れてしまう問題が起きていました。
このような状況では、自動計算が「利用可能なスペースがある」と判断してしまうため、アプリケーション側から方向を上書きする手段が必要でした。vertical-direction 属性はこのユースケースに対応するためのエスケープハッチとして設計されています。
技術的な変更
src/elements/prompt.js に verticalDirection ゲッターが追加され、表示方向の決定ロジックが更新されました。変更の核心は、既存の「ビューポートからはみ出したら上に開く」という単一条件に、強制指定フラグを組み合わせた論理式への置き換えです。
変更前:
if (popoverRect.bottom > window.innerHeight) {
this.#setPopoverOffsetY(contentRect.height - y + fontSize)
this.popoverElement.toggleAttribute("data-clipped-at-bottom", true)
}
変更後:
get verticalDirection() {
return this.getAttribute("vertical-direction")
}
// ...
const forceTop = this.verticalDirection === "top"
const forceBottom = this.verticalDirection === "bottom"
const overflowsWindow = popoverRect.bottom > window.innerHeight
if (!forceBottom && (forceTop || overflowsWindow)) {
this.#setPopoverOffsetY(contentRect.height - y + fontSize)
this.popoverElement.toggleAttribute("data-clipped-at-bottom", true)
}
条件式 !forceBottom && (forceTop || overflowsWindow) によって、3つのケースが整理されています。forceBottom が真の場合は他の条件に関わらず下向きを維持し、forceTop が真の場合は overflowsWindow の結果を無視して上向きに強制し、どちらも指定がなければ従来の自動計算が適用されます。
使用方法はシンプルで、HTML属性として指定するだけです:
<lexxy-prompt trigger="@" src="..." name="mention" vertical-direction="top"></lexxy-prompt>
設計判断
属性値による宣言的な上書きという設計が採用されました。JavaScriptからプログラム的に制御するAPIではなく、HTML属性として表現されている点が重要です。これにより、サーバーサイドレンダリングのテンプレートから直接制御でき、コンポーネントの利用者がJavaScriptを記述せずに挙動を変更できます。
また、vertical-direction が指定されない場合の挙動は既存と完全に同一であり、後方互換性が保たれています。forceTop と forceBottom が両方とも偽の場合、条件式は overflowsWindow のみに依存するため、既存のコードパスへの影響はありません。
テストは test/browser/tests/prompts/vertical_direction.test.js にブラウザテストとして追加されており、ビューポートサイズを 500×340px に固定した上で、vertical-direction="top" でメニューが編集エリアの上に表示されること、vertical-direction="bottom" でビューポート端でも下向きを維持することをそれぞれ検証しています。
まとめ
本PRは、自動計算では対処できないレイアウト上の制約に対して、宣言的な属性による脱出口を提供する変更です。条件式の最小限の拡張によって既存の自動判定ロジックを壊さずに強制指定を実現しており、フローティングUIを持つアプリケーションでの実用性を高めています。