Quick Start
This guide walks you through creating windows with Glazier. We’ll show both the recommended approach using WindowFrame composables and the manual approach for full control.
Option 1: Using WindowFrame Composables (Recommended)
The WindowFrame system dramatically reduces boilerplate while still giving you full styling control.
Setup
First, wrap your app with WindowManagerProvider and define your windows:
import { useRef } from "react";import { WindowManagerProvider, Window, Desktop, createRegistry,} from "glazier";import { defineWindows } from "glazier/server";
// Define all windows in one placeconst windows = defineWindows({ home: { title: "My Window", defaultPosition: { x: 100, y: 100 }, defaultSize: { width: 400, height: 300 }, path: "/", },});
// Type-safe component registryconst registry = createRegistry(windows.ids, { home: MyWindow,});
function App() { const containerRef = useRef<HTMLDivElement>(null);
return ( <WindowManagerProvider boundsRef={containerRef} registry={registry} defaultWindows={[windows.getWindowState("home")]} > <div ref={containerRef} style={{ position: "relative", height: "100vh" }}> <Desktop> {({ windowId, component: Component }) => ( <Window id={windowId} className="bg-white rounded-lg shadow-xl"> <Component windowId={windowId} /> </Window> )} </Desktop> </div> </WindowManagerProvider> );}Create a Window Component
Use WindowFrame composables for minimal boilerplate:
import { WindowFrame, TitleBar, Title, WindowControls, Content, ResizeHandles,} from "glazier";
function MyWindow({ windowId }: { windowId: string }) { return ( <WindowFrame windowId={windowId} enableDoubleClickMaximize enableSnapToEdges > {/* Title bar with drag support */} <TitleBar className="flex h-10 items-center justify-between bg-slate-900 px-3"> <Title className="text-white font-medium" /> <WindowControls className="flex gap-1" buttonClassName="p-1 rounded hover:bg-slate-700 text-slate-400" closeButtonClassName="hover:bg-red-600 hover:text-white" /> </TitleBar>
{/* Content area */} <Content className="p-4 overflow-auto"> <h1>Hello from Glazier!</h1> <p>This window is draggable and resizable.</p> </Content>
{/* Resize handles */} <ResizeHandles windowId={windowId} minWidth={300} minHeight={200} /> </WindowFrame> );}That’s it! You now have a fully functional window with:
- Draggable title bar
- Double-click to maximize
- Snap-to-edges support
- Minimize, maximize, close controls
- Resize handles on all 8 edges
Option 2: Manual Control (Full Flexibility)
For complete control over every aspect, use the lower-level hooks:
Basic Setup
import { useRef } from "react";import { WindowManagerProvider } from "glazier";
function App() { const containerRef = useRef<HTMLDivElement>(null);
return ( <WindowManagerProvider boundsRef={containerRef} defaultWindows={[ { id: "window-1", title: "My Window", position: { x: 100, y: 100 }, size: { width: 400, height: 300 }, zIndex: 1, displayState: "normal", }, ]} > <div ref={containerRef} style={{ position: "relative", height: "100vh" }}> <MyWindow windowId="window-1" /> </div> </WindowManagerProvider> );}Creating a Window Component
import { useRef } from "react";import { Window, useWindowManager, useWindowDrag, useResize,} from "glazier";
function MyWindow({ windowId }: { windowId: string }) { const { state, updateWindow, closeWindow } = useWindowManager(); const win = state.windows.find((w) => w.id === windowId); const titleBarRef = useRef<HTMLDivElement>(null);
const { isDragging, dragHandleProps } = useWindowDrag({ windowId, dragHandleRef: titleBarRef, enableDoubleClickMaximize: true, });
const { resizeHandleProps } = useResize( win?.size ?? { width: 400, height: 300 }, win?.position ?? { x: 0, y: 0 }, { minWidth: 200, minHeight: 150, onResize: (size, position) => updateWindow(windowId, { size, position }), } );
if (!win) return null;
return ( <Window id={windowId}> {/* Title bar - drag handle */} <div ref={titleBarRef} {...dragHandleProps}> {win.title} <button onClick={() => closeWindow(windowId)}>×</button> </div>
{/* Content */} <div>Window content here</div>
{/* Resize handle */} <div {...resizeHandleProps("se")} /> </Window> );}Understanding the Parts
WindowManagerProvider
The root provider manages all window state. Key props:
boundsRef- Container element for bounds constraintsdefaultWindows- Initial windows to renderregistry- Component registry for Desktop pattern
defineWindows (glazier/server)
Unified configuration helper. Import from glazier/server for server-component compatibility:
import { defineWindows } from "glazier/server";
const windows = defineWindows({ home: { title: "Home", defaultPosition: { x: 100, y: 100 }, defaultSize: { width: 400, height: 300 }, path: "/", icon: { label: "Home", position: { x: 20, y: 20 } }, },});
// Helperswindows.getWindowState("home"); // Get WindowState for openingwindows.getIconConfigs(); // Get all icon configswindows.getPathMap(); // Get path mapping for routingwindows.ids; // ['home']WindowFrame System
Composable primitives for window chrome:
WindowFrame- Container with drag contextTitleBar- Draggable title barTitle- Window title displayWindowControls- Minimize/maximize/close buttonsContent- Scrollable content areaResizeHandles- All 8 resize handles
Window Component
The Window component handles positioning based on state. It:
- Reads position/size from context
- Applies z-index for stacking
- Handles visibility for minimized state
Next Steps
- Learn about Window Management patterns
- Add Desktop Icons to your interface
- Use the Component Registry for multiple window types