Skip to content

maomaolabs/core

Repository files navigation

@maomaolabs/core β€” Desktop Window Management for the Web

@maomaolabs/core

A standalone, lightweight React library that brings a complete desktop window management experience to the web.
Drag, resize, snap, minimize, maximize β€” all performant and mobile-ready out of the box.

NPM Version License Changelog React 18+


✨ Features

⚑ Zero unnecessary re-renders

Context is split into useWindows (state) and useWindowActions (actions). Components that only dispatch actions never re-render on state changes.

Performance architecture

πŸͺŸ Complete window lifecycle

Open, close, minimize, maximize, drag and resize windows with native-feeling interactions on both desktop and mobile.

Window lifecycle

🧲 Built-in snapping

Half-screen (edge) and quarter-screen (corner) snapping with real-time preview overlays, just like a native OS.

Window snapping

🧰 Out-of-the-box Toolbar

A fully customizable taskbar that handles individual app launchers, folder groupings, and minimized window management.

Toolbar

πŸ“± Responsive by default

Interactions automatically adapt between mouse and touch environments. No configuration needed.

Responsive design

πŸ“¦ Installation

npm install @maomaolabs/core
# or
yarn add @maomaolabs/core
# or
pnpm add @maomaolabs/core

Requires react and react-dom >= 18.0.0 as peer dependencies.


πŸš€ Quick Start

import { WindowSystemProvider, WindowManager, useWindowActions } from '@maomaolabs/core';
import '@maomaolabs/core/dist/style.css';

const AppLauncher = () => {
  const { openWindow } = useWindowActions();

  return (
    <button onClick={() => openWindow({
      id: 'hello',
      title: 'Hello World',
      component: <div>Hello from a managed window!</div>
    })}>
      Launch App
    </button>
  );
};

export default function App() {
  return (
    <WindowSystemProvider>
      <WindowManager />
      <AppLauncher />
    </WindowSystemProvider>
  );
}

⚠️ Don't forget the CSS import β€” it's required for drag, resize, and snap overlays to work correctly.


πŸ“– Usage Guide

With Toolbar

The Toolbar component provides a ready-made taskbar with app launchers, folder support, and minimized window restoration.

Toolbar integration

import { WindowSystemProvider, WindowManager, Toolbar } from '@maomaolabs/core';

const DESKTOP_ITEMS = [
  {
    id: 'browser',
    title: 'Browser',
    component: <div />,
    initialSize: { width: 800, height: 600 }
  },
  {
    id: 'games-folder',
    title: 'Games',
    apps: [
      { id: 'minesweeper', title: 'Minesweeper', component: <div /> }
    ]
  }
];

export default function Desktop() {
  return (
    <WindowSystemProvider>
      <WindowManager />
      <Toolbar toolbarItems={DESKTOP_ITEMS} showLogo={true} />
    </WindowSystemProvider>
  );
}

Accessing Window State

Use useWindows when you need to render UI based on open windows (e.g., a custom taskbar or badge counter).

Window state access

⚠️ Warning: useWindows triggers a re-render on every window state change (drag, resize, focus). Only use it where necessary.

import { useWindows } from '@maomaolabs/core';

const OpenAppCounter = () => {
  const windows = useWindows();
  return <div>Active windows: {windows.length}</div>;
};

πŸ“š API Reference

Components

Component Description Props
WindowSystemProvider Root context provider. Wrap your entire app with this. children: ReactNode, systemStyle?: SystemStyle
WindowManager Renders all active windows and snap preview overlays. β€”
Toolbar Taskbar with app launchers and folder support. toolbarItems: ToolbarItem[], showLogo?: boolean

Hooks

useWindowActions()

Returns window manipulation methods. Does not subscribe to window state β€” safe to call anywhere without performance concerns.

Method Signature Description
openWindow (window: WindowDefinition) => void Opens a new window, or focuses it if already open.
closeWindow (id: string) => void Destroys a window instance.
focusWindow (id: string) => void Brings a window to the top of the z-index stack.
updateWindow (id: string, data: Partial<WindowInstance>) => void Patches an existing window's state.

useWindows()

Returns WindowInstance[] β€” the list of all currently active windows. Re-renders on every state change.

useWindowSnap()

Returns { snapPreview, setSnapPreview } for reading and controlling the active snap preview overlay.


Interfaces

WindowDefinition

