- Shipped
- September 3, 2026 at 5:39 PM UTC
- Author
- Kamo
- Commit
- 4e36c5d
A popup tool window has had three states: docked in the row along the bottom, maximized over the viewport, or minimized to a chat head. This adds FLOATING — detached from the row, dropped anywhere on the screen, and resized from any edge — and reaches it two ways. THE BUTTON. A control in the title bar, wearing the same icon that detaches a note, lifts the window off the slot it was in and cascades it clear of the dock so the eye can follow it. Pressed again it goes back to the row. A maximized window is un-maximized and centred instead, since it has no slot to come off. THE DRAG, which is the interesting half. Pressing the title bar and pulling is ONE gesture with three outcomes, and where the window is let go decides which: - released with its bottom edge within 96px of the viewport's bottom, it takes a slot in the row — so dragging a docked window sideways REORDERS the dock, which was not previously possible at all; - released anywhere else it floats there, which for a docked window is the moment it detaches. It detaches from exactly where it was, so nothing jumps; - and a floating window dragged back down snaps into the row as it approaches, at its standard size and in order with its neighbours. The bottom EDGE is measured, not the pointer: dragging a 650px window by its title bar puts the pointer 600px above the dock on the first frame, and a pointer test would detach every attempt at a reorder. Nothing is committed until the pointer comes up. The carried window, the neighbours shuffling to make room (or closing ranks behind it), the drop rail brightening as the dock nears and the halo around the slot it will land in are all a preview resolved from the live box each frame — which is what makes Escape, and changing your mind halfway, cost nothing. Two smaller decisions worth naming. Docked windows are now positioned from their TOP edge rather than pinned with "bottom: 0"; top and bottom are different properties and no transition carries an element between them, so the snap would have jumped however it was timed. And "resizable: false" becomes a FLOOR once a window is off the row rather than a veto — the email composer is one of the fixed-size tools, and it is the window members most want more room for. The row order and the float geometry both survive a reload: the snapshot carries the float box, the dock size to return to, and the array order, which is the member's own left-to-right arrangement. Requires @kamo/tool-core 0.1.6 (setFloating / setFloatGeometry / setWindowOrder), bumped here.