Skip to content

useWindowManager

useWindowManager() returns the reactive window-manager state plus a set of dispatch functions. Mount it anywhere inside <DesktopProvider>. The library’s own components consume it; consumers use it to build custom UI (alternative docks, a launcher widget, a window-list inspector).

import { useWindowManager } from "@react-ui-os/core";
PropertyTypeDescription
stateWindowManagerStateRaw state: { windows, focusedId, nextZ, workspaces, activeWorkspaceId }. Rarely needed; the convenience fields cover it.
windowsOpenWindow[]All currently-open windows in z-index order.
focusedWindowOpenWindow | nullThe currently-focused window, or null.
windowById(id: string) => OpenWindow | undefinedLook up a window by its stable id.
openWindow(payload, initialBounds?) => voidOpen or focus a window. Dedups by windowIdOf(payload).
closeWindow(id: string) => voidClose a window. Auto-refocuses the next-top.
focusWindow(id: string) => voidBring a window to the top.
minimizeWindow(id: string) => voidFlip state to "minimized". Clears focus if the focused window minimized.
restoreWindow(id: string) => voidRestore from minimized and focus.
toggleMaximize(id: string) => voidCycle normalmaximized.
moveWindow(id, x, y) => voidUpdate position only.
resizeWindow(id, w, h) => voidUpdate size only.
setBounds(id, x, y, w, h) => voidUpdate position + size in one dispatch.
switchWorkspace(workspaceId) => voidShow another workspace; pulls focus there.
moveWindowToWorkspace(id, workspaceId) => voidMove a window to another workspace.
addWorkspace(workspaceId?) => voidAppend a workspace; generates an id when omitted.
removeWorkspace(workspaceId) => voidRemove a workspace; refuses the last and migrates its windows to the first remaining.
type WindowPayload =
| { kind: "app"; appId: string }
| {
kind: "system";
systemId: string;
args?: Record<string, string | number | boolean>;
};
  • App payloads dedup by appId. Opening the same app twice focuses the existing window.
  • System payloads dedup by systemId plus a stable serialization of args. Pass distinct args to open multiple instances (e.g. { name: "Window" } and { name: "Spotlight" } for two component-reference windows).
import { windowIdOf } from "@react-ui-os/core";
windowIdOf({ kind: "app", appId: "notes" });
// → "app:notes"
windowIdOf({ kind: "system", systemId: "component", args: { name: "Window" } });
// → "system:component:name=Window"

Use this when you need to address a window before it exists (e.g. to read its windowById(id) after a deferred open).

function Launcher() {
const { openWindow } = useWindowManager();
useEffect(() => {
const onKey = (e: KeyboardEvent) => {
if ((e.metaKey || e.ctrlKey) && e.key === "n") {
e.preventDefault();
openWindow({ kind: "app", appId: "notes" });
}
};
window.addEventListener("keydown", onKey);
return () => window.removeEventListener("keydown", onKey);
}, [openWindow]);
return null;
}
function WindowList() {
const { windows, focusedWindow, focusWindow } = useWindowManager();
return (
<ul>
{windows.map((w) => (
<li key={w.id}>
<button onClick={() => focusWindow(w.id)}>
{w.id} {w.id === focusedWindow?.id ? "(focused)" : ""}
</button>
</li>
))}
</ul>
);
}

Sync the focused window’s payload to the URL

Section titled “Sync the focused window’s payload to the URL”
const { focusedWindow } = useWindowManager();
const router = useRouter();
useEffect(() => {
if (focusedWindow?.payload.kind === "app") {
router.replace(`/apps/${focusedWindow.payload.appId}`);
}
}, [focusedWindow, router]);