Skip to content

Admin shell: tree/workspace splitter gets stuck in resize mode (pointer-events never restored when mouse is released outside dw-area) #656

Description

@Justinvolved

Summary

In the DW10 admin shell, dragging the splitter between the tree (e.g. the Content page tree) and the workspace (e.g. the Visual Editor) can leave the UI stuck: the cursor stays ew-resize and the whole workspace stops reacting to clicks. Escape, left click in the workspace and right click do not recover it. Only a click inside the tree panel or a page reload does.

Observed on Dynamicweb.CoreUI.Rendering 10.29.1-PreRelease (also present in 10.28.x), Chrome on Windows 11.

Steps to reproduce

  1. Open Content, select a page so the Visual Editor is loaded in the workspace.
  2. Press the mouse on the boundary between the page tree and the workspace (cursor turns into the double arrow).
  3. Drag and release the button while the pointer is outside the dw-area element: over the left application nav, over the browser chrome, outside the window, or on a second monitor. A fast drag that overshoots is enough.
  4. Move back into the workspace.

Result: cursor remains ew-resize, the Visual Editor / workspace ignores all mouse input, Escape does nothing. Clicking in the workspace does not help because the workspace is the element that has been disabled. The stored tree width (localStorage["DW:SHELL:TREE:WIDTH"]) has also jumped to wherever the pointer ended (in our case 992 px, then 1208 px), squeezing the editor.

Cause

In Admin/assets/main.js the tree resizer is wired on each dw-area element roughly like this (de-minified):

area.addEventListener("mousedown", () => {
  if (!nearEdge) return;
  workspace.style.pointerEvents = "none";   // so the iframe stops swallowing events
  workspace.style.userSelect = "none";
  onMove = e => onDragging(e, getNavWidth());
  area.addEventListener("mousemove", onMove);
});
area.addEventListener("mouseup", () => {
  workspace.style.removeProperty("pointer-events");
  workspace.style.removeProperty("user-select");
  area.removeEventListener("mousemove", onMove);
});
area.addEventListener("mousemove", e => {
  nearEdge = Math.abs(getTreeWidth() + getNavWidth() - e.pageX) < 7;
  area.style.cursor = nearEdge ? "ew-resize" : "";
});
area.addEventListener("mouseleave", () => area.removeEventListener("mousemove", onMove));
  • The cleanup runs only on a mouseup that reaches that dw-area element. A mouseup anywhere else (left nav, browser chrome, outside the window) never restores pointer-events on dw-workspace.
  • mouseleave removes the drag handler but does not restore pointer-events / user-select or the cursor.
  • There is no pointercancel / blur / Escape handling, and no pointer capture.

Suggested fix

  • Register the drag-end handler on document (or window) for mouseup / pointerup / pointercancel / blur, not on the area, and run the same cleanup from mouseleave.
  • Alternatively use setPointerCapture on a real splitter element so the release is always delivered to it.
  • Clear area.style.cursor in the cleanup as well.
  • Optional: clamp the persisted DW:SHELL:TREE:WIDTH to a sane maximum (a fraction of the viewport) so a runaway drag cannot collapse the workspace.

Workaround for users

Click once inside the tree panel (not the workspace) to fire the missing mouseup, or reload the page. Reset the width with localStorage.removeItem("DW:SHELL:TREE:WIDTH") and reload.

Metadata

Metadata

Assignees

Labels

AcceptedBugSomething isn't workingPlatformFor items related to the entire platform

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions