SwapOverlay
SwapOverlay draws a dashed ghost over the window that a drop would swap with. WindowManager shows it while a docked window is dragged onto an occupied slot.
import { SwapOverlay } from 'jarvis-react-ui';
Swap ghost
When active is on and ghostRect is set, a dashed outline covers that rect; hovered gives it a
stronger fill and glow. Like SnapOverlay, the overlay is a
position: fixed layer over its containing block and ignores the pointer. The ghost gets its rect
as the CSS variables --lib-swap-ghost-x, -y, -w and -h.
import { useState } from 'react';
import { SwapOverlay, Switch, Window } from 'jarvis-react-ui';
const TARGET = { x: 0, y: 0, w: 300, h: 160 };
export default function Basic() {
const [active, setActive] = useState(true);
const [hovered, setHovered] = useState(false);
return (
<div className="flex flex-col items-center gap-4">
<div className="flex gap-6">
<Switch label="Active" checked={active} onCheckedChange={setActive} />
<Switch label="Hovered" checked={hovered} onCheckedChange={setHovered} />
</div>
{/* transform-gpu makes this box the containing block of the fixed overlay. */}
<div className="relative h-[160px] w-[300px] transform-gpu">
<Window
id="agenda"
title="Agenda"
ix="▦"
position={TARGET}
draggable={false}
itemRenderer={() => '09:30 · Standup'}
/>
<SwapOverlay active={active} ghostRect={TARGET} hovered={hovered} />
</div>
</div>
);
}
In WindowManager
During a drag of a compact window, WindowManager checks whether the slot under the pointer holds
another window. If it does, SwapOverlay is turned on with hovered, and ghostRect is that
window's slot, so the user sees which window will trade places. SnapOverlay keeps highlighting the
target slot at the same time.
Standalone use
With useSlotDrag, slotDragState.swapTarget is the id of the window in the
hovered slot. Look up its slot rect (see the slot grid helpers) and pass it
as ghostRect:
const { swapTarget } = slotDragState;
const swapRect = swapTarget !== null ? slotRects[assignments[swapTarget]] : null;
<SwapOverlay active={swapRect !== null} ghostRect={swapRect} hovered />;
Accessibility
The overlay is decorative: its root is aria-hidden and it takes no pointer events.
API
| Prop | Type | Default | Description |
|---|---|---|---|
active (required) |
boolean |
Whether the ghost is drawn; nothing is drawn while false or without a ghostRect. |
|
ghostRect (required) |
SlotRect | null |
Rect of the window that would be swapped, or null for no ghost. |
|
className |
string |
Extra classes for the root <div> element (the fixed full-size layer). |
|
hovered |
boolean |
false |
Highlights the ghost with a stronger fill and glow, e.g. while the drop would swap. |
Type SlotRect
Rectangular geometry (pixel-absolute, viewport-relative).
| Field | Type | Default | Description |
|---|---|---|---|
h (required) |
number |
Height in px. | |
w (required) |
number |
Width in px. | |
x (required) |
number |
Left edge in px. | |
y (required) |
number |
Top edge in px. |