Deskwerk· Workshop

Demos

Draggable: a chat window you can move

Try the demo →

In dashboards and work tools, there’s no corner that’s always free: one minute the chat covers the table, the next it covers the chart. The fix is a window the user moves to wherever it isn’t in the way.

The principle: the container moves, not the widget

The widget renders once into an absolutely positioned window. Only the container moves, via CSS transform. Nothing changes for the widget, and the conversation runs on undisturbed:

zE('messenger', 'render', {
  mode: 'embedded',
  widget: { targetElement: '#chat-fenster-inhalt' },
});

Important as always in embedded mode: no second render call. If you want to “reposition” the window, you move it. It can only be rendered once per page load.

Pointer Events instead of mouse fiddling

pointerdown/pointermove/pointerup cover mouse, touch, and stylus at once. Three details make the difference:

griff.addEventListener('pointerdown', (e) => {
  griff.setPointerCapture(e.pointerId); // move events stay with the handle,
  merkePosition(e);                     // even when the pointer leaves the element
});
  • setPointerCapture: without it, the drag breaks off the moment the pointer moves faster than the window.
  • touch-action: none on the title bar: otherwise the touch browser scrolls instead of dragging.
  • Only the title bar is the handle, not the whole window: otherwise you can’t select text in the chat anymore.

Setting boundaries

A window you can push off the viewport is a lost window. So while dragging, the offset is clamped to the allowed area:

dx = Math.max(bereich.left - fenster.left, Math.min(dx, bereich.right - fenster.right));
dy = Math.max(bereich.top - fenster.top, Math.min(dy, bereich.bottom - fenster.bottom));

Along with it comes a reset button in the title bar: one click, and the window sits back at its starting position. The cheapest insurance against “where did my chat go?”.

When it’s worth it

Internal tools, dashboards, configurators: anywhere people work on the same page for a long stretch and the chat is a companion, not the lead. For regular websites, the Custom Launcher or the sidebar stays the calmer pattern.

← Back to the demo