From f9bc92b4d299599d42282c3eb42e394423db013f Mon Sep 17 00:00:00 2001 From: cynfria Date: Thu, 27 Aug 2026 16:57:30 -0700 Subject: [PATCH] feat(desktop): preview panel merge edge Signed-off-by: cynfria --- .../app/buzz-project-prototype.tsx | 34 +++++++++++++++++++ prototypes/project-cube-orbit/app/globals.css | 27 +++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/prototypes/project-cube-orbit/app/buzz-project-prototype.tsx b/prototypes/project-cube-orbit/app/buzz-project-prototype.tsx index b717a68671..8547a5d96c 100644 --- a/prototypes/project-cube-orbit/app/buzz-project-prototype.tsx +++ b/prototypes/project-cube-orbit/app/buzz-project-prototype.tsx @@ -1025,8 +1025,32 @@ function MessagesView() { y: number; connectedAtStart: boolean; hasBroken: boolean; + previewCell: HTMLElement | null; + previewEdge: MessagePanelEdge | null; } | null>(null); + const clearMergePreview = (drag: NonNullable) => { + if (drag.previewCell && drag.previewEdge) { + drag.previewCell.classList.remove(`merge-preview-${drag.previewEdge}`); + } + drag.previewCell = null; + drag.previewEdge = null; + }; + + const updateMergePreview = ( + drag: NonNullable, + snap: ReturnType, + ) => { + if (snap && drag.previewCell?.dataset.panelId === snap.target && drag.previewEdge === snap.edge) return; + clearMergePreview(drag); + if (!snap) return; + const targetCell = boardRef.current?.querySelector(`[data-panel-id="${snap.target}"]`); + if (!targetCell) return; + targetCell.classList.add(`merge-preview-${snap.edge}`); + drag.previewCell = targetCell; + drag.previewEdge = snap.edge; + }; + const isPanelConnected = (id: MessagePanelId) => connections.some((connection) => connection.a === id || connection.b === id); @@ -1149,6 +1173,8 @@ function MessagesView() { y: current.y, connectedAtStart, hasBroken: false, + previewCell: null, + previewEdge: null, }; cell.classList.add("is-pulling", "is-active-drag"); }; @@ -1173,6 +1199,10 @@ function MessagesView() { drag.cell.style.setProperty("--panel-y", `${drag.y}px`); drag.cell.style.setProperty("--panel-tilt", `${Math.max(-1.2, Math.min(1.2, (event.clientX - drag.startX) * 0.012))}deg`); drag.cell.classList.toggle("is-breaking", drag.hasBroken); + updateMergePreview( + drag, + drag.connectedAtStart && !drag.hasBroken ? null : findSnapTarget(drag.id, drag.x, drag.y), + ); }; const endPanelDrag = (event: ReactPointerEvent) => { @@ -1186,6 +1216,7 @@ function MessagesView() { ? connections : connections.filter((connection) => connection.a !== drag.id && connection.b !== drag.id); const snap = stayedConnected ? null : findSnapTarget(drag.id, drag.x, drag.y); + clearMergePreview(drag); const next = stayedConnected ? { x: drag.originX, y: drag.originY } : snap @@ -1223,6 +1254,7 @@ function MessagesView() {