---
title: Resizable
description: "Astro panels with pointer and keyboard size controls."
seo:
    title: "Resizable for Astro — examples and usage"
---

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

<ResizablePanelGroup class="h-48 w-full max-w-2xl rounded-lg border">
  <ResizablePanel defaultSize={50} minSize={20}>
    <div class="flex h-full flex-col items-center justify-center gap-2 p-6">
      <span class="font-semibold">Panel A</span>
      <span class="text-muted-foreground text-sm">
        Drag the handle to resize.
      </span>
    </div>
  </ResizablePanel>
  <ResizableHandle withHandle />
  <ResizablePanel defaultSize={50} minSize={20} class="bg-muted">
    <div class="flex h-full flex-col items-center justify-center gap-2 p-6">
      <span class="font-semibold">Panel B</span>
      <span class="text-muted-foreground text-sm">
        Arrow keys resize the focused handle.
      </span>
    </div>
  </ResizablePanel>
</ResizablePanelGroup>
```

## Installation

```bash
bunx --bun shadcn@latest add @gnosticai/resizable
```

## Usage

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

```astro
<ResizablePanelGroup class="h-48 w-full rounded-lg border">
  <ResizablePanel defaultSize={50} minSize={20}>
    <div class="flex h-full items-center justify-center p-6">One</div>
  </ResizablePanel>
  <ResizableHandle />
  <ResizablePanel defaultSize={50} minSize={20}>
    <div class="flex h-full items-center justify-center p-6">Two</div>
  </ResizablePanel>
</ResizablePanelGroup>
```

## Composition

Place one `ResizableHandle` between each pair of panels. Sizes are percentages of the group. Give the group a height.

```text
ResizablePanelGroup
├── ResizablePanel
├── ResizableHandle
└── ResizablePanel
```

## Examples

### Vertical

Set `direction="vertical"` to stack the panels. The handle moves up and down.

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

<ResizablePanelGroup
  direction="vertical"
  class="h-64 w-full max-w-md rounded-lg border"
>
  <ResizablePanel defaultSize={40} minSize={20}>
    <div class="flex h-full flex-col items-center justify-center gap-2 p-6">
      <span class="font-semibold">Panel A</span>
      <span class="text-muted-foreground text-sm">
        Drag the handle to resize.
      </span>
    </div>
  </ResizablePanel>
  <ResizableHandle withHandle />
  <ResizablePanel defaultSize={60} minSize={20} class="bg-muted">
    <div class="flex h-full flex-col items-center justify-center gap-2 p-6">
      <span class="font-semibold">Panel B</span>
      <span class="text-muted-foreground text-sm">
        Up and down arrow keys resize this group.
      </span>
    </div>
  </ResizablePanel>
</ResizablePanelGroup>
```

### Custom handle

Add a custom handle by passing a direct child to `ResizableHandle`.

```astro
---
import GripVerticalIcon from "@lucide/astro/icons/grip-vertical"
import {
  ResizableHandle,
  ResizablePanel,
  ResizablePanelGroup,
} from "@/components/ui/resizable"
---

<ResizablePanelGroup class="h-48 w-full max-w-2xl rounded-lg border">
  <ResizablePanel defaultSize={50} minSize={20}>
    <div class="flex h-full flex-col items-center justify-center gap-2 p-6">
      <span class="font-semibold">Panel A</span>
      <span class="text-muted-foreground text-sm">
        Drag the custom handle to resize.
      </span>
    </div>
  </ResizablePanel>
  <ResizableHandle>
    <GripVerticalIcon class="h-6 w-3 bg-border z-10 flex shrink-0 rounded-lg text-muted-foreground/72" />
  </ResizableHandle>
  <ResizablePanel defaultSize={50} minSize={20} class="bg-muted">
    <div class="flex h-full flex-col items-center justify-center gap-2 p-6">
      <span class="font-semibold">Panel B</span>
      <span class="text-muted-foreground text-sm">
        Arrow keys resize the focused panel.
      </span>
    </div>
  </ResizablePanel>
</ResizablePanelGroup>
```

### Nested groups

A panel can contain another group. Use `withHandle` to show a grip on the separator.

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

