Resizable
A component for building resizable panel groups with draggable separators.
Overview
Resizable creates panel layouts with draggable separators. It does not own a panel background, border, radius, or shadow; wrap it in Card, Surface, or an app-owned container when you need a framed area. The examples below use consumer-painted frame classes with SurfaceProvider so the resize handle reads the matching surface context.
Usage
import {
ResizableHandle,
ResizablePanel,
ResizablePanelGroup,
} from "@tilt-legal/cubitt-components/resizable";
import { SurfaceProvider } from "@tilt-legal/cubitt-components/utilities";<SurfaceProvider level={3}>
<ResizablePanelGroup
className="h-full min-h-80 w-full overflow-hidden rounded-xl border border-border-3 bg-surface-3"
orientation="horizontal"
>
<ResizablePanel>One</ResizablePanel>
<ResizableHandle />
<ResizablePanel>Two</ResizablePanel>
</ResizablePanelGroup>
</SurfaceProvider>Examples
Vertical
Use orientation="vertical" to stack panels vertically.
import {
ResizableHandle,
ResizablePanel,
ResizablePanelGroup,
} from "@tilt-legal/cubitt-components/resizable";
import { SurfaceProvider } from "@tilt-legal/cubitt-components/utilities";
export default function Component() {
return (
<SurfaceProvider level={3}>
<ResizablePanelGroup
className="h-full min-h-80 w-full overflow-hidden rounded-xl border border-border-3 bg-surface-3"
orientation="vertical"
>
<ResizablePanel defaultSize={25}>
<div className="flex h-full items-center justify-center p-6">
<span className="font-medium">Header</span>
</div>
</ResizablePanel>
<ResizableHandle />
<ResizablePanel defaultSize={75}>
<div className="flex h-full items-center justify-center p-6">
<span className="font-medium">Content</span>
</div>
</ResizablePanel>
</ResizablePanelGroup>
</SurfaceProvider>
);
}With Handle
Add withHandle to display a visible grip on the resize separator.
import {
ResizableHandle,
ResizablePanel,
ResizablePanelGroup,
} from "@tilt-legal/cubitt-components/resizable";
import { SurfaceProvider } from "@tilt-legal/cubitt-components/utilities";
export default function Component() {
return (
<SurfaceProvider level={3}>
<ResizablePanelGroup
className="h-full min-h-80 w-full overflow-hidden rounded-xl border border-border-3 bg-surface-3"
orientation="horizontal"
>
<ResizablePanel defaultSize={50}>
<div className="flex h-full items-center justify-center p-6">
<span className="font-medium">One</span>
</div>
</ResizablePanel>
<ResizableHandle withHandle />
<ResizablePanel defaultSize={50}>
<div className="flex h-full items-center justify-center p-6">
<span className="font-medium">Two</span>
</div>
</ResizablePanel>
</ResizablePanelGroup>
</SurfaceProvider>
);
}Pixel-Based Sizing
Use numeric values for pixel-based constraints. The second panel fills the remaining space.
import {
ResizableHandle,
ResizablePanel,
ResizablePanelGroup,
} from "@tilt-legal/cubitt-components/resizable";
import { SurfaceProvider } from "@tilt-legal/cubitt-components/utilities";
export default function Component() {
return (
<SurfaceProvider level={3}>
<ResizablePanelGroup
className="h-full min-h-80 w-full overflow-hidden rounded-xl border border-border-3 bg-surface-3"
orientation="horizontal"
>
<ResizablePanel defaultSize={280} maxSize={400} minSize={200}>
<div className="flex h-full items-center justify-center p-6">
<span className="font-medium">Fixed Sidebar (280px)</span>
</div>
</ResizablePanel>
<ResizableHandle withHandle />
<ResizablePanel>
<div className="flex h-full items-center justify-center p-6">
<span className="font-medium">Flexible Content</span>
</div>
</ResizablePanel>
</ResizablePanelGroup>
</SurfaceProvider>
);
}API Reference
ResizablePanelGroup
Container component that manages the resizable panel layout.
| Prop | Type | Default | Description |
|---|---|---|---|
orientation | "horizontal" | "vertical" | "horizontal" | The panel layout direction. |
onLayoutChange | (layout: Layout) => void | - | Callback when panel sizes change. |
className | string | - | Additional classes for layout sizing and app-owned framing. |
ResizablePanel
Panel size props accept percentages, pixels, relative font units, and viewport units. Numeric values are treated as pixels, while strings without units are treated as percentages.
| Prop | Type | Default | Description |
|---|---|---|---|
defaultSize | number | string | - | Initial size. |
minSize | number | string | - | Minimum size constraint. |
maxSize | number | string | - | Maximum size constraint. |
collapsible | boolean | false | Whether the panel can collapse. |
collapsedSize | number | string | - | Size when collapsed. |
onResize | (size) => void | - | Callback when the panel is resized. |
className | string | - | Additional classes for panel content layout. |
ResizableHandle
Draggable separator between panels.
| Prop | Type | Default | Description |
|---|---|---|---|
withHandle | boolean | React.ReactNode | false | Shows the default grip when true, or renders a custom grip element. |
disabled | boolean | false | Disables resizing through this handle. |
className | string | - | Additional classes for the separator. |
Hooks
useResizablePanelRef
Get a ref to imperatively control a panel.
import { useResizablePanelRef } from "@tilt-legal/cubitt-components/resizable";
function Component() {
const panelRef = useResizablePanelRef();
return (
<ResizablePanelGroup orientation="horizontal">
<ResizablePanel collapsible panelRef={panelRef}>
Sidebar
</ResizablePanel>
<ResizableHandle />
<ResizablePanel>Content</ResizablePanel>
</ResizablePanelGroup>
);
}useResizableGroupRef
Get a ref to imperatively control the entire group layout.
import { useResizableGroupRef } from "@tilt-legal/cubitt-components/resizable";
function Component() {
const groupRef = useResizableGroupRef();
return (
<ResizablePanelGroup groupRef={groupRef} orientation="horizontal">
<ResizablePanel id="left">Left</ResizablePanel>
<ResizableHandle />
<ResizablePanel id="right">Right</ResizablePanel>
</ResizablePanelGroup>
);
}useResizableDefaultLayout
Persist and restore layouts to storage.
import { useResizableDefaultLayout } from "@tilt-legal/cubitt-components/resizable";
function Component() {
const { defaultLayout } = useResizableDefaultLayout({
panelIds: ["sidebar", "content"],
storage: localStorage,
});
return (
<ResizablePanelGroup defaultLayout={defaultLayout} orientation="horizontal">
<ResizablePanel defaultSize={280} id="sidebar">
Sidebar
</ResizablePanel>
<ResizableHandle />
<ResizablePanel id="content">Content</ResizablePanel>
</ResizablePanelGroup>
);
}Types
import type {
ResizableLayout,
ResizablePanelGroupHandle,
ResizablePanelHandle,
ResizablePanelSize,
} from "@tilt-legal/cubitt-components/resizable";Credits
Built with react-resizable-panels.