Top Related Projects
🖱 A resizable and draggable component for React.
A draggable and resizable grid layout with responsive breakpoints, for React.
A simple React component that is resizable with a handle.
Drag and Drop for React
Moveable! Draggable! Resizable! Scalable! Rotatable! Warpable! Pinchable! Groupable! Snappable!
Quick Overview
React Resizable Panels is a React component library that enables the creation of resizable panel layouts. It provides a flexible and customizable way to build split-view interfaces with draggable dividers, allowing users to adjust panel sizes dynamically.
Pros
- Lightweight and performant, with minimal dependencies
- Supports both horizontal and vertical layouts
- Offers keyboard accessibility and screen reader support
- Provides smooth animations and touch device compatibility
Cons
- Limited to React applications only
- Requires some setup and configuration for complex layouts
- May have a learning curve for developers new to React or panel-based layouts
- Documentation could be more comprehensive for advanced use cases
Code Examples
- Basic horizontal layout:
import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels";
function App() {
return (
<PanelGroup direction="horizontal">
<Panel>Left panel</Panel>
<PanelResizeHandle />
<Panel>Right panel</Panel>
</PanelGroup>
);
}
- Vertical layout with multiple panels:
<PanelGroup direction="vertical">
<Panel>Top panel</Panel>
<PanelResizeHandle />
<Panel>Middle panel</Panel>
<PanelResizeHandle />
<Panel>Bottom panel</Panel>
</PanelGroup>
- Using imperative handle to control panel size:
function App() {
const panelRef = useRef(null);
const handleResize = () => {
panelRef.current?.resize(50);
};
return (
<PanelGroup>
<Panel ref={panelRef}>Resizable panel</Panel>
<PanelResizeHandle />
<Panel>Fixed panel</Panel>
<button onClick={handleResize}>Resize to 50%</button>
</PanelGroup>
);
}
Getting Started
-
Install the package:
npm install react-resizable-panels
-
Import and use the components in your React application:
import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels"; function App() { return ( <PanelGroup direction="horizontal"> <Panel minSize={20}>Left panel</Panel> <PanelResizeHandle /> <Panel minSize={30}>Right panel</Panel> </PanelGroup> ); }
-
Style the components as needed using CSS or the provided
className
props.
Competitor Comparisons
🖱 A resizable and draggable component for React.
Pros of react-rnd
- More flexible: Allows both resizing and dragging of components
- Supports touch devices and multiple resize handles
- Offers more customization options for resize and drag behavior
Cons of react-rnd
- Larger bundle size due to additional features
- May have a steeper learning curve for basic resizing tasks
- Less focused on performance optimizations for resizing operations
Code Comparison
react-rnd:
<Rnd
size={{ width: 200, height: 200 }}
position={{ x: 0, y: 0 }}
onDragStop={(e, d) => { /* Handle drag */ }}
onResizeStop={(e, direction, ref, delta, position) => { /* Handle resize */ }}
>
Content
</Rnd>
react-resizable-panels:
<PanelGroup direction="horizontal">
<Panel defaultSize={20}>
Left panel
</Panel>
<PanelResizeHandle />
<Panel>
Right panel
</Panel>
</PanelGroup>
react-rnd offers more flexibility with dragging and resizing, while react-resizable-panels focuses on a simpler, performance-oriented approach for creating resizable layouts. The choice between the two depends on the specific requirements of your project, such as the need for draggable components or the importance of optimized resizing performance.
A draggable and resizable grid layout with responsive breakpoints, for React.
Pros of react-grid-layout
- More feature-rich with built-in grid system and draggable elements
- Supports responsive layouts out of the box
- Offers a wider range of customization options for grid items
Cons of react-grid-layout
- Steeper learning curve due to more complex API
- Heavier bundle size, which may impact performance for simpler use cases
- Less focused on resizable panels, as it's a more general-purpose grid system
Code Comparison
react-grid-layout:
import GridLayout from 'react-grid-layout';
<GridLayout className="layout" layout={layout} cols={12} rowHeight={30} width={1200}>
<div key="a">a</div>
<div key="b">b</div>
<div key="c">c</div>
</GridLayout>
react-resizable-panels:
import { Panel, PanelGroup, PanelResizeHandle } from 'react-resizable-panels';
<PanelGroup direction="horizontal">
<Panel>Left panel</Panel>
<PanelResizeHandle />
<Panel>Right panel</Panel>
</PanelGroup>
react-resizable-panels focuses specifically on resizable panels with a simpler API, while react-grid-layout provides a more comprehensive grid system with additional features like draggable elements and responsive layouts. The choice between the two depends on the specific requirements of your project and the level of complexity you need.
A simple React component that is resizable with a handle.
Pros of react-resizable
- More mature and widely adopted, with a larger community and ecosystem
- Offers a complete grid layout system, not just resizable panels
- Supports both vertical and horizontal resizing out of the box
Cons of react-resizable
- Heavier and more complex, which may impact performance for simpler use cases
- Less focused on accessibility features compared to react-resizable-panels
- May require more setup and configuration for basic resizing functionality
Code Comparison
react-resizable:
import { Resizable } from 'react-resizable';
<Resizable width={200} height={200} onResize={this.onResize}>
<div className="box">Contents</div>
</Resizable>
react-resizable-panels:
import { Panel, PanelGroup, PanelResizeHandle } from 'react-resizable-panels';
<PanelGroup direction="horizontal">
<Panel>Left panel</Panel>
<PanelResizeHandle />
<Panel>Right panel</Panel>
</PanelGroup>
The code comparison shows that react-resizable-panels offers a more declarative API with dedicated components for panels and resize handles, while react-resizable provides a wrapper component with resize functionality. react-resizable-panels' approach may be more intuitive for creating complex layouts with multiple resizable panels.
Drag and Drop for React
Pros of react-dnd
- More versatile, supporting a wide range of drag-and-drop interactions beyond just resizing panels
- Extensive ecosystem with additional utilities and extensions
- Well-established project with a large community and long-term support
Cons of react-dnd
- Steeper learning curve due to its more complex API and concepts
- Potentially overkill for simple resizing tasks, leading to unnecessary overhead
- Requires more setup and configuration for basic functionality
Code Comparison
react-dnd:
import { useDrag, useDrop } from 'react-dnd';
function DraggableItem() {
const [{ isDragging }, drag] = useDrag(() => ({
type: 'ITEM',
collect: (monitor) => ({
isDragging: !!monitor.isDragging(),
}),
}));
return <div ref={drag}>Drag me</div>;
}
react-resizable-panels:
import { Panel, PanelGroup, PanelResizeHandle } from 'react-resizable-panels';
function ResizablePanels() {
return (
<PanelGroup direction="horizontal">
<Panel>Left panel</Panel>
<PanelResizeHandle />
<Panel>Right panel</Panel>
</PanelGroup>
);
}
The code comparison shows that react-resizable-panels offers a more straightforward API for creating resizable panels, while react-dnd requires more setup but provides greater flexibility for complex drag-and-drop interactions.
Moveable! Draggable! Resizable! Scalable! Rotatable! Warpable! Pinchable! Groupable! Snappable!
Pros of Moveable
- More versatile: Supports resizing, dragging, rotating, and other transformations
- Framework-agnostic: Can be used with various JavaScript frameworks or vanilla JS
- Extensive customization options and event handling
Cons of Moveable
- Steeper learning curve due to its extensive feature set
- Potentially heavier in terms of bundle size and performance impact
- May require more setup and configuration for simple resizing tasks
Code Comparison
Moveable:
import Moveable from "moveable";
const moveable = new Moveable(document.body, {
target: document.querySelector(".target"),
draggable: true,
resizable: true,
});
moveable.on("drag", ({ target, transform }) => {
target.style.transform = transform;
});
React-resizable-panels:
import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels";
<PanelGroup direction="horizontal">
<Panel>Left panel</Panel>
<PanelResizeHandle />
<Panel>Right panel</Panel>
</PanelGroup>
Summary
Moveable offers a more comprehensive set of features for element manipulation, making it suitable for complex use cases across different frameworks. React-resizable-panels, on the other hand, provides a simpler, React-specific solution focused primarily on resizable panels. The choice between the two depends on the specific requirements of your project, desired level of customization, and the framework you're using.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
react-resizable-panels
React components for resizable panel groups/layouts.
Supported input methods include mouse, touch, and keyboard (via Window Splitter).
If you like this project, ð become a sponsor or â buy me a coffee
FAQ
Can panel sizes be specified in pixels?
No. Pixel-based constraints added significant complexity to the initialization and validation logic and so I've decided not to support them. You may be able to implement a version of this yourself following a pattern like this but it is not officially supported by this library.
How can I fix layout/sizing problems with conditionally rendered panels?
The Panel
API doesn't require id
and order
props because they aren't necessary for static layouts. When panels are conditionally rendered though, it's best to supply these values.
<PanelGroup direction="horizontal">
{renderSideBar && (
<>
<Panel id="sidebar" minSize={25} order={1}>
<Sidebar />
</Panel>
<PanelResizeHandle />
</>
)}
<Panel minSize={25} order={2}>
<Main />
</Panel>
</PanelGroup>
Can a attach a ref to the DOM elements?
No. I think exposing two refs (one for the component's imperative API and one for a DOM element) would be awkward. This library does export several utility methods for accessing the underlying DOM elements though. For example:
import {
getPanelElement,
getPanelGroupElement,
getResizeHandleElement,
Panel,
PanelGroup,
PanelResizeHandle,
} from "react-resizable-panels";
export function Example() {
const refs = useRef();
useEffect(() => {
const groupElement = getPanelGroupElement("group");
const leftPanelElement = getPanelElement("left-panel");
const rightPanelElement = getPanelElement("right-panel");
const resizeHandleElement = getResizeHandleElement("resize-handle");
// If you want to, you can store them in a ref to pass around
refs.current = {
groupElement,
leftPanelElement,
rightPanelElement,
resizeHandleElement,
};
}, []);
return (
<PanelGroup direction="horizontal" id="group">
<Panel id="left-panel">{/* ... */}</Panel>
<PanelResizeHandle id="resize-handle" />
<Panel id="right-panel">{/* ... */}</Panel>
</PanelGroup>
);
}
Why don't I see any resize UI?
This likely means that you haven't applied any CSS to style the resize handles. By default, a resize handle is just an empty DOM element. To add styling, use the className
or style
props:
// Tailwind example
<PanelResizeHandle className="w-2 bg-blue-800" />
How can I use persistent layouts with SSR?
By default, this library uses localStorage
to persist layouts. With server rendering, this can cause a flicker when the default layout (rendered on the server) is replaced with the persisted layout (in localStorage
). The way to avoid this flicker is to also persist the layout with a cookie like so:
Server component
import ResizablePanels from "@/app/ResizablePanels";
import { cookies } from "next/headers";
export function ServerComponent() {
const layout = cookies().get("react-resizable-panels:layout");
let defaultLayout;
if (layout) {
defaultLayout = JSON.parse(layout.value);
}
return <ClientComponent defaultLayout={defaultLayout} />;
}
Client component
"use client";
import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels";
export function ClientComponent({
defaultLayout = [33, 67],
}: {
defaultLayout: number[] | undefined;
}) {
const onLayout = (sizes: number[]) => {
document.cookie = `react-resizable-panels:layout=${JSON.stringify(sizes)}`;
};
return (
<PanelGroup direction="horizontal" onLayout={onLayout}>
<Panel defaultSize={defaultLayout[0]}>{/* ... */}</Panel>
<PanelResizeHandle className="w-2 bg-blue-800" />
<Panel defaultSize={defaultLayout[1]}>{/* ... */}</Panel>
</PanelGroup>
);
}
[!NOTE] Be sure to specify a
defaultSize
prop for everyPanel
component to avoid layout flicker.
A demo of this is available here.
How can I set the CSP "nonce"
attribute?
import { setNonce } from "react-resizable-panels";
setNonce("your-nonce-value-here");
How can I disable global cursor styles?
import { disableGlobalCursorStyles } from "react-resizable-panels";
disableGlobalCursorStyles();
Top Related Projects
🖱 A resizable and draggable component for React.
A draggable and resizable grid layout with responsive breakpoints, for React.
A simple React component that is resizable with a handle.
Drag and Drop for React
Moveable! Draggable! Resizable! Scalable! Rotatable! Warpable! Pinchable! Groupable! Snappable!
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot