プロンプトのはみ出しをウィンドウではなくエディタ境界で制御する

basecamp/lexxy

エディタがモーダル内に表示される場合、右端付近でプロンプトを開くとウィンドウ幅を基準にしたクリッピング判定が機能せず、ポップオーバーが画面外にはみ出す問題がありました。この修正により、判定基準をウィンドウからエディタ自身の矩形に変更し、プロンプトが常にエディタの範囲内に収まるようになります。

背景

メンションやスラッシュコマンドなどのプロンプトは、入力位置に応じてポップオーバーを表示します。このポップオーバーが右端に近い位置で開かれた際に data-clipped-at-right 属性を付与してレイアウトを調整する仕組みが既に存在していましたが、その判定に window.innerWidth を使用していました。

エディタがページ全体を占める通常のユースケースでは window.innerWidth での判定が概ね機能しますが、モーダルやサイドバーなどエディタがビューポートの一部に配置される場合、エディタの右端よりも先にウィンドウ右端が存在するため、クリッピング判定が実際の表示領域を正しく捉えられていませんでした。結果として、ポップオーバーのアイテムが読み取り不能な状態になっていました。

技術的な変更

変更の核心は src/elements/prompt.js の判定条件を1行変更することです。ポップオーバーの右端が超えてはならない境界を、ウィンドウ幅からエディタ自身の右端座標に切り替えました。

変更前:

if (popoverRect.right > window.innerWidth) {
  this.popoverElement.toggleAttribute("data-clipped-at-right", true)
}

変更後:

if (popoverRect.right > editorRect.right) {
  this.popoverElement.toggleAttribute("data-clipped-at-right", true)
}

なお、editorRect はこのコードよりも前の処理で getBoundingClientRect() を使って取得済みであり、新たなDOM操作の追加は不要でした。

テストコード(test/browser/tests/prompts/mentions.test.js)も合わせて更新されています。変更前のテストはビューポートサイズ400pxに対してエディタを右寄せで150px幅に設定し、ポップオーバーがビューポート内(rect.right <= 400)に収まることを確認していました。変更後は、エディタを220px幅にしてビューポート端との余白を確保したうえで、ポップオーバーの境界が エディタの境界editorRect.right / editorRect.left)に対して収まっているかを検証するよう変更されました。テストのタイトルも "popover stays within viewport" から "popover stays within the editor" へと修正され、意図が明確になっています。

設計判断

「コンテナを基準にする」 というアプローチは、エディタをどの文脈に埋め込んでも正しく機能するという点で汎用性が高い判断です。ウィンドウ幅を基準にする実装はエディタがフルページで表示される前提を暗黙的に持っており、モーダルやパネルへの埋め込みを想定した設計ではありませんでした。editorRect.right を使うことで、エディタ自身が自分のレイアウトコンテキストを参照するようになり、外部の状態(ウィンドウサイズ)への依存が排除されます。

この変更は1行の差分でありながら、テストの検証対象も「ビューポート」から「エディタ」へと整合性が取れており、修正の意図が実装・テスト・テスト名の3箇所すべてに一貫して反映されています。

まとめ

クリッピング判定の基準を window.innerWidth から editorRect.right へ変更したことで、モーダルやパネルなどあらゆる埋め込みコンテキストでプロンプトが正しくエディタ内に収まるようになります。「自分のコンテナを基準にする」という単純な原則の適用が、埋め込みユースケース全般の堅牢性を高めています。

記事メタデータ

Generated by:
Claude Sonnet 4.6 for DiffDaily
LLM Trace:
4bcd4029

この記事はAIによって自動生成されています。内容の正確性については、必ずソースコードやPRを確認してください。

品質レビュー結果

Review Status:
承認済み
Review Count:
1回
Reviewed by:
Gemini 2.5 Pro for DiffDaily

Review Criteria:

記事構成 ✓ PASS

Title, Context, Technical Detailの存在と明確さ

「リード文→背景→技術的な変更→設計判断→まとめ」という総論→各論→結論の構成が明確で、読者が変更の全体像と詳細をスムーズに理解できる構成になっている。

カスタムMarkdown構文 ✓ PASS

シンタックスハイライト・GitHubリンク記法の正確性

ファイル名付きシンタックスハイライト(```javascript:filepath```)およびPR番号のリンク記法([#1077](URL))がガイドラインに準拠して正しく使用されている。

対象読者への適合性 ✓ PASS

エンジニア向けの適切な技術レベルと表現

専門用語を前提として使用し、冗長な説明を省いているため、対象読者であるエンジニアにとって非常に読みやすい内容となっている。

パラグラフ・ライティング ✓ PASS

トピックセンテンス・1段落1トピック・段落長

各セクション・各パラグラフがトピックセンテンスで始まり、1段落1トピックの原則が守られている。非常に構造的で可読性の高い文章構成である。

Diff内容との照合 ✓ PASS

コードブロックとDiff内容の一致

`src/elements/prompt.js`のコード変更と、`mentions.test.js`のテストロジックの変更が、提供されたDiffと完全に一致している。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

`window.innerWidth`, `getBoundingClientRect`, `popover`などの技術用語が、文脈に沿って正確かつ適切に使用されている。

説明の技術的正確性 ✓ PASS

技術的主張の正確性と論理性

ウィンドウ幅を基準にした判定の問題点と、エディタの矩形を基準にする解決策の技術的な妥当性について、論理的かつ正確に説明されている。

事実の突合 ✓ PASS

PR情報による主張の裏付け(ハルシネーション検出)

記事内のすべての主張(問題の背景、解決策、テストの変更意図)は、PRのDescriptionとDiffの内容で裏付けられており、ハルシネーションは見られない。

数値・固有名詞の確認 ✓ PASS

PR番号・コミットID・バージョン等の正確性

PR番号(#1077)やファイルパスが正確に記載されている。

タイトル・説明との一致 ✓ PASS

記事タイトル・説明とPR内容の一致

記事のタイトル「プロンプトのはみ出しをウィンドウではなくエディタ境界で制御する」は、PRのタイトル「Keep prompts horizontally within the editor」の内容を的確に表現している。

外部知識の正確性 ✓ PASS

PRに記載のない外部知識(LTS、サポート状況など)の不使用

PRで言及されていないバージョン情報やサポート状況などの外部知識は含まれておらず、提供された情報源に忠実である。

時間表現の正確性 ✓ PASS

時間表現がPR情報と一致しているか

PRで示されている問題の状況(...was overflowing)を正しく反映しており、時間表現の歪曲は見られない。