Resizable
Build flexible layouts with resizable panels separated by draggable dividers.
| Name | Category | Description | Type | Default |
|---|---|---|---|---|
default-size | Size | Initial panel size (1-100%). Panels without this split remaining space equally | number | — |
min-size | Size | Minimum panel size (%) | number | 10 |
max-size | Size | Maximum panel size (%) | number | 100 |
collapsed-size | Size | Panel size when collapsed (%) | number | 0 |
disabled | State | Whether dragging is disabled | boolean | false |
direction | Behavior | Panel layout direction | 'horizontal' | 'vertical' | — |
auto-save-id | Behavior | Unique ID for auto-saving layout to localStorage | string | — |
keyboard-resize-by | Behavior | Step size (%) for keyboard arrow key resizing | number | 10 |
collapsible | Behavior | Whether the panel is collapsible | boolean | false |
hit-area-margins | Behavior | Extra hit area margin in pixels for easier grabbing | number | 0 |
layout | Event | Triggered when panel sizes change, with an array of percentage sizes | (sizes: number[]) => void | — |
resize | Event | Triggered when panel size changes | (size: number) => void | — |
collapse | Event | Triggered when panel collapses | () => void | — |
expand | Event | Triggered when panel expands | () => void | — |
dragging | Event | Triggered when dragging state changes | (isDragging: boolean) => void | — |
default | Slot | ResizablePanel and ResizableHandle components | — | |
default | Slot | Panel content | — | |
collapse | Expose | Collapse the panel | () => void | — |
expand | Expose | Expand the panel | () => void | — |
getSize | Expose | Get current panel size | () => number | — |
resize | Expose | Set panel size | (size: number) => void | — |
Basic Usage
A horizontal two-panel layout. Drag the handle to resize.
<template>
<div class="demo-resizable">
<px-resizable-group direction="horizontal">
<px-resizable-panel :default-size="50">
<div class="demo-panel">Panel A</div>
</px-resizable-panel>
<px-resizable-handle />
<px-resizable-panel :default-size="50">
<div class="demo-panel">Panel B</div>
</px-resizable-panel>
</px-resizable-group>
</div>
</template>
<style scoped>
.demo-resizable {
height: 200px;
border: 2px solid var(--px-border-color);
}
.demo-panel {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
font-family: var(--px-font-family);
}
</style>Vertical Direction
Use direction="vertical" for top/bottom split.
<template>
<div class="demo-resizable">
<px-resizable-group direction="vertical">
<px-resizable-panel :default-size="40">
<div class="demo-panel">Top</div>
</px-resizable-panel>
<px-resizable-handle />
<px-resizable-panel :default-size="60">
<div class="demo-panel">Bottom</div>
</px-resizable-panel>
</px-resizable-group>
</div>
</template>
<style scoped>
.demo-resizable {
height: 300px;
border: 2px solid var(--px-border-color);
}
.demo-panel {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
font-family: var(--px-font-family);
}
</style>Three Panels
Multiple panels with handles between each pair.
<template>
<div class="demo-resizable">
<px-resizable-group direction="horizontal">
<px-resizable-panel :default-size="25">
<div class="demo-panel">Sidebar</div>
</px-resizable-panel>
<px-resizable-handle />
<px-resizable-panel :default-size="50">
<div class="demo-panel">Content</div>
</px-resizable-panel>
<px-resizable-handle />
<px-resizable-panel :default-size="25">
<div class="demo-panel">Inspector</div>
</px-resizable-panel>
</px-resizable-group>
</div>
</template>
<style scoped>
.demo-resizable {
height: 200px;
border: 2px solid var(--px-border-color);
}
.demo-panel {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
font-family: var(--px-font-family);
}
</style>Min / Max Size
Use min-size and max-size to constrain panel sizes.
<template>
<div class="demo-resizable">
<px-resizable-group direction="horizontal">
<px-resizable-panel :default-size="30" :min-size="20" :max-size="50">
<div class="demo-panel">Min 20% / Max 50%</div>
</px-resizable-panel>
<px-resizable-handle />
<px-resizable-panel :default-size="70">
<div class="demo-panel">Flexible</div>
</px-resizable-panel>
</px-resizable-group>
</div>
</template>
<style scoped>
.demo-resizable {
height: 200px;
border: 2px solid var(--px-border-color);
}
.demo-panel {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
font-family: var(--px-font-family);
font-size: 12px;
}
</style>Collapsible Panel
Set collapsible on a panel to allow collapsing it to collapsed-size. Use exposed collapse() and expand() methods.
<script setup lang="ts">
import { ref } from 'vue';
const panelRef = ref();
function toggleCollapse() {
if (!panelRef.value) return;
if (panelRef.value.getSize() <= 5) {
panelRef.value.expand();
} else {
panelRef.value.collapse();
}
}
</script>
<template>
<px-button @click="toggleCollapse" style="margin-bottom: 12px">
Toggle Sidebar
</px-button>
<div class="demo-resizable">
<px-resizable-group direction="horizontal">
<px-resizable-panel
ref="panelRef"
:default-size="30"
collapsible
:collapsed-size="0"
>
<div class="demo-panel">Sidebar</div>
</px-resizable-panel>
<px-resizable-handle />
<px-resizable-panel :default-size="70">
<div class="demo-panel">Content</div>
</px-resizable-panel>
</px-resizable-group>
</div>
</template>
<style scoped>
.demo-resizable {
height: 200px;
border: 2px solid var(--px-border-color);
}
.demo-panel {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
font-family: var(--px-font-family);
}
</style>Nested Layout
Nest ResizableGroup components with different directions for complex layouts.
<template>
<div class="demo-resizable">
<px-resizable-group direction="vertical">
<px-resizable-panel :default-size="60">
<px-resizable-group direction="horizontal">
<px-resizable-panel :default-size="30">
<div class="demo-panel">Sidebar</div>
</px-resizable-panel>
<px-resizable-handle />
<px-resizable-panel :default-size="70">
<div class="demo-panel">Editor</div>
</px-resizable-panel>
</px-resizable-group>
</px-resizable-panel>
<px-resizable-handle />
<px-resizable-panel :default-size="40">
<div class="demo-panel">Terminal</div>
</px-resizable-panel>
</px-resizable-group>
</div>
</template>
<style scoped>
.demo-resizable {
height: 350px;
border: 2px solid var(--px-border-color);
}
.demo-panel {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
font-family: var(--px-font-family);
}
</style>Auto Save
Set auto-save-id to persist layout to localStorage. The layout restores on page reload.
<template>
<div class="demo-resizable">
<p style="margin-bottom: 8px; font-family: var(--px-font-family)">
Resize the panels, then reload the page — the layout is saved.
</p>
<div class="demo-container">
<px-resizable-group direction="horizontal" auto-save-id="demo-layout">
<px-resizable-panel :default-size="40">
<div class="demo-panel">Saved Panel A</div>
</px-resizable-panel>
<px-resizable-handle />
<px-resizable-panel :default-size="60">
<div class="demo-panel">Saved Panel B</div>
</px-resizable-panel>
</px-resizable-group>
</div>
</div>
</template>
<style scoped>
.demo-container {
height: 200px;
border: 2px solid var(--px-border-color);
}
.demo-panel {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
font-family: var(--px-font-family);
}
</style>