サンドボックス DnD の仕組み
このページの目的
見出しへのリンクカンバン、並べ替えテーブル、編集可能なファイルツリーは、同じ組み込み sortable DnD runtime を使っていますが、見え方は同じではありません。重要なのは remote 側の reorder ロジックだけではなく、各 sandbox が host 側の drag presentation をどうスタイリングして、実際の製品に近い操作感を作っているかです。
レイヤー 1: remote state は Worker に置く
見出しへのリンク各 sandbox の source of truth は remote worker の中にあります。
- kanban の worker は lane と card を持つ;
- table の worker は row order を持つ;
- file tree の worker は nested node、rename state、inline action を持つ。
worker は RemoteSortableContainer、RemoteSortableItem、RemoteDragHandle を描画し、onDrop で RemoteSortableEvent を処理します。host はその state を直接変更しません。
レイヤー 2: host が実 DOM と hit-testing を担当する
見出しへのリンク実際の DOM ツリーは docs ページ側が持ちます。HostedTree が preview に remote view を mount し、組み込みの host DnD runtime が次を処理します。
- pointer tracking と drag threshold;
before、after、insideの解決;- item
typeと containeracceptsによる acceptance checks; pointercancel、Escape、unmount 時の session cleanup。
この分離によって、低レベルの DOM 処理は信頼された host に残り、worker は data と UI structure に集中できます。
レイヤー 3: drag presentation は host runtime に built-in されている
見出しへのリンクsandbox はもう host 側で独自の overlay ロジックを書いていません。組み込みの DnD presentation layer が次を作ります。
- 掴んだ source item の floating overlay clone;
- drop 位置を示す placeholder;
data-dnd-source、data-dnd-target、data-dnd-placement、data-dnd-drop-allowedのような real DOM state attributes。
そのため demo の host 側はかなり単純です。worker を起動し、endpoint を mount し、teardown で unmount するだけです。
レイヤー 4: CSS が各 sandbox の見え方を決める
見出しへのリンクスタイリングが少し複雑なのは、3 つの demo が同じ runtime markers を共有しつつ、それを異なる視覚表現に変換しているからです。
- kanban は placeholder を card-shaped vacancy として見せ、empty lane を full-height drop-zone にする;
- sortable table は overlay と placeholder を row geometry のまま保ち、card-like に見えないようにする;
- file tree は placeholder を compact node slot として描き、drag presentation 中は nested children を隠して tree move を読みやすくする。
重要なのは、CSS 自身が drag state を発明しないことです。CSS は host runtime markers と sandbox の DOM structure に反応するだけです。
sandbox CSS の原則
見出しへのリンク- drag presentation に docs chrome や markdown の style が漏れないよう、sandbox root に style を閉じ込める。
data-dnd-overlayとdata-dnd-placeholderを、別物の widget ではなく real item の variation として扱う。- placeholder のサイズを real item と揃え、reorder 時の list や tree のジャンプを防ぐ。
- empty container を独立した drop target として扱い、独自の visual state を持たせる。
- row actions や nested tree children など、overlay の可読性を下げる部分は drag presentation から外す。
table と tree に追加の工夫が必要な理由
見出しへのリンク同じ DnD contract を使っていても、2 つの例は追加の配慮が必要です。
- table row は generic block element として preview できないため、host presentation layer は cell geometry を保つ table-row adapter を使う;
- tree node は visible row だけでなく node slot 全体を wrap する必要があり、そうしないと same-list reorder で余計な高さが増え、nested drop も不安定になる。
これは別の remote API ではなく、presentation と structure の問題です。
demo の外でも再利用できるもの
見出しへのリンク- worker 側の state pattern はそのまま再利用しやすく、worker が source of truth を持って drop を適用する。
- built-in host drag presentation もそのまま再利用でき、overlay、placeholder、DOM markers は runtime が提供する。
- CSS は意図的に example-specific です。再利用すべきなのは principle と selector で、最終的な見た目は board、table、tree のどれを作るかで変わります。