Skip to content

Resizable

Build flexible layouts with resizable panels separated by draggable dividers.

NameCategoryDescriptionTypeDefault
default-size? SizeInitial panel size (1-100%). Panels without this split remaining space equallynumber
min-size? SizeMinimum panel size (%)number10
max-size? SizeMaximum panel size (%)number100
collapsed-size? SizePanel size when collapsed (%)number0
disabled? StateWhether dragging is disabledbooleanfalse
direction? BehaviorPanel layout direction'horizontal' | 'vertical'
auto-save-id? BehaviorUnique ID for auto-saving layout to localStoragestring
keyboard-resize-by? BehaviorStep size (%) for keyboard arrow key resizingnumber10
collapsible? BehaviorWhether the panel is collapsiblebooleanfalse
hit-area-margins? BehaviorExtra hit area margin in pixels for easier grabbingnumber0
layout? EventTriggered when panel sizes change, with an array of percentage sizes(sizes: number[]) => void
resize? EventTriggered when panel size changes(size: number) => void
collapse? EventTriggered when panel collapses() => void
expand? EventTriggered when panel expands() => void
dragging? EventTriggered when dragging state changes(isDragging: boolean) => void
default? SlotResizablePanel and ResizableHandle components
default? SlotPanel content
collapse? ExposeCollapse the panel() => void
expand? ExposeExpand the panel() => void
getSize? ExposeGet current panel size() => number
resize? ExposeSet 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>