ComponentsPage layouts

Resizable

User-sized panes for split views: inbox + message, media grid + details, editor + preview. Keyboard resizing, pixel or percent limits, collapsible panes, nested groups and a remembered layout.

react-resizable-panels v4 components/resizable.tsx, styles/navigation.csstheme · material · accent · density · font
  • Northwind — master services agreement.pdf412 KB · Nov 4
  • Kadıköy Bistro — renewal 2027.pdf286 KB · Oct 29
  • Lumen Architects — NDA.pdf118 KB · Oct 12

Installation

$ pnpm add @vamos-ui/react

The whole kit as one package — get updates by bumping the version. Add the styles to globals.css: @import "@vamos-ui/react/styles.css";

Usage

import { ResizableGroup, ResizablePanel, ResizableHandle } from "@vamos-ui/react";

<ResizableGroup autoSaveId="inbox" className="h-[560px]">
  <ResizablePanel id="list" defaultSize="35%" minSize="25%">…</ResizablePanel>
  <ResizableHandle withGrip />
  <ResizablePanel id="detail">…</ResizablePanel>
</ResizableGroup>

Keyboard (WAI-ARIA Window Splitter): focus the handle, then ← → (or ↑ ↓), Home / End; Enter collapses a collapsible pane.

Glass mode: surfaces inside the group stop blurring while a handle is dragged, to avoid flicker.

On phones, show one pane and open the other in a Sheet — this is not automatic.

Examples

Split view with saved layout (CRM inbox)

autoSaveId stores the layout in localStorage (safe when storage is blocked). Panels need stable ids. Pixel limits keep the list readable on any width.

  • Laura Callahan09:42

    Renewal — revised quote

    Thanks, the 3-year option works for us if…

  • Jonas Weber08:15

    Onboarding call

    Could we move it to Thursday at 14:00?

  • Priya NairMon

    Invoice INV-2026-0411

    Payment was sent yesterday, reference…

  • Kenji SatoSun

    API rate limits

    We're hitting 429s on the contacts endpoint…

Renewal — revised quote

Laura Callahan · Northwind Traders

Thanks, the 3-year option works for us if the onboarding hours can be included. Our board meets on December 3; I'd like to bring a signed draft.

Nested groups (CMS editor)

A vertical group inside a horizontal one. Double-click a handle to reset its panes.

<section class="hero">
  <h1>{{ page.title }}</h1>
  <p>{{ page.lead }}</p>
</section>

Compiled in 42 ms · 0 warnings

Autumn menu is here

Twelve new dishes from the Aegean coast, served from November 14.

Collapsible pane (HR directory)

collapsible + collapsedSize; drive it with useResizablePanelRef() → collapse() / expand().

  • Elif Kaya — Engineering manager
  • Mert Aydın — SRE
  • Sofia Rossi — Designer
  • Omar Haddad — Recruiter
  • Emma Clarke — Payroll

Elif Kaya

Engineering manager · Istanbul office · 6 direct reports

API

ResizableGroup

PropTypeDefault
orientation
Panes side by side or stacked. direction is an alias.
"horizontal" | "vertical""horizontal"
autoSaveId
Persist the layout under this key.
string—
storage
Storage for autoSaveId (e.g. a cookie adapter so the server renders the saved layout).
{ getItem; setItem }safe localStorage
defaultLayout
Initial layout in percentages.
Record<panelId, number>—
onLayoutChanged
After a resize ends (pointer released / key pressed).
(layout, meta) => void—
onLayoutChange
On every pointer move while resizing.
(layout) => void—
groupRef
getLayout() / setLayout(). See useResizableGroupRef().
Ref<ResizableGroupHandle>—
disabled
Turn resizing off.
booleanfalse

ResizablePanel

PropTypeDefault
id
Stable id (required for saved layouts).
string—
defaultSize
Number = px; "35" or "35%" = percent; also rem, em, vh, vw.
number | string—
minSize · maxSize
Limits, same units as defaultSize.
number | string"0%" · "100%"
collapsible
Collapses when dragged below minSize.
booleanfalse
collapsedSize
Size when collapsed.
number | string"0%"
onResize
Called when the size changes.
(size: { asPercentage; inPixels }) => void—
panelRef
collapse(), expand(), resize(), getSize(), isCollapsed(). See useResizablePanelRef().
Ref<ResizablePanelHandle>—

ResizableHandle

PropTypeDefault
withGrip
A visible grip in the middle of the line.
booleanfalse
aria-label
Name of the splitter, e.g. "Resize thread list".
string—
disabled
This handle can't be dragged.
booleanfalse
disableDoubleClick
Turn off double-click to reset.
booleanfalse