Layout
Resizable
Two panels that share one space, with a handle people drag or move with the keyboard.
| Class name | Type | Description |
|---|---|---|
resizableplf:resizable | Component | Two panels and a handle |
resizable-panelplf:resizable-panel | Part | One of the two panels |
resizable-handleplf:resizable-handle | Part | The handle between the panels |
resizable-gripplf:resizable-grip | Part | An optional box that draws a grip icon |
resizable-iconplf:resizable-icon | Part | Your own SVG in the grip, in place of the drawn one; an icon class there doesn't need it |
Default
The group takes exactly these three children: a panel is named by its first heading, or by aria-label, and the handle starts hidden; the script names it after the first panel.
Customers
Recent accounts
Olivia Martin
olivia@example.com
Jackson Lee
jackson@example.com
Sofia Davis
sofia@example.com
Customer details
Olivia Martin · Pro account
Overview
Active since January 2026. Monthly billing, with a dedicated workspace for design and reporting.
Lifetime revenue
$2,480.00Team members
12Each panel scrolls independently. On narrow screens, both panels remain readable in a stacked layout.
<div class="resizable" data-plf-resizable>
<section class="resizable-panel flex flex-col gap-4" data-plf-size="35" data-plf-min-size="25" data-plf-max-size="75">
<div>
<h3>Customers</h3>
<p>Recent accounts</p>
</div>
<div class="flex flex-col gap-4">
<div class="item">
<div class="item-content">
<p class="item-title">Olivia Martin</p>
<p class="item-description">olivia@example.com</p>
</div>
<span class="badge">Pro</span>
</div>
<div class="item">
<div class="item-content">
<p class="item-title">Jackson Lee</p>
<p class="item-description">jackson@example.com</p>
</div>
</div>
<div class="item">
<div class="item-content">
<p class="item-title">Sofia Davis</p>
<p class="item-description">sofia@example.com</p>
</div>
</div>
</div>
</section>
<div class="resizable-handle" hidden>
<span class="resizable-grip"></span>
</div>
<section class="resizable-panel flex flex-col gap-4">
<div>
<h3>Customer details</h3>
<p>Olivia Martin · Pro account</p>
</div>
<div>
<h4>Overview</h4>
<p>Active since January 2026. Monthly billing, with a dedicated workspace for design and reporting.</p>
</div>
<div class="grid grid-cols-2 gap-4">
<div>
<p>Lifetime revenue</p>
<strong>$2,480.00</strong>
</div>
<div>
<p>Team members</p>
<strong>12</strong>
</div>
</div>
<p>Each panel scrolls independently. On narrow screens, both panels remain readable in a stacked layout.</p>
</section>
</div><div class="plf:resizable" data-plf-resizable>
<section class="plf:resizable-panel plf:flex plf:flex-col plf:gap-4" data-plf-size="35" data-plf-min-size="25" data-plf-max-size="75">
<div>
<h3>Customers</h3>
<p>Recent accounts</p>
</div>
<div class="plf:flex plf:flex-col plf:gap-4">
<div class="plf:item">
<div class="plf:item-content">
<p class="plf:item-title">Olivia Martin</p>
<p class="plf:item-description">olivia@example.com</p>
</div>
<span class="plf:badge">Pro</span>
</div>
<div class="plf:item">
<div class="plf:item-content">
<p class="plf:item-title">Jackson Lee</p>
<p class="plf:item-description">jackson@example.com</p>
</div>
</div>
<div class="plf:item">
<div class="plf:item-content">
<p class="plf:item-title">Sofia Davis</p>
<p class="plf:item-description">sofia@example.com</p>
</div>
</div>
</div>
</section>
<div class="plf:resizable-handle" hidden>
<span class="plf:resizable-grip"></span>
</div>
<section class="plf:resizable-panel plf:flex plf:flex-col plf:gap-4">
<div>
<h3>Customer details</h3>
<p>Olivia Martin · Pro account</p>
</div>
<div>
<h4>Overview</h4>
<p>Active since January 2026. Monthly billing, with a dedicated workspace for design and reporting.</p>
</div>
<div class="plf:grid plf:grid-cols-2 plf:gap-4">
<div>
<p>Lifetime revenue</p>
<strong>$2,480.00</strong>
</div>
<div>
<p>Team members</p>
<strong>12</strong>
</div>
</div>
<p>Each panel scrolls independently. On narrow screens, both panels remain readable in a stacked layout.</p>
</section>
</div>import { Badge, Item, ItemContent, ItemDescription, Resizable, ResizableGrip, ResizableHandle, ResizablePanel } from '@pelatform/react';
export function Example() {
return (
<Resizable defaultSize={35} minSize={25} maxSize={75}>
<ResizablePanel className="flex flex-col gap-4">
<div>
<h3>Customers</h3>
<p>Recent accounts</p>
</div>
<div className="flex flex-col gap-4">
<Item>
<ItemContent>
<p className="item-title">Olivia Martin</p>
<ItemDescription>olivia@example.com</ItemDescription>
</ItemContent>
<Badge>Pro</Badge>
</Item>
<Item>
<ItemContent>
<p className="item-title">Jackson Lee</p>
<ItemDescription>jackson@example.com</ItemDescription>
</ItemContent>
</Item>
<Item>
<ItemContent>
<p className="item-title">Sofia Davis</p>
<ItemDescription>sofia@example.com</ItemDescription>
</ItemContent>
</Item>
</div>
</ResizablePanel>
<ResizableHandle>
<ResizableGrip />
</ResizableHandle>
<ResizablePanel className="flex flex-col gap-4">
<div>
<h3>Customer details</h3>
<p>Olivia Martin · Pro account</p>
</div>
<div>
<h4>Overview</h4>
<p>Active since January 2026. Monthly billing, with a dedicated workspace for design and reporting.</p>
</div>
<div className="grid grid-cols-2 gap-4">
<div>
<p>Lifetime revenue</p>
<strong>$2,480.00</strong>
</div>
<div>
<p>Team members</p>
<strong>12</strong>
</div>
</div>
<p>Each panel scrolls independently. On narrow screens, both panels remain readable in a stacked layout.</p>
</ResizablePanel>
</Resizable>
);
}import { Badge, Item, ItemContent, ItemDescription, Resizable, ResizableGrip, ResizableHandle, ResizablePanel } from '@pelatform/react/prefixed';
export function Example() {
return (
<Resizable defaultSize={35} minSize={25} maxSize={75}>
<ResizablePanel className="plf:flex plf:flex-col plf:gap-4">
<div>
<h3>Customers</h3>
<p>Recent accounts</p>
</div>
<div className="plf:flex plf:flex-col plf:gap-4">
<Item>
<ItemContent>
<p className="plf:item-title">Olivia Martin</p>
<ItemDescription>olivia@example.com</ItemDescription>
</ItemContent>
<Badge>Pro</Badge>
</Item>
<Item>
<ItemContent>
<p className="plf:item-title">Jackson Lee</p>
<ItemDescription>jackson@example.com</ItemDescription>
</ItemContent>
</Item>
<Item>
<ItemContent>
<p className="plf:item-title">Sofia Davis</p>
<ItemDescription>sofia@example.com</ItemDescription>
</ItemContent>
</Item>
</div>
</ResizablePanel>
<ResizableHandle>
<ResizableGrip />
</ResizableHandle>
<ResizablePanel className="plf:flex plf:flex-col plf:gap-4">
<div>
<h3>Customer details</h3>
<p>Olivia Martin · Pro account</p>
</div>
<div>
<h4>Overview</h4>
<p>Active since January 2026. Monthly billing, with a dedicated workspace for design and reporting.</p>
</div>
<div className="plf:grid plf:grid-cols-2 plf:gap-4">
<div>
<p>Lifetime revenue</p>
<strong>$2,480.00</strong>
</div>
<div>
<p>Team members</p>
<strong>12</strong>
</div>
</div>
<p>Each panel scrolls independently. On narrow screens, both panels remain readable in a stacked layout.</p>
</ResizablePanel>
</Resizable>
);
}Monthly summary
Total revenue
$18,420.00New customers
126Recent activity
Monthly report is ready
Today at 09:42
Olivia upgraded to Pro
Today at 08:30
Weekly invoice processed
Yesterday at 16:15
<div class="resizable" data-plf-resizable data-plf-orientation="vertical">
<section class="resizable-panel flex flex-col gap-4" data-plf-size="45" data-plf-min-size="25" data-plf-max-size="75">
<h3>Monthly summary</h3>
<div class="grid grid-cols-2 gap-4">
<div>
<p>Total revenue</p>
<strong>$18,420.00</strong>
</div>
<div>
<p>New customers</p>
<strong>126</strong>
</div>
</div>
</section>
<div class="resizable-handle" hidden>
<span class="resizable-grip"></span>
</div>
<section class="resizable-panel flex flex-col gap-4">
<h3>Recent activity</h3>
<div class="item">
<div class="item-content">
<p class="item-title">Monthly report is ready</p>
<p class="item-description">Today at 09:42</p>
</div>
<span class="badge">Report</span>
</div>
<div class="item">
<div class="item-content">
<p class="item-title">Olivia upgraded to Pro</p>
<p class="item-description">Today at 08:30</p>
</div>
</div>
<div class="item">
<div class="item-content">
<p class="item-title">Weekly invoice processed</p>
<p class="item-description">Yesterday at 16:15</p>
</div>
</div>
</section>
</div><div class="plf:resizable" data-plf-resizable data-plf-orientation="vertical">
<section class="plf:resizable-panel plf:flex plf:flex-col plf:gap-4" data-plf-size="45" data-plf-min-size="25" data-plf-max-size="75">
<h3>Monthly summary</h3>
<div class="plf:grid plf:grid-cols-2 plf:gap-4">
<div>
<p>Total revenue</p>
<strong>$18,420.00</strong>
</div>
<div>
<p>New customers</p>
<strong>126</strong>
</div>
</div>
</section>
<div class="plf:resizable-handle" hidden>
<span class="plf:resizable-grip"></span>
</div>
<section class="plf:resizable-panel plf:flex plf:flex-col plf:gap-4">
<h3>Recent activity</h3>
<div class="plf:item">
<div class="plf:item-content">
<p class="plf:item-title">Monthly report is ready</p>
<p class="plf:item-description">Today at 09:42</p>
</div>
<span class="plf:badge">Report</span>
</div>
<div class="plf:item">
<div class="plf:item-content">
<p class="plf:item-title">Olivia upgraded to Pro</p>
<p class="plf:item-description">Today at 08:30</p>
</div>
</div>
<div class="plf:item">
<div class="plf:item-content">
<p class="plf:item-title">Weekly invoice processed</p>
<p class="plf:item-description">Yesterday at 16:15</p>
</div>
</div>
</section>
</div>import { Badge, Item, ItemContent, ItemDescription, Resizable, ResizableGrip, ResizableHandle, ResizablePanel } from '@pelatform/react';
export function Example() {
return (
<Resizable orientation="vertical" defaultSize={45} minSize={25} maxSize={75}>
<ResizablePanel className="flex flex-col gap-4">
<h3>Monthly summary</h3>
<div className="grid grid-cols-2 gap-4">
<div>
<p>Total revenue</p>
<strong>$18,420.00</strong>
</div>
<div>
<p>New customers</p>
<strong>126</strong>
</div>
</div>
</ResizablePanel>
<ResizableHandle>
<ResizableGrip />
</ResizableHandle>
<ResizablePanel className="flex flex-col gap-4">
<h3>Recent activity</h3>
<Item>
<ItemContent>
<p className="item-title">Monthly report is ready</p>
<ItemDescription>Today at 09:42</ItemDescription>
</ItemContent>
<Badge>Report</Badge>
</Item>
<Item>
<ItemContent>
<p className="item-title">Olivia upgraded to Pro</p>
<ItemDescription>Today at 08:30</ItemDescription>
</ItemContent>
</Item>
<Item>
<ItemContent>
<p className="item-title">Weekly invoice processed</p>
<ItemDescription>Yesterday at 16:15</ItemDescription>
</ItemContent>
</Item>
</ResizablePanel>
</Resizable>
);
}import { Badge, Item, ItemContent, ItemDescription, Resizable, ResizableGrip, ResizableHandle, ResizablePanel } from '@pelatform/react/prefixed';
export function Example() {
return (
<Resizable orientation="vertical" defaultSize={45} minSize={25} maxSize={75}>
<ResizablePanel className="plf:flex plf:flex-col plf:gap-4">
<h3>Monthly summary</h3>
<div className="plf:grid plf:grid-cols-2 plf:gap-4">
<div>
<p>Total revenue</p>
<strong>$18,420.00</strong>
</div>
<div>
<p>New customers</p>
<strong>126</strong>
</div>
</div>
</ResizablePanel>
<ResizableHandle>
<ResizableGrip />
</ResizableHandle>
<ResizablePanel className="plf:flex plf:flex-col plf:gap-4">
<h3>Recent activity</h3>
<Item>
<ItemContent>
<p className="plf:item-title">Monthly report is ready</p>
<ItemDescription>Today at 09:42</ItemDescription>
</ItemContent>
<Badge>Report</Badge>
</Item>
<Item>
<ItemContent>
<p className="plf:item-title">Olivia upgraded to Pro</p>
<ItemDescription>Today at 08:30</ItemDescription>
</ItemContent>
</Item>
<Item>
<ItemContent>
<p className="plf:item-title">Weekly invoice processed</p>
<ItemDescription>Yesterday at 16:15</ItemDescription>
</ItemContent>
</Item>
</ResizablePanel>
</Resizable>
);
}Sizes
The first panel’s size and bounds are enough: the second panel takes the rest.
Customers
Recent accounts
Olivia Martin
olivia@example.com
Jackson Lee
jackson@example.com
Sofia Davis
sofia@example.com
Customer details
Olivia Martin · Pro account
Overview
Active since January 2026. Monthly billing, with a dedicated workspace for design and reporting.
Lifetime revenue
$2,480.00Team members
12Each panel scrolls independently. On narrow screens, both panels remain readable in a stacked layout.
<div class="resizable" data-plf-resizable>
<section class="resizable-panel flex flex-col gap-4" data-plf-size="25" data-plf-min-size="20" data-plf-max-size="50">
<div>
<h3>Customers</h3>
<p>Recent accounts</p>
</div>
<div class="flex flex-col gap-4">
<div class="item">
<div class="item-content">
<p class="item-title">Olivia Martin</p>
<p class="item-description">olivia@example.com</p>
</div>
<span class="badge">Pro</span>
</div>
<div class="item">
<div class="item-content">
<p class="item-title">Jackson Lee</p>
<p class="item-description">jackson@example.com</p>
</div>
</div>
<div class="item">
<div class="item-content">
<p class="item-title">Sofia Davis</p>
<p class="item-description">sofia@example.com</p>
</div>
</div>
</div>
</section>
<div class="resizable-handle" hidden>
<span class="resizable-grip"></span>
</div>
<section class="resizable-panel flex flex-col gap-4">
<div>
<h3>Customer details</h3>
<p>Olivia Martin · Pro account</p>
</div>
<div>
<h4>Overview</h4>
<p>Active since January 2026. Monthly billing, with a dedicated workspace for design and reporting.</p>
</div>
<div class="grid grid-cols-2 gap-4">
<div>
<p>Lifetime revenue</p>
<strong>$2,480.00</strong>
</div>
<div>
<p>Team members</p>
<strong>12</strong>
</div>
</div>
<p>Each panel scrolls independently. On narrow screens, both panels remain readable in a stacked layout.</p>
</section>
</div><div class="plf:resizable" data-plf-resizable>
<section class="plf:resizable-panel plf:flex plf:flex-col plf:gap-4" data-plf-size="25" data-plf-min-size="20" data-plf-max-size="50">
<div>
<h3>Customers</h3>
<p>Recent accounts</p>
</div>
<div class="plf:flex plf:flex-col plf:gap-4">
<div class="plf:item">
<div class="plf:item-content">
<p class="plf:item-title">Olivia Martin</p>
<p class="plf:item-description">olivia@example.com</p>
</div>
<span class="plf:badge">Pro</span>
</div>
<div class="plf:item">
<div class="plf:item-content">
<p class="plf:item-title">Jackson Lee</p>
<p class="plf:item-description">jackson@example.com</p>
</div>
</div>
<div class="plf:item">
<div class="plf:item-content">
<p class="plf:item-title">Sofia Davis</p>
<p class="plf:item-description">sofia@example.com</p>
</div>
</div>
</div>
</section>
<div class="plf:resizable-handle" hidden>
<span class="plf:resizable-grip"></span>
</div>
<section class="plf:resizable-panel plf:flex plf:flex-col plf:gap-4">
<div>
<h3>Customer details</h3>
<p>Olivia Martin · Pro account</p>
</div>
<div>
<h4>Overview</h4>
<p>Active since January 2026. Monthly billing, with a dedicated workspace for design and reporting.</p>
</div>
<div class="plf:grid plf:grid-cols-2 plf:gap-4">
<div>
<p>Lifetime revenue</p>
<strong>$2,480.00</strong>
</div>
<div>
<p>Team members</p>
<strong>12</strong>
</div>
</div>
<p>Each panel scrolls independently. On narrow screens, both panels remain readable in a stacked layout.</p>
</section>
</div>import { Badge, Item, ItemContent, ItemDescription, Resizable, ResizableGrip, ResizableHandle, ResizablePanel } from '@pelatform/react';
export function Example() {
return (
<Resizable defaultSize={25} minSize={20} maxSize={50}>
<ResizablePanel className="flex flex-col gap-4">
<div>
<h3>Customers</h3>
<p>Recent accounts</p>
</div>
<div className="flex flex-col gap-4">
<Item>
<ItemContent>
<p className="item-title">Olivia Martin</p>
<ItemDescription>olivia@example.com</ItemDescription>
</ItemContent>
<Badge>Pro</Badge>
</Item>
<Item>
<ItemContent>
<p className="item-title">Jackson Lee</p>
<ItemDescription>jackson@example.com</ItemDescription>
</ItemContent>
</Item>
<Item>
<ItemContent>
<p className="item-title">Sofia Davis</p>
<ItemDescription>sofia@example.com</ItemDescription>
</ItemContent>
</Item>
</div>
</ResizablePanel>
<ResizableHandle>
<ResizableGrip />
</ResizableHandle>
<ResizablePanel className="flex flex-col gap-4">
<div>
<h3>Customer details</h3>
<p>Olivia Martin · Pro account</p>
</div>
<div>
<h4>Overview</h4>
<p>Active since January 2026. Monthly billing, with a dedicated workspace for design and reporting.</p>
</div>
<div className="grid grid-cols-2 gap-4">
<div>
<p>Lifetime revenue</p>
<strong>$2,480.00</strong>
</div>
<div>
<p>Team members</p>
<strong>12</strong>
</div>
</div>
<p>Each panel scrolls independently. On narrow screens, both panels remain readable in a stacked layout.</p>
</ResizablePanel>
</Resizable>
);
}import { Badge, Item, ItemContent, ItemDescription, Resizable, ResizableGrip, ResizableHandle, ResizablePanel } from '@pelatform/react/prefixed';
export function Example() {
return (
<Resizable defaultSize={25} minSize={20} maxSize={50}>
<ResizablePanel className="plf:flex plf:flex-col plf:gap-4">
<div>
<h3>Customers</h3>
<p>Recent accounts</p>
</div>
<div className="plf:flex plf:flex-col plf:gap-4">
<Item>
<ItemContent>
<p className="plf:item-title">Olivia Martin</p>
<ItemDescription>olivia@example.com</ItemDescription>
</ItemContent>
<Badge>Pro</Badge>
</Item>
<Item>
<ItemContent>
<p className="plf:item-title">Jackson Lee</p>
<ItemDescription>jackson@example.com</ItemDescription>
</ItemContent>
</Item>
<Item>
<ItemContent>
<p className="plf:item-title">Sofia Davis</p>
<ItemDescription>sofia@example.com</ItemDescription>
</ItemContent>
</Item>
</div>
</ResizablePanel>
<ResizableHandle>
<ResizableGrip />
</ResizableHandle>
<ResizablePanel className="plf:flex plf:flex-col plf:gap-4">
<div>
<h3>Customer details</h3>
<p>Olivia Martin · Pro account</p>
</div>
<div>
<h4>Overview</h4>
<p>Active since January 2026. Monthly billing, with a dedicated workspace for design and reporting.</p>
</div>
<div className="plf:grid plf:grid-cols-2 plf:gap-4">
<div>
<p>Lifetime revenue</p>
<strong>$2,480.00</strong>
</div>
<div>
<p>Team members</p>
<strong>12</strong>
</div>
</div>
<p>Each panel scrolls independently. On narrow screens, both panels remain readable in a stacked layout.</p>
</ResizablePanel>
</Resizable>
);
}Disabled
A disabled surrounding <fieldset> also blocks resizing.
Customers
Recent accounts
Olivia Martin
olivia@example.com
Jackson Lee
jackson@example.com
Sofia Davis
sofia@example.com
Customer details
Olivia Martin · Pro account
Overview
Active since January 2026. Monthly billing, with a dedicated workspace for design and reporting.
Lifetime revenue
$2,480.00Team members
12Each panel scrolls independently. On narrow screens, both panels remain readable in a stacked layout.
<div class="resizable" data-plf-resizable aria-disabled="true">
<section class="resizable-panel flex flex-col gap-4">
<div>
<h3>Customers</h3>
<p>Recent accounts</p>
</div>
<div class="flex flex-col gap-4">
<div class="item">
<div class="item-content">
<p class="item-title">Olivia Martin</p>
<p class="item-description">olivia@example.com</p>
</div>
<span class="badge">Pro</span>
</div>
<div class="item">
<div class="item-content">
<p class="item-title">Jackson Lee</p>
<p class="item-description">jackson@example.com</p>
</div>
</div>
<div class="item">
<div class="item-content">
<p class="item-title">Sofia Davis</p>
<p class="item-description">sofia@example.com</p>
</div>
</div>
</div>
</section>
<div class="resizable-handle" hidden>
<span class="resizable-grip"></span>
</div>
<section class="resizable-panel flex flex-col gap-4">
<div>
<h3>Customer details</h3>
<p>Olivia Martin · Pro account</p>
</div>
<div>
<h4>Overview</h4>
<p>Active since January 2026. Monthly billing, with a dedicated workspace for design and reporting.</p>
</div>
<div class="grid grid-cols-2 gap-4">
<div>
<p>Lifetime revenue</p>
<strong>$2,480.00</strong>
</div>
<div>
<p>Team members</p>
<strong>12</strong>
</div>
</div>
<p>Each panel scrolls independently. On narrow screens, both panels remain readable in a stacked layout.</p>
</section>
</div><div class="plf:resizable" data-plf-resizable aria-disabled="true">
<section class="plf:resizable-panel plf:flex plf:flex-col plf:gap-4">
<div>
<h3>Customers</h3>
<p>Recent accounts</p>
</div>
<div class="plf:flex plf:flex-col plf:gap-4">
<div class="plf:item">
<div class="plf:item-content">
<p class="plf:item-title">Olivia Martin</p>
<p class="plf:item-description">olivia@example.com</p>
</div>
<span class="plf:badge">Pro</span>
</div>
<div class="plf:item">
<div class="plf:item-content">
<p class="plf:item-title">Jackson Lee</p>
<p class="plf:item-description">jackson@example.com</p>
</div>
</div>
<div class="plf:item">
<div class="plf:item-content">
<p class="plf:item-title">Sofia Davis</p>
<p class="plf:item-description">sofia@example.com</p>
</div>
</div>
</div>
</section>
<div class="plf:resizable-handle" hidden>
<span class="plf:resizable-grip"></span>
</div>
<section class="plf:resizable-panel plf:flex plf:flex-col plf:gap-4">
<div>
<h3>Customer details</h3>
<p>Olivia Martin · Pro account</p>
</div>
<div>
<h4>Overview</h4>
<p>Active since January 2026. Monthly billing, with a dedicated workspace for design and reporting.</p>
</div>
<div class="plf:grid plf:grid-cols-2 plf:gap-4">
<div>
<p>Lifetime revenue</p>
<strong>$2,480.00</strong>
</div>
<div>
<p>Team members</p>
<strong>12</strong>
</div>
</div>
<p>Each panel scrolls independently. On narrow screens, both panels remain readable in a stacked layout.</p>
</section>
</div>import { Badge, Item, ItemContent, ItemDescription, Resizable, ResizableGrip, ResizableHandle, ResizablePanel } from '@pelatform/react';
export function Example() {
return (
<Resizable aria-disabled="true">
<ResizablePanel className="flex flex-col gap-4">
<div>
<h3>Customers</h3>
<p>Recent accounts</p>
</div>
<div className="flex flex-col gap-4">
<Item>
<ItemContent>
<p className="item-title">Olivia Martin</p>
<ItemDescription>olivia@example.com</ItemDescription>
</ItemContent>
<Badge>Pro</Badge>
</Item>
<Item>
<ItemContent>
<p className="item-title">Jackson Lee</p>
<ItemDescription>jackson@example.com</ItemDescription>
</ItemContent>
</Item>
<Item>
<ItemContent>
<p className="item-title">Sofia Davis</p>
<ItemDescription>sofia@example.com</ItemDescription>
</ItemContent>
</Item>
</div>
</ResizablePanel>
<ResizableHandle>
<ResizableGrip />
</ResizableHandle>
<ResizablePanel className="flex flex-col gap-4">
<div>
<h3>Customer details</h3>
<p>Olivia Martin · Pro account</p>
</div>
<div>
<h4>Overview</h4>
<p>Active since January 2026. Monthly billing, with a dedicated workspace for design and reporting.</p>
</div>
<div className="grid grid-cols-2 gap-4">
<div>
<p>Lifetime revenue</p>
<strong>$2,480.00</strong>
</div>
<div>
<p>Team members</p>
<strong>12</strong>
</div>
</div>
<p>Each panel scrolls independently. On narrow screens, both panels remain readable in a stacked layout.</p>
</ResizablePanel>
</Resizable>
);
}import { Badge, Item, ItemContent, ItemDescription, Resizable, ResizableGrip, ResizableHandle, ResizablePanel } from '@pelatform/react/prefixed';
export function Example() {
return (
<Resizable aria-disabled="true">
<ResizablePanel className="plf:flex plf:flex-col plf:gap-4">
<div>
<h3>Customers</h3>
<p>Recent accounts</p>
</div>
<div className="plf:flex plf:flex-col plf:gap-4">
<Item>
<ItemContent>
<p className="plf:item-title">Olivia Martin</p>
<ItemDescription>olivia@example.com</ItemDescription>
</ItemContent>
<Badge>Pro</Badge>
</Item>
<Item>
<ItemContent>
<p className="plf:item-title">Jackson Lee</p>
<ItemDescription>jackson@example.com</ItemDescription>
</ItemContent>
</Item>
<Item>
<ItemContent>
<p className="plf:item-title">Sofia Davis</p>
<ItemDescription>sofia@example.com</ItemDescription>
</ItemContent>
</Item>
</div>
</ResizablePanel>
<ResizableHandle>
<ResizableGrip />
</ResizableHandle>
<ResizablePanel className="plf:flex plf:flex-col plf:gap-4">
<div>
<h3>Customer details</h3>
<p>Olivia Martin · Pro account</p>
</div>
<div>
<h4>Overview</h4>
<p>Active since January 2026. Monthly billing, with a dedicated workspace for design and reporting.</p>
</div>
<div className="plf:grid plf:grid-cols-2 plf:gap-4">
<div>
<p>Lifetime revenue</p>
<strong>$2,480.00</strong>
</div>
<div>
<p>Team members</p>
<strong>12</strong>
</div>
</div>
<p>Each panel scrolls independently. On narrow screens, both panels remain readable in a stacked layout.</p>
</ResizablePanel>
</Resizable>
);
}Remember sizes
The script restores the size this browser saved, and saves each new one.
Files
index.html
styles.css
Editor
Drag the handle; the next visit opens at the same size.
<div class="resizable" data-plf-resizable id="resizable-editor">
<section class="resizable-panel flex flex-col gap-2">
<h3>Files</h3>
<p>index.html</p>
<p>styles.css</p>
</section>
<div class="resizable-handle" hidden>
<span class="resizable-grip"></span>
</div>
<section class="resizable-panel flex flex-col gap-2">
<h3>Editor</h3>
<p>Drag the handle; the next visit opens at the same size.</p>
</section>
</div>
<script>
const editor = document.getElementById('resizable-editor');
document.addEventListener('DOMContentLoaded', () => {
let size = 0;
try { size = Number(localStorage.getItem('editor-size')); } catch {}
if (size) PLF.Resizable.getOrCreateInstance(editor)?.setSizes([size, 100 - size]);
});
editor.addEventListener('plf:resizable:change', (event) => {
try { localStorage.setItem('editor-size', event.detail.sizes[0]); } catch {}
});
</script><div class="plf:resizable" data-plf-resizable id="resizable-editor">
<section class="plf:resizable-panel plf:flex plf:flex-col plf:gap-2">
<h3>Files</h3>
<p>index.html</p>
<p>styles.css</p>
</section>
<div class="plf:resizable-handle" hidden>
<span class="plf:resizable-grip"></span>
</div>
<section class="plf:resizable-panel plf:flex plf:flex-col plf:gap-2">
<h3>Editor</h3>
<p>Drag the handle; the next visit opens at the same size.</p>
</section>
</div>
<script>
const editor = document.getElementById('resizable-editor');
document.addEventListener('DOMContentLoaded', () => {
let size = 0;
try { size = Number(localStorage.getItem('editor-size')); } catch {}
if (size) PLF.Resizable.getOrCreateInstance(editor)?.setSizes([size, 100 - size]);
});
editor.addEventListener('plf:resizable:change', (event) => {
try { localStorage.setItem('editor-size', event.detail.sizes[0]); } catch {}
});
</script>'use client';
import { useEffect, useState } from 'react';
import { Resizable, ResizableGrip, ResizableHandle, ResizablePanel } from '@pelatform/react';
export function Example() {
const [size, setSize] = useState(50);
// Restores the size this browser saved, once the page has loaded.
useEffect(() => {
let saved = 0;
try { saved = Number(localStorage.getItem('editor-size')); } catch {}
if (saved) setSize(saved);
}, []);
return (
<Resizable
size={size}
onSizeChange={next => {
setSize(next);
try { localStorage.setItem('editor-size', String(next)); } catch {}
}}
>
<ResizablePanel className="flex flex-col gap-2">
<h3>Files</h3>
<p>index.html</p>
<p>styles.css</p>
</ResizablePanel>
<ResizableHandle>
<ResizableGrip />
</ResizableHandle>
<ResizablePanel className="flex flex-col gap-2">
<h3>Editor</h3>
<p>Drag the handle; the next visit opens at the same size.</p>
</ResizablePanel>
</Resizable>
);
}'use client';
import { useEffect, useState } from 'react';
import { Resizable, ResizableGrip, ResizableHandle, ResizablePanel } from '@pelatform/react/prefixed';
export function Example() {
const [size, setSize] = useState(50);
// Restores the size this browser saved, once the page has loaded.
useEffect(() => {
let saved = 0;
try { saved = Number(localStorage.getItem('editor-size')); } catch {}
if (saved) setSize(saved);
}, []);
return (
<Resizable
size={size}
onSizeChange={next => {
setSize(next);
try { localStorage.setItem('editor-size', String(next)); } catch {}
}}
>
<ResizablePanel className="plf:flex plf:flex-col plf:gap-2">
<h3>Files</h3>
<p>index.html</p>
<p>styles.css</p>
</ResizablePanel>
<ResizableHandle>
<ResizableGrip />
</ResizableHandle>
<ResizablePanel className="plf:flex plf:flex-col plf:gap-2">
<h3>Editor</h3>
<p>Drag the handle; the next visit opens at the same size.</p>
</ResizablePanel>
</Resizable>
);
}JavaScript
Resizable needs JavaScript. The Full script (pelatform-ui.min.js) starts every component on page load, with no code of your own; with ESM imports, call init() yourself, as in Installation. For markup you add later, see Dynamic content.
<link rel="stylesheet" href="pelatform-ui.min.css">
<script src="pelatform-ui.min.js" defer></script><link rel="stylesheet" href="core/pelatform-ui-core.min.css">
<link rel="stylesheet" href="components/badge.min.css">
<link rel="stylesheet" href="components/item.min.css">
<link rel="stylesheet" href="components/resizable.min.css">
<script src="core/pelatform-ui-core.min.js" defer></script>
<script src="components/resizable.min.js" defer></script>
<script>document.addEventListener('DOMContentLoaded', () => PLF.init());</script><link rel="stylesheet" href="pelatform-ui.prefixed.min.css">
<script src="pelatform-ui.min.js" defer></script><link rel="stylesheet" href="core/pelatform-ui-core.prefixed.min.css">
<link rel="stylesheet" href="components/badge.prefixed.min.css">
<link rel="stylesheet" href="components/item.prefixed.min.css">
<link rel="stylesheet" href="components/resizable.prefixed.min.css">
<script src="core/pelatform-ui-core.min.js" defer></script>
<script src="components/resizable.min.js" defer></script>
<script>document.addEventListener('DOMContentLoaded', () => PLF.init());</script>| Attribute | Purpose |
|---|---|
data-plf-resizable |
Marks the group |
data-plf-orientation |
horizontal (default) or vertical |
data-plf-size |
On a panel: its starting size in percent; 50 by default. One panel’s size is enough, and two must total 100 |
data-plf-min-size, data-plf-max-size |
On a panel: its bounds in percent; 15 and 85 by default. The second panel’s bounds follow from the first’s unless it gives its own |
data-plf-stack-at |
On the group: the width in pixels below which the panels stack and the handle hides; 480 by default, 0 never stacks |
aria-disabled="true" |
On the group: blocks resizing |
The script shows the handle and sets its role="separator", aria-orientation, aria-controls, aria-value* and tabindex; it adds the panels’ ids, tabindex="0" and their names from their first headings, and the handle’s name, when the markup leaves them out.
Methods
| Method | Behavior |
|---|---|
PLF. |
Returns the instance, creating it for valid markup. options sets orientation, sizes, minSizes, maxSizes (pairs) or stackAt, ahead of the attributes |
PLF. |
Returns the instance or null |
instance. |
Sets sizes that total 100, kept within the bounds. Returns false when unchanged, invalid, canceled or disabled |
instance. |
Returns [first, second] |
instance. |
Returns {sizes, minSizes, maxSizes, orientation, stackAt, stacked, disabled} |
instance. |
Ends a drag, removes listeners and restores the attributes and styles the script set |
| Event | When |
|---|---|
plf: |
Before the sizes change; cancelable |
plf: |
After the sizes change |
Each event’s detail:
| Property | Value |
|---|---|
instance |
The Resizable instance |
reason |
api, keyboard or pointer |
trigger |
The handle, or null from a method |
previousSizes |
The sizes before the change, [first, second] in percent |
sizes |
The new sizes, [first, second] in percent |
| Key | Action |
|---|---|
| Left Arrow, Right Arrow | Move a horizontal handle 1% |
| Up Arrow, Down Arrow | Move a vertical handle 1% |
| Shift with an arrow | Moves 10% |
| Home, End | Shrink or grow the first panel to its bound |
| Escape | During a drag, returns to the starting sizes |
React
Resizable from @pelatform/react renders the two panels and the handle with the names and ARIA the script adds, and moves the handle with a drag or the keys: it keeps the first panel’s size, or the application sets it with size, and each part is a component of its own.
| Prop | Values | Default |
|---|---|---|
size |
The first panel’s size in percent, which the application changes in onSizeChange; keeping it refuses the move |
Its own state |
defaultSize |
The first panel’s starting size when the application does not set size; the second panel takes the rest |
50 |
onSizeChange |
(size), called when a drag or a key moves the handle |
None |
minSize, maxSize |
The first panel’s bounds in percent; the second panel’s follow from them | 15 and 85 |
orientation |
horizontal, vertical |
horizontal |
stackAt |
The width in pixels below which the panels stack and the handle hides; 0 never stacks |
480 |
| Part | Element |
|---|---|
ResizablePanel |
A section with resizable-panel, the first and the last child, named by its first heading written as an element, such as <h3>, unless given aria-label or aria-labelledby |
ResizableHandle |
A div with resizable-handle between the panels, named after the first panel unless given a name |
ResizableGrip |
A span with resizable-grip, which draws the grip; an Icon inside takes its place |
The other props are the element’s own, className and ref included; aria-disabled="true" on Resizable, or a disabled fieldset around it, blocks resizing.
| Variable | Default |
|---|---|
--plf-resizable-height |
24rem (384px) |
--plf-resizable-panel-padding |
Space 4, 1rem (16px) |
--plf-resizable-handle-thickness |
24px |
--plf-resizable-icon-size |
--plf-control-icon-size (16px) |
--plf-resizable-border |
Subtle border |
--plf-resizable-radius |
--plf-radius-lg, 0. (8px) |
--plf-resizable-bg |
Transparent |
--plf-resizable-handle-color |
Muted text |