---
type: doc
title: Resizable
description: Accessible panel groups with pointer and keyboard resizing.
---

```astro live props={{ name: 'resizable' }}
---
import {
  ResizableHandle,
  ResizablePanel,
  ResizablePanelGroup,
} from "@/components/ui/resizable"
---

<ResizablePanelGroup class="h-48 max-w-2xl rounded-lg border">
  <ResizablePanel
    defaultSize={35}
    minSize={20}
    class="flex items-center justify-center p-6"
  >
    Sidebar
  </ResizablePanel>
  <ResizableHandle withHandle aria-label="Resize sidebar and content" />
  <ResizablePanel
    defaultSize={65}
    minSize={30}
    class="flex items-center justify-center p-6"
  >
    Content
  </ResizablePanel>
</ResizablePanelGroup>
```

## Installation

```bash
npx shadcn@latest add @fulldev/resizable
```

## Usage

```astro
---
import {
  ResizableHandle,
  ResizablePanel,
  ResizablePanelGroup,
} from "@/components/ui/resizable"
---

<ResizablePanelGroup class="h-48">
  <ResizablePanel defaultSize={40}>Sidebar</ResizablePanel>
  <ResizableHandle aria-label="Resize panels" />
  <ResizablePanel defaultSize={60}>Content</ResizablePanel>
</ResizablePanelGroup>
```

A group needs one handle between each pair of panels. Give every handle an accessible label. Drag a handle with a pointer, or focus it and use the arrow keys.

## Examples

### Vertical

Use `direction="vertical"` for rows. The handle responds to the up and down arrow keys.

```astro live
---
import {
  ResizableHandle,
  ResizablePanel,
  ResizablePanelGroup,
} from "@/components/ui/resizable"
---

<ResizablePanelGroup
  direction="vertical"
  class="h-72 max-w-2xl rounded-lg border"
>
  <ResizablePanel
    defaultSize={35}
    minSize={20}
    class="flex items-center justify-center p-4"
  >
    Header
  </ResizablePanel>
  <ResizableHandle withHandle aria-label="Resize header and body" />
  <ResizablePanel
    defaultSize={65}
    minSize={30}
    class="flex items-center justify-center p-4"
  >
    Body
  </ResizablePanel>
</ResizablePanelGroup>
```

### Collapsible

Focus the handle and press `Enter` to collapse or restore the first panel. Dragging through the minimum size also collapses it.

```astro live
---
import {
  ResizableHandle,
  ResizablePanel,
  ResizablePanelGroup,
} from "@/components/ui/resizable"
---

<ResizablePanelGroup class="h-48 max-w-2xl rounded-lg border">
  <ResizablePanel
    defaultSize={30}
    minSize={20}
    collapsible
    collapsedSize={0}
    class="flex items-center justify-center p-4"
  >
    Collapsible sidebar
  </ResizablePanel>
  <ResizableHandle withHandle aria-label="Resize or collapse sidebar" />
  <ResizablePanel
    defaultSize={70}
    minSize={30}
    class="flex items-center justify-center p-4"
  >
    Main content
  </ResizablePanel>
</ResizablePanelGroup>
```

### Nested

Each group owns only its direct panels and handles, so a panel can safely contain another resizable group.

```astro live
---
import {
  ResizableHandle,
  ResizablePanel,
  ResizablePanelGroup,
} from "@/components/ui/resizable"
---

<ResizablePanelGroup class="h-72 max-w-2xl rounded-lg border">
  <ResizablePanel
    defaultSize={35}
    minSize={20}
    class="flex items-center justify-center p-4"
  >
    Navigation
  </ResizablePanel>
  <ResizableHandle aria-label="Resize navigation and workspace" />
  <ResizablePanel defaultSize={65} minSize={30}>
    <ResizablePanelGroup direction="vertical" class="h-full">
      <ResizablePanel
        defaultSize={60}
        minSize={25}
        class="flex items-center justify-center p-4"
      >
        Editor
      </ResizablePanel>
      <ResizableHandle withHandle aria-label="Resize editor and console" />
      <ResizablePanel
        defaultSize={40}
        minSize={20}
        class="flex items-center justify-center p-4"
      >
        Console
      </ResizablePanel>
    </ResizablePanelGroup>
  </ResizablePanel>
</ResizablePanelGroup>
```

## Keyboard Controls

| Key                   | Action                                                       |
| --------------------- | ------------------------------------------------------------ |
| Arrow keys            | Resize by `keyboardResizeBy` in the group direction.         |
| `Shift` + arrow       | Resize to the available limit.                               |
| `Home` / `End`        | Minimize or maximize the panel before the handle.            |
| `Enter`               | Collapse or restore the collapsible panel before the handle. |
| `F6` / `Shift` + `F6` | Focus the next or previous handle in the group.              |

## API Reference

### ResizablePanelGroup

`Resizable` is an alias for `ResizablePanelGroup`.

| Prop               | Type                         | Default        | Description                            |
| ------------------ | ---------------------------- | -------------- | -------------------------------------- |
| `direction`        | `"horizontal" \| "vertical"` | `"horizontal"` | Sets the layout and resize axis.       |
| `keyboardResizeBy` | `number`                     | `10`           | Percentage moved by an arrow keypress. |

### ResizablePanel

All sizes are percentages between 0 and 100.

| Prop            | Type      | Default    | Description                                 |
| --------------- | --------- | ---------- | ------------------------------------------- |
| `defaultSize`   | `number`  | even split | Initial panel size.                         |
| `minSize`       | `number`  | `0`        | Minimum expanded size.                      |
| `maxSize`       | `number`  | `100`      | Maximum size.                               |
| `collapsible`   | `boolean` | `false`    | Allows the panel to use its collapsed size. |
| `collapsedSize` | `number`  | `0`        | Size used while collapsed.                  |

### ResizableHandle

| Prop         | Type      | Default | Description                              |
| ------------ | --------- | ------- | ---------------------------------------- |
| `withHandle` | `boolean` | `false` | Shows a visible grip on the separator.   |
| `disabled`   | `boolean` | `false` | Blocks keyboard resizing on this handle. |

The root emits `resizable:change` with `{ layout: number[] }` and `resizable:dragging` with `{ dragging: boolean }`. Dispatch `resizable:set` with `{ layout: number[] }` to set a layout from client code.

See the [GitHub source code](https://github.com/fulldotdev/ui/tree/main/src/components/ui/resizable) for the component source.
See the [data-slot docs](https://github.com/bejamas/data-slot/blob/main/packages/resizable/README.md) for constraints, controller methods, and event details.
