Back to Blog

react-resizable-panels: Full Code Guide (2026)

Complete react-resizable-panels guide with copy-paste code: PanelGroup, drag handles, collapse, localStorage persistence and TypeScript types. Fix common errors fast.

Viprasol Tech Team
14 min read
Updated 2026

react-resizable-panels: PanelOnCollapse, Drag Handles & Examples (2026)

Quick answer. react-resizable-panels is the standard React library for building resizable, draggable layouts. It provides three components โ€” PanelGroup (the container), Panel (each resizable region), and PanelResizeHandle (the drag handle) โ€” plus an onCollapse/onExpand API and built-in localStorage persistence so panel sizes survive reloads. It is SSR-safe and works cleanly in Next.js.

What is react-resizable-panels?

react-resizable-panels is the 2026 standard React library for resizable layouts. It provides three components: <PanelGroup> (container), <Panel> (each resizable region), and <PanelResizeHandle> (drag handle between panels). Layout sizes persist to localStorage via the autoSaveId prop. Authored by Brian Vaughn (React DevTools author), 12 kB gzipped, supports React 18 and 19.

npm install react-resizable-panels
import { Panel, PanelGroup, PanelResizeHandle } from 'react-resizable-panels';

<PanelGroup direction="horizontal" autoSaveId="example">
  <Panel defaultSize={25} minSize={15}><Sidebar /></Panel>
  <PanelResizeHandle />
  <Panel defaultSize={75}><MainContent /></Panel>
</PanelGroup>

Official package: npmjs.com/package/react-resizable-panels.


TL;DR. react-resizable-panels (npm package by Brian Vaughn, author of React DevTools) is the 2026 standard for resizable layouts in React. The three core types you need: <PanelGroup> (the container), <Panel> (each resizable area), and <PanelResizeHandle> (the drag handle between panels). Key callbacks: onCollapse: PanelOnCollapse fires when a panel collapses to its minimum, and onResize fires on every drag. Layout state can be persisted to localStorage via the autoSaveId prop. Below: working code, TypeScript types for PanelOnCollapse, the PanelResizeHandle API, and the patterns the npm docs skip.

Resizable panels are a staple of developer tools, IDE-style interfaces, and data dashboards. Users expect to drag a handle to resize the sidebar, collapse a panel to maximise working space, and have the layout persisted across sessions. react-resizable-panels handles keyboard navigation, accessibility (ARIA live announcements), SSR, and persistence out of the box. The repo is at github.com/bvaughn/react-resizable-panels. This guide covers the working patterns: sidebar + main content, horizontal/vertical splits, collapsible panels, the PanelOnCollapse and onResize callbacks, the PanelResizeHandle API, TypeScript types, and localStorage persistence.


Installation

```bash npm install react-resizable-panels ```

As of May 2026: latest is react-resizable-panels ^3.0.x, supports React 18 and 19. Peer dependency: React โ‰ฅ 16.14. SSR-safe.


๐ŸŒ Looking for a Dev Team That Actually Delivers?

Most agencies sell you a project manager and assign juniors. Viprasol is different โ€” senior engineers only, direct Slack access, and a 5.0โ˜… Upwork record across 1000+ projects.

  • React, Next.js, Node.js, TypeScript โ€” production-grade stack
  • Fixed-price contracts โ€” no surprise invoices
  • Full source code ownership from day one
  • 90-day post-launch support included

Basic Example: Horizontal Split

```tsx import { Panel, PanelGroup, PanelResizeHandle } from 'react-resizable-panels';

export function SplitPane() { return ( ); } ```

Three components, total. direction="horizontal" for side-by-side, "vertical" for stacked. autoSaveId persists the size ratios to localStorage automatically โ€” same key, same layout next visit.


PanelOnCollapse: TypeScript Type and Usage

The PanelOnCollapse callback fires once when a panel transitions from "visible" to "collapsed" (collapsed = size hits the collapsedSize or zero). Together with PanelOnExpand, it gives you both edges of the collapse state machine.

