@メンション後のカンマが改行される問題をCSSとUnicode文字で修正

basecamp/lexxy

display: inline-flex が生み出すアトミックインラインボックスと、importDOM が注入するスペース文字が組み合わさり、@メンション直後のカンマが次の行に折り返される問題が発生していました。本PRはCSS・Unicode・削除ボタンの3点を同時に修正することでこの問題を根本解決しています。

背景

アトミックインラインボックスソフトラップ機会という2つの要因が重なり、メンション後の句読点が意図しない位置で折り返されていました。CustomActionTextAttachmentNode のカスタム要素に適用されていた display: inline-flex は、要素全体を単一のインラインボックスとして扱います。これにより、要素の前後にライン折り返しの機会が生まれます。

さらに、importDOM の実装がメンション要素の末尾にスペース文字を注入していました。スペースはそれ自体がソフトラップ機会となるため、幅の狭い画面ではブラウザがスペースの位置で折り返し、直後のカンマだけが次の行に取り残される現象が発生していました。エディタ幅を250pxから120pxに縮小するリグレッションテストによってこの問題が再現・検証されています。

技術的な変更

修正は「CSS変更」「スペース文字の置き換え」「削除ボタンの表示制御」の3つで構成されており、それぞれが前述の問題に対応します。

CSS: display: inline-flex から display: inline

lexxy-content.css のカスタムアタッチメントに対するスタイルを変更し、アトミックインラインボックスを解消しました。

変更前:

action-text-attachment {
  align-items: center;
  display: inline-flex;
  gap: 0.25ch;
  /* ... */
}

変更後:

action-text-attachment {
  display: inline;
  /* ... */

  img {
    margin-inline-end: 0.25ch;
    vertical-align: middle;
  }
}

inline-flex で実現していたアバター画像の整列(align-items: centergap)は、display: inline への変更により機能しなくなります。これを補うために img 要素へ vertical-align: middlemargin-inline-end: 0.25ch を追加し、レイアウトを維持しています。

Word Joiner (U+2060) によるソフトラップ機会の抑制

PRの説明によれば、importDOM が注入していたトレーリングスペースを Word Joiner (U+2060) に置き換えることで、メンション要素と後続テキスト間のソフトラップ機会を明示的に抑制しています。U+2060 はゼロ幅の非改行文字であり、前後の文字を「接着」してブラウザが改行できないようにします。

削除ボタンの表示制御

display: inline はポジション指定された子要素のレイアウトをサポートしないため、lexxy-node-delete-button を常時表示したままにすることができなくなりました。lexxy-editor.css を修正し、削除ボタンをデフォルトで非表示にし、ノード選択時のみ表示する方式に変更しています。

変更前:

lexxy-node-delete-button {
  inset-inline-start: 0;
  /* ... */
}

変更後:

lexxy-node-delete-button {
  display: none;
  inset-inline-start: 0;
  /* ... */
}

&.node--selected lexxy-node-delete-button {
  display: block;
}

削除ボタンは .node--selected クラスが付与された場合にのみ表示されるため、選択時の操作性は維持されています。

テストの整備

mentions.test.js に幅スイープ型のリグレッションテストが追加されました。エディタ幅を250pxから120pxまで段階的に縮小し、メンションが1行に収まる全ての幅でカンマが同じ行に表示されることを検証します。既存のテストは test.describe("via prompt system") 配下に整理され、新テストと明確に区別されています。

設計判断

display: inline への変更は、アトミックインラインボックスを根本的に排除する最もシンプルなアプローチです。inline-flexinline-block を維持しながら white-space: nowrap でラップを抑制する案も考えられますが、それではメンション要素そのものの途中での折り返しは防げても、要素境界でのラップ機会は残ります。display: inline への変更はこの問題を構造的に解決します。

アバター画像のレイアウト維持に vertical-align: middle を使用している点も注目に値します。inline-flexalign-items: center が提供していた垂直中央揃えを、インラインボックスモデルの範囲内で再現する手法として、古典的かつ堅牢な選択です。

削除ボタンを「常時表示から選択時のみ表示」へと変更した判断は、display: inline への移行が強いる制約への対応ですが、結果的にUIとして自然な振る舞いにもなっています。

まとめ

本PRは、CSS表示モデルの根本的な性質(アトミックインラインボックス)とUnicodeの制御文字(Word Joiner)を組み合わせて、句読点の不正な折り返しを解消しました。display: inline-flex から display: inline への一見シンプルな変更が、削除ボタンのレイアウト戦略の見直しまで波及するという、インラインボックスモデルの影響範囲の広さを示す好例といえます。

記事メタデータ

Generated by:
Claude Sonnet 4.6 for DiffDaily
LLM Trace:
fa4b420d

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

品質レビュー結果

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

Review Criteria:

記事構成 ✓ PASS

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

リード文(総論)→背景・技術的変更・設計判断(各論)→まとめ(結論)という「総論→各論→結論」の3部構成が明確に適用されており、非常に分かりやすい構成です。

カスタムMarkdown構文 ✓ PASS

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

ファイル名付きシンタックスハイライト(```css:path/to/file.css```)とGitHubのPRリンク記法([#853](URL))が正しく使用されています。

対象読者への適合性 ✓ PASS

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

「アトミックインラインボックス」「ソフトラップ機会」「Word Joiner」といった専門用語を適切に使用しており、対象読者であるエンジニアに適した技術レベルで書かれています。

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

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

各セクションが総論→各論の構成になっており、各段落はトピックセンテンスで始まっています。1段落1トピックの原則も守られており、可読性が高いです。

Diff内容との照合 ✓ PASS

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

記事内で引用されているCSSのコードブロックは、提供されたDiffの内容と完全に一致しています。変更前後のコードが正しく示されており、説明とも整合性が取れています。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

「アトミックインラインボックス」「Word Joiner (U+2060)」「vertical-align」など、PR DescriptionやCSSの仕様で用いられる技術用語が正確に使用されています。

説明の技術的正確性 ✓ PASS

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

「display: inline-flex」が改行問題の原因であること、その解決策として「display: inline」への変更とそれに伴うレイアウトの再調整が必要であることなど、技術的な説明はPRの内容と一致しており、論理的かつ正確です。

事実の突合 ✓ PASS

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

記事内のすべての主張(問題の原因、3つの修正点、テストの追加)は、PRのDescriptionやDiffの内容によって裏付けられています。根拠のない推測や創作は見られません。

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

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

PR番号「#853」やUnicodeコードポイント「U+2060」などの数値・固有名詞はすべて正確に記載されています。

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

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

記事タイトル「@メンション後のカンマが改行される問題をCSSとUnicode文字で修正」は、PRのタイトル「Glue commas to their @mentions」の内容を技術的アプローチを含めて具体的に表現しており、主題と完全に一致しています。

外部知識の正確性 ✓ PASS

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

記事に含まれる情報はすべてPRで提供された情報に基づいており、バージョンサポート状況やリリース日程といったPR外の知識の追加はありません。

時間表現の正確性 ✓ PASS

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

「発生していました」「修正しています」といった時間表現は、問題の発生と今回の修正という文脈を正しく反映しており、PR情報との矛盾はありません。