4.0.0
Version 4 of react-resizable-panels offers more flexible size constraints– supporting units as pixels, percentages, REMs/EMs, and more. Support for server-rendering (including Server Components) has also been expanded.
Migrating from version 3 to 4
Refer to the docs for a complete list of props and API methods. Below are some examples of migrating from version 3 to 4, but first a couple of potential questions:
- Q: Why'd you rename <component> or <prop>?
- A: The most likely reason is that I think the new name more closely aligns with web standards like WAI-ARIA and CSS. For example, the
PanelResizeHandlecomponent was renamed toSeparatorto better align with the ARIA "separator" role and thedirectionprop was renamed toorientationto better align with the ARIAorientationattribute . - Q: Why'd you remove support for <feature>?
- A: Probably because it wasn't used widely enough to justify the complexity required to maintain it. If it turns out that I'm mistaken, features can always be (re)added but it's more difficult to remove them.
- Q: Were the
onCollapseandonExpandevent handlers removed? - A: Yes. Use the
onResizeevent handler instead:onResize={(size) => { // Either this const isCollapsed = size === collapsedSize; // Or this: panelRef.isCollapsed(); }}
Basic usage example
// Version 3
import { PanelGroup, Panel, PanelResizeHandle } from "react-resizable-panels";
<PanelGroup direction="horizontal">
<Panel defaultSize={30} minSize={20}>left</Panel>
<PanelResizeHandle />
<Panel defaultSize={30} minSize={20}>right</Panel>
</PanelGroup>
// Version 4
import { Group, Panel, Separator } from "react-resizable-panels";
<Group orientation="horizontal">
<Panel defaultSize={30} minSize={20}>left</Panel>
<Separator />
<Panel defaultSize={30} minSize={20}>right</Panel>
</Group>Persistent layouts using localStorage
// Version 3
import { PanelGroup, Panel, PanelResizeHandle } from "react-resizable-panels";
<PanelGroup autoSaveId="unique-group-id" direction="horizontal">
<Panel>left</Panel>
<PanelResizeHandle />
<Panel>right</Panel>
</PanelGroup>
// Version 4
import { Group, Panel, Separator, useDefaultLayout } from "react-resizable-panels";
const { defaultLayout, onLayoutChange } = useDefaultLayout({
groupId: "unique-group-id",
storage: localStorage
});
<Group defaultLayout={defaultLayout} onLayoutChange={onLayoutChange}>
<Panel>left</Panel>
<Separator />
<Panel>right</Panel>
</Group>Note
Refer to the docs for examples of persistent layouts with server rendering and server components.
Conditional panels
// Version 3
import { PanelGroup, Panel, PanelResizeHandle } from "react-resizable-panels";
<PanelGroup autoSaveId="unique-group-id" direction="horizontal">
{showLeftPanel && (
<>
<Panel id="left" order={1}>left</Panel>
<PanelResizeHandle />
</>
)}
<Panel id="center" order={2}>center</Panel>
{showRightPanel && (
<>
<PanelResizeHandle />
<Panel id="right" order={3}>right</Panel>
</>
)}
</PanelGroup>
// Version 4
import { Group, Panel, Separator } from "react-resizable-panels";
<Group>
{showLeftPanel && (
<>
<Panel id="left">left</Panel>
<Separator />
</>
)}
<Panel id="center">center</Panel>
{showRightPanel && (
<>
<Separator />
<Panel id="right">right</Panel>
</>
)}
</Group>Imperative APIs
// Version 3
import { PanelGroup, Panel, PanelResizeHandle } from "react-resizable-panels";
import type { ImperativePanelGroupHandle, ImperativePanelHandle }from "react-resizable-panels";
const panelRef = useRef<ImperativePanelHandle>(null);
const panelGroupRef = useRef<ImperativePanelGroupHandle>(null);
<PanelGroup direction="horizontal" ref={panelGroupRef}>
<Panel ref={panelRef}>left</Panel>
<PanelResizeHandle />
<Panel>right</Panel>
</PanelGroup>
// Version 4
import { Group, Panel, Separator, useGroupRef, usePanelRef } from "react-resizable-panels";
const groupRef = useGroupRef();
const panelRef = usePanelRef();
<Group groupRef={groupRef} orientation="horizontal">
<Panel panelRef={panelRef}>left</Panel>
<Separator />
<Panel>right</Panel>
</Group>