Resizable Panels

Drag-resizable panels for dashboards, IDEs, and editors. Nest groups for complex layouts like sidebar | editor/terminal.

Component

Explorer
src/
app.tsx
index.ts
app.tsx
export function App() {
  return <div>Hello</div>;
}
Terminal

$ pnpm dev

Installation

pnpm dlx shadcn@latest add "https://pulkitxm.com/components/resizable-panels.json"

Usage

ResizablePanels splits space between children with draggable handles. Each child is a panel. Nest ResizablePanels as a panel child to create complex layouts: different directions at each level let you build IDE-style (sidebar | editor | terminal), dashboards (sidebar | header/content), or multi-column UIs. Always give the root container a height (e.g. h-96) so panels can size correctly.

Import

Add the ResizablePanels import.

import { ResizablePanels } from "@/components/resizable-panels";

Use

Wrap in a container with a defined height. Pass panels as children.

<div className="h-96">
  <ResizablePanels direction="horizontal">
    ...
  </ResizablePanels>
</div>;

Nest for complex layouts

Nest ResizablePanels as a panel child for complex layouts.

<ResizablePanels>
  <div>A</div>
  <ResizablePanels direction="vertical">
    ...
  </ResizablePanels>
</ResizablePanels>;

Guidelines

  • Give the root container a height (h-screen, h-96, etc.) so panels can size correctly.
  • Nest ResizablePanels for complex layouts: each nested group can have its own direction.
  • defaultSizes are proportional weights; [20, 80] means 20% and 80% of available space.
  • Use minSize and maxSize to constrain panel dimensions (default 10–90%).
  • Add overflow-auto to panel content that may overflow (e.g. file lists, code).
  • Touch-friendly: 24px handle by default; use resizeHandleSize to adjust.

Props

All props are optional unless marked required. Use these to customize every aspect of the component.

PropTypeDefaultDescription
childrenReact.ReactNodePanel content. Each direct child becomes a resizable panel. Can be another ResizablePanels for nesting.
classNamestringAdditional CSS classes for the container.
direction"horizontal" | "vertical""horizontal"Layout direction: horizontal (side-by-side) or vertical (stacked).
defaultSizesnumber[]equalInitial panel sizes as flex-grow weights. Values are proportional (e.g. [20, 80] ≈ 20%/80%).
minSizenumber10Minimum panel size as percentage of the group.
maxSizenumber90Maximum panel size as percentage of the group.
resizeHandleSizenumber24Resize handle hit area in pixels. Use 24+ for touch-friendly targets.

Examples

IDE layout

IDE-style: sidebar full height, right side split into editor (top) and terminal (bottom).

Explorer
src/
app.tsx
index.ts
app.tsx
export function App() {
  return <div>Hello</div>;
}
Terminal

$ pnpm dev

import { ResizablePanels } from "@/components/resizable-panels";

export function IdeLayout() {
  return (
    <div className="h-screen">
      <ResizablePanels
        direction="horizontal"
        defaultSizes={[20, 80]}
      >
        <aside className="overflow-auto">
          File explorer
        </aside>
        <ResizablePanels
          direction="vertical"
          defaultSizes={[70, 30]}
        >
          <main className="overflow-auto">Editor</main>
          <footer className="overflow-auto">
            Terminal
          </footer>
        </ResizablePanels>
      </ResizablePanels>
    </div>
  );
}

Dashboard layout

Dashboard: sidebar, then header + main content stacked on the right.

Header / Filters

Date range, search, actions

Main content
Card 1
Card 2
Card 3
Card 4
import { ResizablePanels } from "@/components/resizable-panels";

export function DashboardLayout() {
  return (
    <div className="h-screen">
      <ResizablePanels
        direction="horizontal"
        defaultSizes={[25, 75]}
      >
        <nav className="overflow-auto">Sidebar nav</nav>
        <ResizablePanels
          direction="vertical"
          defaultSizes={[15, 85]}
        >
          <header className="overflow-auto">
            Filters / toolbar
          </header>
          <main className="overflow-auto">
            Content area
          </main>
        </ResizablePanels>
      </ResizablePanels>
    </div>
  );
}

Three-column layout

Three columns in a row. No nesting needed for simple horizontal splits.

Left sidebar
Center content
Right panel
import { ResizablePanels } from "@/components/resizable-panels";

export function ThreeColumnLayout() {
  return (
    <div className="h-96">
      <ResizablePanels
        direction="horizontal"
        defaultSizes={[20, 50, 30]}
      >
        <aside>Left</aside>
        <main>Center</main>
        <aside>Right</aside>
      </ResizablePanels>
    </div>
  );
}

L-shaped layout

L-shaped: left panel spans full height; right side split vertically into top and bottom.

1
2
3
import { ResizablePanels } from "@/components/resizable-panels";

export function LShapedLayout() {
  return (
    <div className="h-96">
      <ResizablePanels
        direction="horizontal"
        defaultSizes={[30, 70]}
      >
        <div className="flex items-center justify-center">
          Sidebar (full height)
        </div>
        <ResizablePanels
          direction="vertical"
          defaultSizes={[50, 50]}
        >
          <div className="flex items-center justify-center">
            Top
          </div>
          <div className="flex items-center justify-center">
            Bottom
          </div>
        </ResizablePanels>
      </ResizablePanels>
    </div>
  );
}

Made with ❤️ by Pulkit & Cursor :)

© 2026 Pulkit. All rights reserved

DMCA Verified

Last updated: