Back to Blog

react-resizable-panels: PanelOnCollapse + Drag Handles (2026)

react-resizable-panels guide: PanelOnCollapse type, PanelResizeHandle API, working code, localStorage persistence, TypeScript types, common pitfalls.

Viprasol Tech Team
14 min read
Updated 2026

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

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: PanelOnCollapse + Drag Handles (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✅ ExcellentonCollapse✅ Built-in autoSaveId2026 recommended pick
react-split-pane⚠️ Stale (last 2021)~8 kBPartialLegacy; do not use
react-reflex⚠️ Slow updates~14 kBManualManualOlder API, harder a11y
allotment (VS Code-derived)✅ Active~20 kBHeavier, more features
react-grid-layout✅ Active~50 kBFor 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-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.