React Mosaic Component
React Mosaic is a robust tiling window manager for React applications, enabling developers to create complex, customizable split-pane layouts. It provides a declarative API for defining and managing workspace configurations, supporting dynamic resizing, reordering, and adding/removing of individual panes. The package's current stable release series is 6.x (latest 6.1.1), while a significant beta release, 7.0.0-beta0, introduces a new n-ary tree structure and updated type system for React 19 compatibility. React Mosaic differentiates itself by offering deep programmatic control over the layout tree, making it ideal for applications requiring highly flexible and user-definable interfaces, such as IDEs or dashboards. It ships with comprehensive TypeScript types and supports React versions 16 through 19 as a peer dependency.
Common errors
-
TypeError: Cannot read properties of undefined (reading 'first') or (reading 'second')
cause Attempting to use a legacy binary tree layout object with react-mosaic-component v7.0.0-beta0, which expects an n-ary tree structure.fixConvert your layout definition to the new n-ary format using `{ children: [node, node, ...] }` or use the `convertLegacyToNary()` utility for automatic migration. -
Error: Could not find the drag and drop manager. Either make sure you've wrapped your top-level component with 'DndProvider', or make sure your 'dragAndDropManager' is a valid instance.
cause Mismatch between the `react-dnd` version used by your application and the version expected by `react-mosaic-component`, or missing `DndProvider` wrapper.fixEnsure `react-dnd` is installed and resolved to a compatible version (e.g., `^16` for `react-mosaic-component` v6.x). Wrap your root component, or at least the `Mosaic` component, with `<DndProvider manager={HTML5Backend}>`. -
TS2345: Argument of type '{ first: ... }' is not assignable to parameter of type 'MosaicParent<T>'. Property 'children' is missing in type '{ first: ... }'.cause Trying to use a v6.x (binary) `MosaicNode` type or object literal with v7.x type definitions.fixUpdate your `MosaicNode` type definitions and layout objects to conform to the n-ary tree structure (`{ direction: 'row' | 'column', children: MosaicNode<T>[] }`) required by v7.x. Alternatively, ensure you are using compatible library versions.
Warnings
- breaking The internal tree structure for defining layouts changed from a binary tree (`{ first: node, second: node }`) to an n-ary tree (`{ children: [node, node, ...] }`) in v7.0.0-beta0. Existing layouts defined with the old format will not render correctly.
- breaking Type definitions for JSX elements were updated in v7.0.0-beta0 to support React 19. Projects using older React versions with v7 types may encounter compatibility issues.
- breaking Version 6.0.0 upgraded `react-dnd` to `^16`. Incompatible versions of `react-dnd` as a direct or transitive dependency can lead to runtime errors or broken drag-and-drop functionality.
- breaking Version 5.0.0 removed all direct Blueprint UI library dependencies, making it optionally cross-platform. This change alters the rendered DOM structure and may break existing CSS styles or Blueprint-specific integrations.
- gotcha Older versions of npm (pre-7) might not automatically install peer dependencies, leading to runtime errors if `react` (and `react-dnd` indirectly) are not explicitly installed.
Install
-
npm install react-mosaic-component -
yarn add react-mosaic-component -
pnpm add react-mosaic-component
Imports
- Mosaic
import Mosaic from 'react-mosaic-component';
import { Mosaic } from 'react-mosaic-component'; - MosaicWindow
import { MosaicWindow } from 'react-mosaic-component'; - MosaicNode
import { MosaicNode } from 'react-mosaic-component';import type { MosaicNode } from 'react-mosaic-component'; - convertLegacyToNary
import { convertLegacyToNary } from 'react-mosaic-component';
Quickstart
import React, { useState } from 'react';
import { Mosaic, MosaicWindow, getpathFromNode, createBalancedTreeFromElement, MosaicParent, MosaicBranch } from 'react-mosaic-component';
import 'react-mosaic-component/src/example/index.css'; // Minimal example styles
type MyMosaicKey = 'a' | 'b' | 'c' | 'd';
const ELEMENT_MAP: Record<MyMosaicKey, JSX.Element> = {
a: <div>Panel A Content</div>,
b: <div>Panel B Content</div>,
c: <div>Panel C Content</div>,
d: <div>Panel D Content</div>,
};
const createInitialLayout = () => {
// In v7.0.0-beta0, the tree structure is n-ary:
return {
direction: 'row',
children: [
'a',
{ direction: 'column', children: ['b', 'c'] },
'd'
]
} satisfies MosaicParent<MyMosaicKey>;
// For v6.x and earlier, use the binary tree format:
// return { direction: 'row', first: 'a', second: { direction: 'column', first: 'b', second: 'c' } } as MosaicParent<MyMosaicKey>;
};
export default function MyMosaicApp() {
const [currentLayout, setCurrentLayout] = useState<MosaicNode<MyMosaicKey>>(() => createInitialLayout());
const renderTile = (id: MyMosaicKey, path: MosaicBranch[]) => (
<MosaicWindow<MyMosaicKey> path={path} createNode={() => 'new'} title={`Window ${id}`}>
{ELEMENT_MAP[id]}
</MosaicWindow>
);
return (
<div style={{ width: '100vw', height: '100vh', display: 'flex' }}>
<Mosaic<MyMosaicKey>
renderTile={renderTile}
initialValue={currentLayout}
onChange={setCurrentLayout}
zeroStateView={<div>Drag a new window here</div>}
/>
</div>
);
}