Meet Mantine Window, a polished extension for Mantine UI that brings draggable, resizable, and collapsible desktop‑like windows to the browser—perfect for dashboards, admin tools, and rich, interactive UIs.
Why Mantine Window stands out 
Mantine Window wraps advanced interaction patterns in a straightforward API that feels native to Mantine. You get smooth dragging, resizing, collapsing, close controls, configurable shadows and radii, and a smart persistence layer—without reinventing the wheel.
If you already use Mantine components and theming, this slots in effortlessly. Start here: Mantine Window and explore more extensions on the community Mantine Extensions HUB: mantine-extensions.vercel.app ↗.
Quick start 
Install and import styles at your app root:
import '@gfazioli/mantine-window/styles.css';
// or scoped layer support:
import '@gfazioli/mantine-window/styles.layer.css';
Then drop a window into any container:
import { Window } from '@gfazioli/mantine-window';
import { Box, Title } from '@mantine/core';
export function Demo() {
return (
<Box pos="relative" style={{ width: '100%', height: 500 }}>
<Window
title="Hello, Mantine Window"
defaultPosition={{ x: 0, y: 0 }}
defaultSize={{ width: 320, height: 256 }}
withinPortal={false}
opened
>
<Title order={4}>This is a window with data</Title>
</Window>
</Box>
);
}
Portal vs. container: control positioning 
Choose exactly how windows behave:
Fixed via portal:
withinPortal={true}keeps the window pinned to the viewport—ideal for overlays and modals that ignore scroll.Relative within a container:
withinPortal={false}uses absolute positioning inside a position: relativeparent—great for embedded widgets and constrained canvases.
Fully controlled or fire‑and‑forget 
Drive visibility with opened and onClose for modal‑style flows, or keep it simple using defaultPosition and defaultSize. It’s React‑friendly either way.
const [opened, { open, close }] = useDisclosure(false);
<Window title="Controlled Window" opened={opened} onClose={close} withinPortal={false} />
Precision movement: drag boundaries 
Lock window movement to specific ranges using dragBounds so your UI stays tidy and intentional—for example, dashboards with hard limits:
dragBounds={{ minX: 50, maxX: 500, minY: 50, maxY: 400 }}
Persistence that delights
With persistState (enabled by default), position and size are remembered via localStorage. Refresh the page, and your layout feels personal—not fragile.
Add an id for multiple distinct windows:
<Window id="analytics-panel" persistState defaultPosition={{ x: 50, y: 50 }} />
Callbacks for analytics and UX 
React to user intent with onPositionChange and onSizeChange. Log telemetry, snap to a grid, or update layout state in real time:
onPositionChange={(pos) => console.log(pos)}
onSizeChange={(size) => console.log(size)}
Lock it down when needed 
Create a centered, fixed window and disable interactions:
draggable="none"
resizable="none"Supply
defaultPositionand defaultSizefor a crisp, modal‑like panel.
You can also disable collapsing entirely with collapsable={false} for deterministic flows.
Styles API: theme it like Mantine 
Mantine Window embraces Mantine’s Styles API, letting you style inner parts with classNames and your theme tokens. It plays nicely with color schemes, radius, shadows, borders, and any design system rules you enforce through MantineProvider.
Perfect use cases 
Analytics dashboards with movable panels
Admin tools with modular widgets
In‑app editors and inspectors
Multi‑window experiences with persistence
Demo environments that need windowed layouts
Why teams adopt Mantine Window 
It’s familiar: Component props and patterns mirror Mantine conventions.
It’s robust: Drag/resizing, boundaries, persistence, and callbacks cover real production needs.
It’s flexible: Portal vs container makes the right placement trivial.
It’s maintainable: The Styles API keeps design aligned across your system.
If you’re building with Mantine, Mantine Window adds the missing desktop‑style interactions your users subconsciously expect—clean, predictable, and delightful. Dive into Mantine first at https://mantine.dev/getting-started/ ↗ and browse more community‑maintained gems at the Mantine Extensions HUB: https://mantine-extensions.vercel.app/ ↗.

Top comments (0)