Resizable
Accessible resizable panel groups and layouts with keyboard support.
Powered by
Installation
bash
npx shadcn@latest add @redpanda/resizablebash
pnpm dlx shadcn@latest add @redpanda/resizablebash
yarn dlx shadcn@latest add @redpanda/resizablebash
bunx shadcn@latest add @redpanda/resizablebash
nubx shadcn@latest add @redpanda/resizablebash
aube dlx shadcn@latest add @redpanda/resizableWhen to use
Resizable panels create flexible layouts where users can adjust the size of content areas. Use this decision tree to determine when resizable panels are appropriate:
Usage
Basic Horizontal Layout
tsx
import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from '@/components/redpanda-ui/resizable';
<ResizablePanelGroup orientation="horizontal" className="min-h-[200px]"> <ResizablePanel defaultSize="50%"> <div className="flex h-full items-center justify-center p-6"> <span className="font-semibold">Left Panel</span> </div> </ResizablePanel> <ResizableHandle /> <ResizablePanel defaultSize="50%"> <div className="flex h-full items-center justify-center p-6"> <span className="font-semibold">Right Panel</span> </div> </ResizablePanel></ResizablePanelGroup>;With Size Constraints
tsx
<ResizablePanelGroup orientation="horizontal" className="min-h-[200px]"> <ResizablePanel defaultSize="25%" minSize="20%" maxSize="40%"> <div className="flex h-full items-center justify-center p-6"> <span className="font-semibold">Sidebar (20-40%)</span> </div> </ResizablePanel> <ResizableHandle withHandle /> <ResizablePanel defaultSize="75%"> <div className="flex h-full items-center justify-center p-6"> <span className="font-semibold">Main Content</span> </div> </ResizablePanel></ResizablePanelGroup>Three Panel Layout
tsx
<ResizablePanelGroup orientation="horizontal" className="min-h-[200px]"> <ResizablePanel defaultSize="20%" minSize="15%"> <div className="flex h-full items-center justify-center p-6"> <span className="font-semibold">Nav</span> </div> </ResizablePanel> <ResizableHandle /> <ResizablePanel defaultSize="60%"> <div className="flex h-full items-center justify-center p-6"> <span className="font-semibold">Content</span> </div> </ResizablePanel> <ResizableHandle /> <ResizablePanel defaultSize="20%" minSize="15%"> <div className="flex h-full items-center justify-center p-6"> <span className="font-semibold">Sidebar</span> </div> </ResizablePanel></ResizablePanelGroup>Nested Layouts
tsx
<ResizablePanelGroup orientation="vertical" className="min-h-[400px]"> <ResizablePanel defaultSize="25%"> <div className="flex h-full items-center justify-center p-6"> <span className="font-semibold">Header</span> </div> </ResizablePanel> <ResizableHandle /> <ResizablePanel defaultSize="75%"> <ResizablePanelGroup orientation="horizontal"> <ResizablePanel defaultSize="30%"> <div className="flex h-full items-center justify-center p-6"> <span className="font-semibold">Sidebar</span> </div> </ResizablePanel> <ResizableHandle withHandle /> <ResizablePanel defaultSize="70%"> <div className="flex h-full items-center justify-center p-6"> <span className="font-semibold">Main Content</span> </div> </ResizablePanel> </ResizablePanelGroup> </ResizablePanel></ResizablePanelGroup>Anatomy
The Resizable component system is built with react-resizable-panels and provides a flexible layout system:
plaintext
<ResizablePanelGroup> (Container)├── orientation="horizontal" | "vertical"├── Layout Management│ ├── Size distribution│ ├── Constraint enforcement│ └── Resize calculations├── <ResizablePanel> (Content Areas)│ ├── Size Properties│ │ ├── defaultSize - initial size percentage│ │ ├── minSize - minimum size percentage│ │ └── maxSize - maximum size percentage│ ├── Content Container│ └── Flex/Grid Positioning└── <ResizableHandle> (Resize Controls) ├── Visual Divider - 1px border line ├── Interaction Area - invisible expanded hit area ├── Handle Indicator (optional) │ ├── <GripVertical> icon │ └── Rounded border container ├── Keyboard Support │ ├── Arrow keys for adjustment │ └── Home/End for min/max └── Mouse/Touch Support ├── Drag interaction └── Double-click reset
Data Attributes:├── [aria-orientation] - horizontal/vertical├── [data-resize-handle-active] - during resize└── [data-resize-handle-state] - drag/hover/idleKey Features:
- Flexible Sizing: Percentage-based with constraints
- Keyboard Accessible: Full keyboard navigation support
- Touch Friendly: Works on mobile devices
- Nested Layouts: Supports complex nested arrangements
- Persistent State: Can save/restore layout configurations
- Smooth Animations: Smooth resize transitions
Examples
Vertical
Use the orientation prop to set the direction of the resizable panels.
tsx
import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from '@/components/ui/resizable';
export default function Example() { return ( <ResizablePanelGroup orientation="vertical"> <ResizablePanel>One</ResizablePanel> <ResizableHandle /> <ResizablePanel>Two</ResizablePanel> </ResizablePanelGroup> );}Handle
You can set or hide the handle by using the withHandle prop on the ResizableHandle component.
tsx
import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from '@/components/ui/resizable';
export default function Example() { return ( <ResizablePanelGroup orientation="horizontal"> <ResizablePanel>One</ResizablePanel> <ResizableHandle withHandle /> <ResizablePanel>Two</ResizablePanel> </ResizablePanelGroup> );}Credits
- We use react-resizable-panels for the resizable component.
- We take our inspiration from Shadcn UI for the resizable style.