← All posts

Windows on the frontend

Snap connections: pane groups — build a mini-dashboard inside the tab with one drag

Four window types (CSS pane, JS pane, JS Console, Output Console) + action bars + floating button — that's six different things JustZix can render inside a tab. Each one separate, each mobile, each with its own persistent state. Without snap connections (since v2.13.42) you'd have to position every element manually after every F5 and every window resize. Snap connections make them one group.

What are snap connections?

Snap = "magnetic attraction". When you drag a panel/bar/button near another (threshold ~20px), JustZix snaps it edge-to-edge against the other and both sides record themselves as a "group". The next drag of any element in the group → moves the whole group as one.

All 6 element types live in a shared ID space:

ElementID prefixPositioning
Action barab_*Absolute (x, y)
Floating button(fixed)Absolute (x, y)
CSS panecp_*Anchor (x, y, anchor: TL/TR/BL/BR)
JS panejp_*Anchor (same as above)
JS Consolejc_*Anchor
Output Consoleoc_*Anchor

The ID space is uniform — saveGroupPositions(groupIds) classifies each ID by prefix and picks the appropriate storage (chrome.storage.local for action bars and panes, chrome.storage.sync for floating btn).

Anchor positioning — why it matters

Action bars use absolute coordinates: x=200, y=400 from top-left. Resize the window from 1920px to 1280px and the action bar can land off-viewport. Panes (CSS/JS/JS Console/Output Console) use anchor positioning:

{ x: 100, y: 50, anchor: 'TR' }
//                       ^^ Top-Right corner
// Element rendered as: right: 100px; top: 50px;

4 possible anchors: TL (top-left), TR (top-right), BL (bottom-left), BR (bottom-right). After each drag end, absToAnchorPosition picks the anchor that gives the shortest offset — the element snaps to the closest viewport corner. Window resize → the element stays near "its" corner, doesn't fly off-screen.

First mini-dashboard: 30 seconds

Say you're building a QA toolbar for yourself. You want in the top-right corner:

  1. An action bar with 3 buttons ("Reset cart" / "Skip cookie" / "Fill demo data")
  2. A JS pane for "🔥 destructive flow"
  3. An Output Console to monitor logs

Workflow:

  1. Load the page. Action bar appears somewhere (default or last position).
  2. Drag the bar to the top-right corner, ~20px from edges. Anchor gets detected as TR.
  3. Drag the JS pane below the bar — within ~20px of the bar's bottom edge. Snap. Pane + bar = group.
  4. Drag the Output Console below the JS pane — another snap. Three-element group.
  5. F5 → everything renders together, in the same layout; snap connections hold. Anchor TR → layout sticks to the top-right corner even after window resize.

That's your personal QA toolbar. It only works for the domain whose scope matches. Other sites — different toolbar (or none).

What snap detection actually does

Algorithm on drag-end (simplified):

// 1. Get the dragged element's bounds (left, top, w, h)
// 2. For each other draggable in DOM (.jz-pane-*, .jz-actions-bar, #justzix-floating-btn):
//    a. Get other's bounds
//    b. Compute distance: minimum of (top-bottom, bottom-top, left-right, right-left)
//    c. If distance < 20px → snap (align dragged edge-to-edge with other)
// 3. After snap, save all group positions (helper saveGroupPositions(groupIds))
// 4. Group membership = anything with start-position close to the dragged element when drag started

20px threshold is deliberate — loose enough that snap happens without precise targeting, but not so large that you accidentally connect things that shouldn't be. On a trackpad / touch it feels intuitive.

Drag with hidden panes — v2.13.54 fix

Bug reported by a user after v2.13.53: the floating button dragged in a group with a hidden CSS pane → the bar moves with the floating btn correctly, but the CSS pane (also hidden) stays in the old place.

Root cause: hidden panes have no DOM element, but they're still in the group. v2.13.53 skipped them in the "get start position" helper. Fix (v2.13.54): a new cssPanesCache (sync access to pos+size of each pane, populated alongside other data) + helper paneAnchorToAbs(pane) which computes absolute bounds from anchor + viewport without needing the DOM. Now a hidden pane is a full group member even when not visible.

Use case 1 — Mobile-style "bottom dock"

Stick to the bottom edge (anchor BL) a wide action bar with 8 buttons + 2 SLIDERS. Stack JS Console + Output Console as 2 panes above the bar — drag each below the other, snap. After reload you have a "bottom dock" like on mobile. Resize the window from 1920 to 1280 → the whole group stays near the bottom edge (anchor BL holds).

Use case 2 — Mini IDE in a corner

CSS pane + JS pane + Output Console snapped vertically in the top-right. CSS pane on top, you edit live → see the effect. JS pane underneath, click ▶ → fire a custom script. Output Console below, monitor page console.log and your JUSTZIX.log. Three "windows" in a single vertical stream — that's literally a mini-IDE.

Use case 3 — Floating button as an anchor for a group

The floating button is typically the launcher menu in the bottom-right (BR). Stick to it an action bar + Output Console — drag them to the floating btn → snap. Now all 3 are grouped. Drag the floating btn anywhere → bar + Output Console follow. Floating btn becomes the "anchor handle" for the whole group.

Pitfalls

What's next

Snap connections turn JustZix from "a few separate tools" into "a configurable dashboard". It's the last puzzle piece for an in-tab mini-IDE: CSS pane + JS Console + JS pane + Output Console + actions (TOGGLE3, SLIDER) — arranged however you like, with one drag.

Install JustZix and build your first mini-dashboard — 30 seconds, zero configuration code.

Rate this post

No ratings yet — be the first.

Try it yourself

Install JustZix and paste any snippet from this article. Two minutes from zero to a working rule across all your devices.

Get JustZix

Features · How it works · Examples · Use cases