# Resizable panels

> Trade space between panes by dragging the divider between them.

- Type: Component (disclosure)
- Access: Free, open source
- Page: https://ui.xzero.co.uk/components/resizable-panels
- Markdown: https://ui.xzero.co.uk/components/resizable-panels/markdown
- Registry item: https://mcp.xzero.co.uk/r/resizable-panels.json
- Source file: `registry/components/resizable-panels/resizable-panels.tsx`
- Dependencies: motion, lucide-react
- Keywords: split view, resizable, panes, react resizable panels, resizable sidebar, draggable divider, split pane, collapsible panel, resizable layout

## When to use

- 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.

## When not to use

- 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

Register both Xzero UI namespaces in your project's components.json:

```json
{
  "registries": {
    "@xzero-ui": "https://mcp.xzero.co.uk/r/{name}.json",
    "@xzero-ui-pro": "https://mcp.xzero.co.uk/r/pro/{name}.json"
  }
}
```

```bash
npx shadcn@4.23.0 add @xzero-ui/resizable-panels
```

Install xzero-foundation once, and import @/components/xzero/foundation.css in your app root. No Xzero token is used by this snapshot. For sample portraits, photos, fonts, or logos, download https://mcp.xzero.co.uk/install-assets.mjs and run node xzero-install-assets.mjs <receiving-project>.

## Usage

```tsx
import { ResizablePanel, ResizablePanels } from "@/components/xzero/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

### ResizablePanels

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

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `children` (required) | `ReactNode` | – | ResizablePanel elements in order. The set of panes should stay stable. |
| `label` | `string` | – | aria-label for the group. |
| `onLayoutChange` | `(sizes: number[]) => void` | – | Called with each pane's share in percent after a resize settles. |
| `className` | `string` | – | Class on the group element. |

### ResizablePanel

Configuration for one pane. The group renders it.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `id` (required) | `string` | – | Stable id, used by the divider's aria-controls. |
| `label` (required) | `string` | – | Names the pane for its divider. |
| `defaultSize` (required) | `number` | – | Starting share of the group. Shares are relative and need not sum to 100. |
| `minSize` | `number` | `80` | Width in px where the pane starts to resist. Content clips and fades below it. |
| `maxSize` | `number` | – | Maximum width in px. |
| `collapsible` | `boolean` | – | Dragging well past the minimum or flicking toward the edge snaps the pane closed. |
| `defaultCollapsed` | `boolean` | – | Starts collapsed. Requires collapsible. |
| `className` | `string` | – | Class on the pane. |
| `children` | `ReactNode` | – | Pane content. |

## Keyboard interactions

| Keys | Action |
| --- | --- |
| ArrowLeft / ArrowRight | Moves the focused divider 16px; with Shift, 64px. Past a limit, collapses a collapsible pane. |
| Home / End | 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. |

## Accessibility

- 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.

## Motion

- 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.

## Responsive behavior

- 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.

## Performance

- 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

- 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.

## Related

- [Drawer](https://ui.xzero.co.uk/components/drawer/markdown): A temporary side surface for focused work.
- [Tree view](https://ui.xzero.co.uk/components/tree-view/markdown): Navigate nested folders and structured content.
- [Tabs](https://ui.xzero.co.uk/components/tabs/markdown): Switch between related content in the same context.

## Also in expand

- [Scroll area](https://ui.xzero.co.uk/components/scroll-area/markdown): A native scroll container with thin overlay scrollbars and edge fades that appear only when content overflows.
- [Accordion](https://ui.xzero.co.uk/components/accordion/markdown): Progressively reveal supporting information in place.
- [Expandable card](https://ui.xzero.co.uk/components/expandable-card/markdown): Give a dense card more room when requested.
- [Expandable text](https://ui.xzero.co.uk/components/expandable-text/markdown): Long text clamped to a few lines with a soft fade that glides open with Read more and closes with Show less, shown only when the text overflows.

## Guidance for AI tools

Resizable panels: Trade space between panes by dragging the divider between them. Follow the declared prop types and do not invent props. Keep keyboard access, reduced motion support, and both light and dark themes intact when adapting it.

Full library index: https://ui.xzero.co.uk/llms.txt