```ts // The exact exported type from react-resizable-panels export type PanelOnCollapse = () => void; export type PanelOnExpand = () => void; ```

Working example:

```tsx import { useState } from 'react'; import { Panel, PanelGroup, PanelResizeHandle, type ImperativePanelHandle } from 'react-resizable-panels'; import type { PanelOnCollapse, PanelOnExpand } from 'react-resizable-panels';

export function CollapsibleSidebar() { const [collapsed, setCollapsed] = useState(false);

const handleCollapse: PanelOnCollapse = () => setCollapsed(true); const handleExpand: PanelOnExpand = () => setCollapsed(false);

return ( {collapsed ? : } ); } ```

Key props:

  • collapsible โ€” enables the collapse behaviour (without it, panels stop at minSize)
  • collapsedSize โ€” the size when collapsed (default 0, set โ‰ฅ 1 if you want a "rail" UI)
  • onCollapse: PanelOnCollapse โ€” fires once at the moment of collapse
  • onExpand: PanelOnExpand โ€” fires once at the moment of expand
  • onResize: PanelOnResize โ€” fires on every drag, signature: (size: number, prevSize: number | undefined) => void

For "export type PanelOnCollapse" searches (devs looking at TypeScript declarations for v1.0.5 and beyond), the type signature is unchanged: a no-argument void function. The collapse event carries no payload โ€” use onResize for that.


react-resizable-panels - react-resizable-panels: Full Code Guide (2026)

๐Ÿš€ Senior Engineers. No Junior Handoffs. Ever.

You get the senior developer, not a project manager who relays your requirements to someone you never meet. Every Viprasol project has a senior lead from kickoff to launch.

  • MVPs in 4โ€“8 weeks, full platforms in 3โ€“5 months
  • Lighthouse 90+ performance scores standard
  • Works across US, UK, AU timezones
  • Free 30-min architecture review, no commitment

PanelResizeHandle API

<PanelResizeHandle> is the drag region between two panels. Always required between <Panel> components inside a <PanelGroup> โ€” without it, panels are static.

```tsx <PanelResizeHandle className="my-handle" hitAreaMargins={{ coarse: 15, fine: 5 }} onDragging={(isDragging) => { /* update cursor / overlay state */ }} /> ```

  • className โ€” full styling control. Tailwind, CSS modules, anything.
  • hitAreaMargins โ€” pixel padding around the visible handle for touch / fine-pointer accessibility. coarse for touch (default 15), fine for mouse (default 5).
  • onDragging โ€” boolean callback fires true on dragstart, false on dragend. Useful for overlay state or analytics.
  • disabled โ€” set to true to lock the handle.

Persistent Layout with localStorage

Pass autoSaveId on the <PanelGroup> to persist size ratios automatically:

```tsx ... ... ... ```

The library writes react-resizable-panels:ide-layout to localStorage whenever sizes change, and reads it on mount. Different autoSaveId per layout, same autoSaveId across pages = same restored state. The persistence is JSON-serialised arrays of sizes; safe to inspect and edit.

For SSR โ€” the library handles hydration. The initial render uses defaultSize; the client effect reads localStorage and updates. No flash if your defaults are close to the saved sizes; for pixel-perfect SSR, save the layout to a cookie and inject defaultSize from there.


Imperative Control: Refs for Programmatic Resize/Collapse

```tsx import { useRef } from 'react'; import { Panel, PanelGroup, PanelResizeHandle, type ImperativePanelHandle } from 'react-resizable-panels';

function ControlledExample() { const sidebarRef = useRef(null);

return ( <> <button onClick={() => sidebarRef.current?.collapse()}>Collapse <button onClick={() => sidebarRef.current?.expand()}>Expand <button onClick={() => sidebarRef.current?.resize(50)}>Resize to 50%

  <PanelGroup direction="horizontal">
    <Panel ref={sidebarRef} defaultSize={20} collapsible>
      <Sidebar />
    </Panel>
    <PanelResizeHandle />
    <Panel><MainContent /></Panel>
  </PanelGroup>
</>

); } ```

