Skip to Content
ComponentsResizable

Resizable

Panels the user can drag apart: a file tree next to an editor, a list next to a preview. Built on react-resizable-panels .

Live Examples

Live Example
☀️
Copy
View Code
import { ResizablePanelGroup, ResizablePanel, ResizableHandle } from '@jarllyng/nostromo' export default function ResizableExample() { return ( <div className="h-48 rounded-lg border border-border"> <ResizablePanelGroup orientation="horizontal"> <ResizablePanel defaultSize="30" minSize="20"> <div className="flex h-full items-center justify-center p-4 text-sm">Sidebar</div> </ResizablePanel>...

Stacked, and nested

Live Example
☀️
Copy
View Code
import { ResizablePanelGroup, ResizablePanel, ResizableHandle } from '@jarllyng/nostromo' export default function ResizableNested() { return ( <div className="h-64 rounded-lg border border-border"> <ResizablePanelGroup orientation="horizontal"> <ResizablePanel defaultSize="40"> <div className="flex h-full items-center justify-center p-4 text-sm">Left</div> </ResizablePanel>...

Collapsible

Live Example
☀️
Copy
View Code
import { ResizablePanelGroup, ResizablePanel, ResizableHandle } from '@jarllyng/nostromo' export default function ResizableCollapsible() { return ( <div className="h-48 rounded-lg border border-border"> <ResizablePanelGroup orientation="horizontal"> <ResizablePanel defaultSize="25" minSize="15" collapsible collapsedSize="0"> <div className="flex h-full items-center justify-center p-4 text-sm">Drag me shut</div> </ResizablePanel>...

Import

import { ResizablePanelGroup, ResizablePanel, ResizableHandle, } from "@jarllyng/nostromo";

Props

ResizablePanelGroup

PropTypeDefaultDescription
orientation"horizontal" | "vertical""horizontal"Which way the panels are laid out
defaultLayoutLayout-Restore a saved layout
onLayoutChanged(layout: Layout) => void-Fires when a drag ends, for saving
disabledbooleanfalseNothing can be resized

ResizablePanel

PropTypeDefaultDescription
defaultSizenumber | stringEven splitA number is pixels, a bare string is percent
minSizenumber | string0Lower bound
maxSizenumber | string"100%"Upper bound
collapsiblebooleanfalseCan be dragged shut past minSize
collapsedSizenumber | string0Size when collapsed

ResizableHandle

PropTypeDefaultDescription
withHandlebooleanfalseDraw a grip on the divider
disabledbooleanfalseThis divider cannot be dragged

Sizes are numbers for pixels and strings for percent: defaultSize={200} is 200 pixels, defaultSize="50" is half. Explicit units work too, "20rem" for instance.

Give the group’s parent a height

The group sets display, flex-direction, width: 100% and height: 100% as inline styles. Inline styles beat classes, so this does nothing at all:

<ResizablePanelGroup className="h-96">

The class lands on the element and is then overridden, with no warning. Put the height on the element around the group, which is what the examples above do, or pass it as a style, which merges:

<ResizablePanelGroup style={{ height: "24rem" }}>

For the same reason ResizablePanelGroup adds no layout classes of its own. A flex or a flex-direction switch would be dead CSS.

A class on a panel lands inside it

ResizablePanel renders a wrapper the library controls with flex, and puts your className on a child inside it. That is deliberate upstream: it stops padding and borders from fighting the flex sizing. A background on a panel paints the inner box, which is what you want anyway.

Keyboard

The divider is a real separator with a tab stop and aria-valuenow. Arrow keys resize it, Home and End send it to its limits, and Enter collapses or restores a collapsible panel. That is the reason to use the library rather than a div with a mousedown handler.

aria-orientation on the divider is the divider’s own axis, not the group’s: two panels side by side are separated by a vertical line, so a horizontal group reports aria-orientation="vertical".

Last updated on