<ResizablePanelGroup class="h-64 w-full max-w-2xl rounded-lg border">
  <ResizablePanel defaultSize={50} minSize={20}>
    <div class="flex h-full items-center justify-center p-6">
      <span class="font-semibold">One</span>
    </div>
  </ResizablePanel>
  <ResizableHandle withHandle />
  <ResizablePanel defaultSize={50} minSize={20}>
    <ResizablePanelGroup direction="vertical" class="h-full">
      <ResizablePanel defaultSize={30} minSize={15}>
        <div class="flex h-full items-center justify-center p-6">
          <span class="font-semibold">Two</span>
        </div>
      </ResizablePanel>
      <ResizableHandle withHandle />
      <ResizablePanel defaultSize={70} minSize={15} class="bg-muted">
        <div class="flex h-full items-center justify-center p-6">
          <span class="font-semibold">Three</span>
        </div>
      </ResizablePanel>
    </ResizablePanelGroup>
  </ResizablePanel>
</ResizablePanelGroup>
```

### Collapsible panel

Set `collapsible` on a panel to let it collapse past `minSize`. Focus the handle and press Enter to collapse and expand that panel. Arrow keys resize by 10 percent. Home and End move to the limits.

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

<ResizablePanelGroup class="h-48 w-full max-w-2xl rounded-lg border">
  <ResizablePanel
    defaultSize={25}
    minSize={15}
    collapsible
    collapsedSize={0}
    class="bg-muted"
  >
    <div class="flex h-full items-center justify-center p-4">
      <span class="text-sm font-semibold">Sidebar</span>
    </div>
  </ResizablePanel>
  <ResizableHandle withHandle aria-label="Resize sidebar" />
  <ResizablePanel defaultSize={75} minSize={30}>
    <div class="flex h-full flex-col items-center justify-center gap-2 p-6">
      <span class="font-semibold">Content</span>
      <span class="text-muted-foreground text-center text-sm">
        Focus the handle and press Enter to collapse the sidebar.
      </span>
    </div>
  </ResizablePanel>
</ResizablePanelGroup>
```

## API Reference

`ResizablePanelGroup`, `ResizablePanel`, and `ResizableHandle` accept native div attributes.

### ResizablePanelGroup

| Prop               | Type                     | Default      | Purpose                                 |
| ------------------ | ------------------------ | ------------ | --------------------------------------- |
| `direction`        | `horizontal`, `vertical` | `horizontal` | Layout axis.                            |
| `keyboardResizeBy` | `number`                 | `10`         | Percent moved for each arrow key press. |

### ResizablePanel

| Prop            | Type      | Default    | Purpose                                                         |
| --------------- | --------- | ---------- | --------------------------------------------------------------- |
| `defaultSize`   | `number`  | even split | Initial size as a percentage.                                   |
| `minSize`       | `number`  | `0`        | Minimum size as a percentage.                                   |
| `maxSize`       | `number`  | `100`      | Maximum size as a percentage.                                   |
| `collapsible`   | `boolean` | `false`    | The panel can collapse.                                         |
| `collapsedSize` | `number`  | `0`        | Size as a percentage when collapsed. Must not exceed `minSize`. |

### ResizableHandle

| Prop         | Type      | Default | Purpose                                  |
| ------------ | --------- | ------- | ---------------------------------------- |
| `withHandle` | `boolean` | `false` | Show a grip in the center of the handle. |

The group emits `resizable:change` on the root element. `event.detail.layout` is the panel sizes in percent. The component does not store the layout.

Read the [installed source](/r/resizable.json) for the component source.
See the [data-slot docs](https://data-slot.com/components/resizable/) for keyboard behavior and the controller API.

## When to use Resizable

Compose panels and resize handles inside a ResizablePanelGroup. Choose an orientation and useful size bounds so neither panel becomes unusable. Keep the panel content independent of its starting size.

## Keyboard and behavior

The existing data-slot controller handles pointer and keyboard resizing. Give each handle a useful label and test its arrow-key behavior. A panel that contains a form must still expose all controls at its minimum size.

## Theme and layout

The handle uses shared border and focus colors. Check content overflow after a resize and at narrow viewport widths. Some layouts are clearer when panels stack instead of remaining resizable on a phone.

## Related choices

Use [Scroll Area](/components/scroll-area) inside a bounded panel and [Sidebar](/components/sidebar) for a navigation shell.