ImperativePanelHandle methods: collapse(), expand(), resize(size), getSize(), getId(), isCollapsed(), isExpanded(). Use for keyboard shortcuts (Cmd+B to toggle sidebar) or sync with external state.


Working Example: IDE-Style 3-Pane Layout

```tsx import { Panel, PanelGroup, PanelResizeHandle } from 'react-resizable-panels';

export function IDELayout() { return (

  <Panel>
    <PanelGroup direction="vertical">
      <Panel defaultSize={70} minSize={20}>
        <EditorPane />
      </Panel>
      <PanelResizeHandle className="h-px bg-gray-700 hover:bg-blue-500" />
      <Panel defaultSize={30} minSize={10} collapsible>
        <TerminalPane />
      </Panel>
    </PanelGroup>
  </Panel>

  <PanelResizeHandle className="w-px bg-gray-700 hover:bg-blue-500" />
  <Panel defaultSize={20} minSize={15} collapsible>
    <PreviewPane />
  </Panel>
</PanelGroup>

); } ```

Sidebar + editor / terminal stack + preview โ€” VS Code in 40 lines. Each region is independently collapsible. autoSaveId="ide" makes the entire layout persistent across reloads.


react-resizable-panels vs Alternatives (2026)

LibraryMaintainedBundle SizeTS TypesCollapse APIPersistenceNotes
react-resizable-panelsโœ… Active (Brian Vaughn)~12 kB gzipโœ… Excellentโœ… onCollapseโœ… Built-in autoSaveId2026 recommended pick
react-split-paneโš ๏ธ Stale (last 2021)~8 kBPartialโŒโŒLegacy; do not use
react-reflexโš ๏ธ Slow updates~14 kBโœ…ManualManualOlder API, harder a11y
allotment (VS Code-derived)โœ… Active~20 kBโœ…โœ…โœ…Heavier, more features
react-grid-layoutโœ… Active~50 kBโœ…โ€”โœ…For draggable grid, not splits

Use react-resizable-panels for resizable splits. Use allotment if you need the exact VS Code visual. Use react-grid-layout only if you need a free-form draggable grid (dashboard tiles).


Common Pitfalls

  1. Forgetting <PanelResizeHandle> between panels. No handle = static layout. Always exactly one handle between every two panels.
  2. collapsible without collapsedSize. Default collapsedSize is 0, which hides the panel entirely. Set collapsedSize={4} for a "rail" UI that's still visible.
  3. Layout flashes on SSR. Save the sizes to a cookie server-side and pass as defaultSize to avoid the post-hydration jump.
  4. onCollapse firing repeatedly. It only fires on the transition, not while collapsed. If you see repeated fires, check that you are not toggling the collapsible prop.
  5. Touch devices ignoring small handles. Set hitAreaMargins={{ coarse: 20 }} to give touch users a bigger drag region.
  6. Stale autoSaveId after refactor. When you change layout shape (number of panels), localStorage entries become stale. Either bump autoSaveId or read/clear the old key.

FAQ

What is PanelOnCollapse in react-resizable-panels?

PanelOnCollapse is the TypeScript type of the onCollapse callback on <Panel>. Its signature is () => void โ€” a no-argument void function that fires once when the panel transitions from "visible" to "collapsed." It works alongside PanelOnExpand, which fires on the reverse transition. Both are exported from the package so you can annotate handlers explicitly.

How do I install react-resizable-panels?

npm install react-resizable-panels. Import Panel, PanelGroup, and PanelResizeHandle. Wrap your layout in <PanelGroup direction="horizontal" | "vertical">. Each resizable region is a <Panel> with a <PanelResizeHandle> between every pair.

What is the type of PanelOnCollapse for react-resizable-panels 1.0.5+?

export type PanelOnCollapse = () => void; โ€” unchanged from 1.0.5 through 3.x. The collapse event carries no payload. For size-change events, use onResize (PanelOnResize = (size: number, prevSize: number | undefined) => void).

What does PanelResizeHandle do?

It is the draggable region between two panels in a <PanelGroup>. Without it, panels are static. Style it with className, control its hit area with hitAreaMargins, listen for drag start/end with onDragging. Always exactly one between each pair of panels.

