Skip to content

Migrating from WinBox ​

@surdeddd/wmkit/winbox speaks the WinBox.js 0.2 API, so an app moves over by changing one import. Under it runs the wmkit manager, which brings snapping, keyboard control, screen-reader announcements, undo and persistence along.

Three steps ​

  1. Install: npm i @surdeddd/wmkit.
  2. Swap the import:
    js
    // before
    import WinBox from 'winbox/src/js/winbox.js'
    import 'winbox/dist/css/winbox.min.css'
    // after
    import WinBox from '@surdeddd/wmkit/winbox'
  3. Delete the WinBox stylesheet import. A WinBox-like look is injected once (<style data-wmkit-winbox>); call WinBox.configure({ styles: false }) before the first window to bring your own.

Every way of opening a window keeps working: new WinBox(title, options), new WinBox(options), WinBox.new(...) and WinBox(...) without new.

In CommonJS, require('@surdeddd/wmkit/winbox') returns the constructor itself, as WinBox's own bundle does; .default, .WinBox, .winboxMessages and .winboxMessagesRu hang off it. The CommonJS types use export =, so import WinBox = require('@surdeddd/wmkit/winbox') type-checks in TypeScript.

What maps to what ​

WinBoxwmkit
id, title, width, height, x, y (px, %, "center", "right", "bottom")the same, resolved against the window area
minwidth, minheight, maxwidth, maxheightminSize / maxSize of the window
modallayer: 'modal' plus a backdrop; the windows below take no input
max, min, hiddenstart maximized, minimized or hidden
mount, html, urlnode moved in (and back on close), innerHTML, an iframe
top, right, bottom, leftthe area the windows live in; snapping and maximize respect it
overflowwindows may leave the area
background, border, icon, classthe same; control classes no-min, no-max, no-full, no-close, no-resize, no-move, no-header, no-shadow, no-animation
autosizesize to the content once it is in
oncreate, onclose(force) (a truthy return vetoes), onfocus, onblur, onmove(x, y), onresize(w, h), onminimize, onmaximize, onrestore, onfullscreen, onhide, onshowthe same, with the instance as this
mount, unmount, setUrl, setTitle, setIcon, setBackground, move, resize, close(force), focus, blur, hide, show, minimize, maximize, fullscreen, restore, addClass, removeClass, hasClass, toggleClass, addControl, removeControlthe same, chainable
x, y, width, height, minwidth … (writable), min, max, full, hidden, focusedthe same
WinBox.stack()open windows in focus order, the focused one last

The markup keeps WinBox's class names — .winbox with the focus, min, max, full, hide and modal state classes, .wb-header, .wb-control (.wb-min, .wb-max, .wb-full, .wb-close), .wb-drag, .wb-icon, .wb-title, .wb-body — so CSS written for WinBox keeps applying.

The state classes and the callbacks follow the manager rather than the call that caused a change, so they stay right after undo, redo, a restored layout and a viewport change. onresize and onmove also fire when maximizing, restoring or snapping changes the geometry, in the order WinBox uses: resize, then move, then the stage callback.

What is different ​

  • Snapping and keyboard control are on. Drag a window to an edge to snap it, use the arrow keys on a focused window. Turn either off with WinBox.configure({ snap: false, keyboard: false }). Grouping windows into tabs is off by default and comes back with grouping: true.
  • The control buttons work from the keyboard. They take focus and answer Enter and Space, those added with addControl too. A hidden window cannot take the focus, so F6 skips it, and passing the focus on from a window you hide records no undo step, during undo and redo too.
  • Closing is final. A closed window never comes back through undo, redo or a restored layout; open a new one instead. Undoing the close of a box therefore shows nothing — the box is gone and its window closes again at once — and the next undo goes on to the step before. An undo whose only effect would be to put the focus back on a hidden box shows nothing either.
  • The last window takes its desktop along. When the last window of a desktop closes, the desktop, its controller and their listeners on the page are removed, and the next new WinBox() builds a fresh one. A desktop whose manager you took with WinBox.manager() stays, so persist(WinBox.manager(), …) keeps working.
  • Minimized windows wait in a strip of title buttons along the bottom edge; a click restores them.
  • top/right/bottom/left belong to a desktop, not a window. Windows created with the same set share one desktop; another set gets its own. Positions are measured inside that area.
  • index is ignored: stacking is the manager's job.
  • html writes innerHTML, as in WinBox. Pages that enforce Trusted Types or a strict CSP should pass mount instead.
  • Size. The compat entry is about 22 kB brotli with the manager inside it; winbox.bundle.min.js 0.2.82 is 5.4 kB. The difference pays for snapping, undo, persistence, keyboard control, focus management and the screen-reader layer — if you need none of those, WinBox stays the lighter choice.

Going further ​

WinBox.manager(root?) returns the underlying WindowManager, so the rest of wmkit is one call away:

js
import WinBox from '@surdeddd/wmkit/winbox'
import { persist } from '@surdeddd/wmkit/persist'

persist(WinBox.manager(), { key: 'my-desktop' })
new WinBox('Notes', { width: 400, height: 300 })