fix: resolve widget overlaps after resize

When resizing a widget, any widget that gets overlapped is automatically
pushed down to clear the collision. Multi-pass overlap detection ensures
cascading widgets are all resolved. Positions persisted to API.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Gjermund Høsøien Wiggen
2026-06-09 13:48:07 +02:00
parent 41fb10120c
commit b3da204bd0

View File

@@ -194,9 +194,49 @@ export default function DashboardPage({ params }: { params: Promise<{ id: string
document.removeEventListener("mousemove", onMove); document.removeEventListener("mousemove", onMove);
document.removeEventListener("mouseup", onUp); document.removeEventListener("mouseup", onUp);
setResizingId(null); setResizingId(null);
const updated = widgets.find((w) => w.id === widgetId);
if (updated) { // Resolve overlaps: push overlapping widgets out of the way
await updateWidget(id, widgetId, { position: updated.position }); let resolved = widgets.map((w) => (w.id === widgetId ? { ...w, position: { ...w.position } } : w));
const movedIds = new Set<string>();
// Keep pushing until no overlaps
for (let pass = 0; pass < 10; pass++) {
let hasOverlap = false;
for (let i = 0; i < resolved.length; i++) {
for (let j = i + 1; j < resolved.length; j++) {
const a = resolved[i].position;
const b = resolved[j].position;
const ax2 = a.x + a.w;
const ay2 = a.y + a.h;
const bx2 = b.x + b.w;
const by2 = b.y + b.h;
if (ax2 > b.x && a.x < bx2 && ay2 > b.y && a.y < by2) {
hasOverlap = true;
// Fix the resized widget in place, push the OTHER widget down
const toMove = widgetId === resolved[i].id ? j : i;
const movedW = resolved[toMove];
const fixedW = resolved[widgetId === resolved[i].id ? i : j];
const newY = fixedW.position.y + fixedW.position.h;
resolved[toMove] = {
...movedW,
position: { ...movedW.position, y: newY },
};
movedIds.add(movedW.id);
}
}
}
if (!hasOverlap) break;
}
setWidgets(resolved);
// Persist positions
for (const w of resolved) {
const original = widgets.find((o) => o.id === w.id);
if (original && (original.position.y !== w.position.y || original.position.h !== w.position.h)) {
await updateWidget(id, w.id, { position: w.position });
}
} }
}; };