How do I persist react-resizable-panels layout to localStorage?

Pass an autoSaveId prop to <PanelGroup>. The library serializes sizes to localStorage under react-resizable-panels:<autoSaveId> and restores on mount. No code required.

Is there a working JavaScript resizable dashboard layout example?

Yes โ€” for the IDE-style 3-pane dashboard pattern (file explorer + editor + preview), see the working example above. For free-form draggable dashboard tiles, use react-grid-layout instead.

Can I control react-resizable-panels imperatively?

Yes. Pass a ref to <Panel> of type ImperativePanelHandle, then call .collapse(), .expand(), .resize(n), .getSize(), .isCollapsed(), .isExpanded(). Useful for keyboard shortcuts and external state sync.


Partnering With Viprasol

We build production React UIs โ€” IDE-style developer tools, real-time trading dashboards, multi-tenant SaaS admin panels. When the panel layout has to feel native and persistent across thousands of users, we ship the pixel-perfect version, not the prototype.

โ†’ Talk to our team about React app development.


Continue Learning

react resizable panels: quick recap

To recap, react resizable panels (the react-resizable-panels library) gives you PanelGroup, Panel, and PanelResizeHandle to build resizable, persistent, SSR-safe layouts in React and Next.js.

Installing react-resizable-panels (npm)

Install the package from npm:

npm install react-resizable-panels

Then import PanelGroup, Panel and PanelResizeHandle. The three primitives compose into any resizable layout โ€” horizontal split views, IDE-style sidebars, or nested grids.

Using react-resizable-panels with shadcn/ui

The shadcn/ui Resizable component is a thin wrapper around react-resizable-panels โ€” so if you are building a shadcn sidebar resizable layout or a resizable sidebar in shadcn, you are already using this library under the hood. Add it with the shadcn CLI (the "resizable" component) and you get styled ResizablePanelGroup, ResizablePanel and ResizableHandle that map 1:1 to the primitives above. Use the autoSaveId prop to persist panel sizes across reloads.

react-resizable-panels vs react-resizable

These are different libraries. react-resizable is an older package for making a single box resizable by dragging its edges. react-resizable-panels is purpose-built for multi-panel split layouts (think VS Code), with collapsing, nested groups, keyboard support and size persistence. For dashboard and app layouts, react-resizable-panels is the modern choice.

react-resizable-panels FAQ

How do I install react-resizable-panels? Run npm install react-resizable-panels (or the equivalent yarn/pnpm command), then import PanelGroup, Panel and PanelResizeHandle.

Is react-resizable-panels the same as react-resizable? No โ€” react-resizable resizes a single element; react-resizable-panels builds full multi-panel split layouts.

How do I build a resizable sidebar with shadcn? Use the shadcn Resizable component (it wraps react-resizable-panels): a ResizablePanelGroup with two ResizablePanels and a ResizableHandle.

How do I persist panel sizes? Set the autoSaveId prop on PanelGroup โ€” sizes are saved to localStorage and restored on reload.

Building a complex resizable UI and want it done right? See our custom web development services.

react-resizable-panelsreactpaneloncollapsepanelresizehandletypescriptfrontend
Share this article:

About the Author

V

Viprasol Tech Team

Custom Software Development Specialists

The Viprasol Tech team specialises in algorithmic trading software, AI agent systems, and SaaS development. With 1000+ projects delivered across MT4/MT5 EAs, fintech platforms, and production AI systems, the team brings deep technical experience to every engagement.

MT4/MT5 EA DevelopmentAI Agent SystemsSaaS DevelopmentAlgorithmic Trading

Need a Modern Web Application?

From landing pages to complex SaaS platforms โ€” we build it all with Next.js and React.

Free consultation โ€ข No commitment โ€ข Response within 24 hours

Viprasol ยท Web Development

Need a custom web application built?

We build React and Next.js web applications with Lighthouse โ‰ฅ90 scores, mobile-first design, and full source code ownership. Senior engineers only โ€” from architecture through deployment.