Resizable panels

Trade space between panes by dragging the divider between them.

pnpm dlx shadcn@latest add @uiarc/resizable-panels
Live · keyboard ready
Inbox3 unread

Harbour suite 4 moves to Friday

Sofia Ramirezsofia@marenhouse.com9:41

The Andersens asked to push their arrival to Friday the 26th. I've held Harbour suite 4 for them and moved the airport pickup to 14:10.

Could housekeeping leave the rust linen throw from the autumn shoot on the bench? They asked about it after seeing the photos.

Sofia

  • Editor, mail, or dashboard layouts where people trade space between side-by-side panes.
  • Sidebars that should collapse by dragging or flicking toward the edge.
  • Layouts whose pane sizes should persist between visits via onLayoutChange.
  • Use drawer for a panel that slides over the page.
  • Use tabs when only one pane needs to be visible at a time.
  • Avoid it for vertical splits, since it is horizontal only.

Installation

Add Resizable panels with the shadcn CLI, or copy the source by hand.

pnpm dlx shadcn@latest add @uiarc/resizable-panels

Adds the component and its local dependencies, and installs motion, lucide-react. First time? Add the @uiarc registry to components.json, or use the full URL:

example.tsx
import { ResizablePanel, ResizablePanels } from "@/registry/components/resizable-panels/resizable-panels"; export function MailLayout() {  return (    <div style={{ height: 480 }}>      <ResizablePanels label="Mail" onLayoutChange={saveLayout}>        <ResizablePanel id="folders" label="Folders" defaultSize={22} minSize={160} collapsible>          <FolderList />        </ResizablePanel>        <ResizablePanel id="messages" label="Messages" defaultSize={78}>          <MessageList />        </ResizablePanel>      </ResizablePanels>    </div>  );}

API reference

2 parts. The first is the root.

ResizablePanels

A horizontal split view with draggable, keyboard-operable dividers between panes. Needs a definite height.

PropTypeDefaultDescription
childrenRequiredReactNode–ResizablePanel elements in order. The set of panes should stay stable.
labelstring–aria-label for the group.
onLayoutChange(sizes: number[]) => void–Called with each pane's share in percent after a resize settles.
classNamestring–Class on the group element.

ResizablePanel

Configuration for one pane. The group renders it.

PropTypeDefaultDescription
idRequiredstring–Stable id, used by the divider's aria-controls.
labelRequiredstring–Names the pane for its divider.
defaultSizeRequirednumber–Starting share of the group. Shares are relative and need not sum to 100.
minSizenumber80Width in px where the pane starts to resist. Content clips and fades below it.
maxSizenumber–Maximum width in px.
collapsibleboolean–Dragging well past the minimum or flicking toward the edge snaps the pane closed.
defaultCollapsedboolean–Starts collapsed. Requires collapsible.
classNamestring–Class on the pane.
childrenReactNode–Pane content.
ArrowLeftorArrowRight
Moves the focused divider 16px; with Shift, 64px. Past a limit, collapses a collapsible pane.
HomeorEnd
Moves the divider to its minimum or maximum.
Enter
Collapses or restores a collapsible neighbouring pane.
Escape
During a drag, returns the divider to where it started.
  • Each divider is a focusable role="separator" with aria-orientation, aria-controls, aria-valuenow, min, and max in percent.
  • aria-valuetext announces the share, or that a pane is hidden and Enter shows it.
  • Collapsed panes are inert. The group has role="group"; pass label to name it.
  • Dividers follow the pointer 1:1, rubber-band past limits, and spring to rest; flicks toward an edge collapse a pane. Double-click resets the layout.
  • Pane content fades as it is squeezed below its minimum and a restore tab pops in on a snappy spring.
  • Reduced motion jumps panes to their targets and fades the restore tab.
  • Panes do not stack on narrow screens; on mobile, render a single pane or switch to tabs yourself.
  • Dividers use pointer capture with touch-action none, so touch, pen, and mouse drags all work.
  • The group needs a definite height from its parent.
  • A ResizeObserver on the group refits pane widths when the container resizes.
  • Dragging sets widths directly and springs only on release or collapse; pane content is never re-rendered by the drag itself.

Notes for AI

Give your coding assistant the Markdown reference instead of screenshots.

  • Use for editor, mail, or dashboard layouts where people trade space between side-by-side panes. Horizontal only.
  • Give the parent a definite height and persist onLayoutChange shares to restore via defaultSize.

The full library index for assistants is at /llms.txt.