Property Type Required Description
id string βœ… Unique identifier for the window.
title string βœ… Text shown in the window title bar.
component ReactNode βœ… Content rendered inside the window.
icon ReactNode β€” Icon shown in the title bar and toolbar.
initialSize { width: number; height: number } β€” Starting dimensions in pixels.
initialPosition { x: number; y: number } β€” Starting coordinates in pixels.
layer 'base' | 'normal' | 'alwaysOnTop' | 'modal' β€” Z-index render layer.
isMaximized boolean β€” Spawns the window in maximized state.
canMinimize boolean β€” Shows the minimize control.
canMaximize boolean β€” Shows the maximize/restore control.
canClose boolean β€” Shows the close control.
className string β€” Inject custom CSS classes directly into the window container.
style React.CSSProperties β€” Inject inline styles overriding or extending window container styles.

FolderDefinition

Property Type Required Description
id string βœ… Unique identifier for the folder.
title string βœ… Folder display name.
apps WindowDefinition[] βœ… Windows grouped inside this folder.
icon ReactNode β€” Optional visual icon.

ToolbarItem = WindowDefinition | FolderDefinition

WindowStyling

Exported type available for reuse in your own components:

import type { WindowStyling } from '@maomaolabs/core';
// { className?: string; style?: React.CSSProperties }

βš™οΈ Styling

The library requires a single CSS import to function correctly:

import '@maomaolabs/core/dist/style.css';

Ensure your bundler (Vite, Webpack, etc.) is configured to process CSS from node_modules.

Theming System (systemStyle)

The context provider accepts a systemStyle prop that governs the aesthetics of the entire rendered window manager system:

<WindowSystemProvider systemStyle="aero">

Pre-bundled themes include:

  • default
  • traffic (colored dot buttons concept)
  • linux (modern dark/light gradient adaptation)
  • yk2000 (classic 90s/00s retro styling)
  • aero (translucent glass blurring)

Note on Custom Themes: SystemStyle strictly autocompletes the pre-built themes above, but mathematically permits any string to be passed via Type relaxation. You can pass your own systemStyle="my-custom-theme" alongside injected custom CSS.

Custom Theme Injection

You can define your own theme by creating a CSS file that targets the data-system-style attribute.

⚠️ Use standard CSS attribute selectors β€” avoid :global() unless your bundler explicitly supports it (e.g. CSS Modules with PostCSS).

/* my-custom-theme.css */
[data-system-style="my-custom-theme"] .window-header {
  background: #1a1a2e;
  color: #e0e0e0;
}

[data-system-style="my-custom-theme"] .window-controls {
  gap: 6px;
}

Import the CSS file anywhere in your app (e.g. src/index.tsx) before the provider renders:

import './my-custom-theme.css';

Then pass the identifier to the provider:

<WindowSystemProvider systemStyle="my-custom-theme">
  {/* ... */}
</WindowSystemProvider>

Available CSS selectors

The following global class names are always present on the window DOM and safe to target in your theme:

Selector Element
.window-container Root window wrapper
.window-header Title bar (drag area)
.window-title Title text container
.window-icon Icon inside the title bar
.window-controls Button group (minimize / maximize / close)
.terminal-btn Generic control button
.window-scrollbar Scrollable content area
.window-resize-handle Bottom-right resize grip

You can also target individual buttons via the data-action attribute:

[data-system-style="my-custom-theme"] [data-action="close"] { background: red; }
[data-system-style="my-custom-theme"] [data-action="maximize"] { background: green; }
[data-system-style="my-custom-theme"] [data-action="minimize"] { background: yellow; }

Per-window inline overrides

Custom className and style props are accepted on each individual window definition via openWindow(), allowing per-instance overrides on top of the global theme:

openWindow({
  id: 'my-app',
  title: 'My App',
  component: <div />,
  className: 'my-extra-class',
  style: { borderRadius: '16px', border: '1px solid #444' },
});

These are merged after the global theme styles, so they always take precedence.


🀝 Contributing

npm install       # Install dependencies
npm run dev       # Start dev server with hot reload
npm run test      # Run test suite (Vitest)

PRs are welcome. Please ensure all tests pass before submitting.


πŸ“ License

MIT Β© MaoMao Labs

About

A lightweight, high-performance Window Manager context for React. Features 60FPS physics, headless architecture, and zero-lag drag & drop.

Resources

License

Stars

Watchers

Forks

Packages