Redpanda UI
RC
Redpanda UI

Resizable

Accessible resizable panel groups and layouts with keyboard support.

Made by bvaughn
Loading component...

When 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:

Installation

Usage

Basic Horizontal Layout

import {
  ResizableHandle,
  ResizablePanel,
  ResizablePanelGroup,
} from "@/components/redpanda-ui/resizable"

<ResizablePanelGroup direction="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

<ResizablePanelGroup direction="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

<ResizablePanelGroup direction="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

<ResizablePanelGroup direction="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 direction="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:

<ResizablePanelGroup> (Container)
├── direction="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:
├── [data-panel-group-direction] - horizontal/vertical
├── [data-resize-handle-active] - during resize
└── [data-resize-handle-state] - drag/hover/idle

Key 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 direction prop to set the direction of the resizable panels.

Loading component...
import {
  ResizableHandle,
  ResizablePanel,
  ResizablePanelGroup,
} from "@/components/ui/resizable"

export default function Example() {
  return (
    <ResizablePanelGroup direction="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.

Loading component...
import {
  ResizableHandle,
  ResizablePanel,
  ResizablePanelGroup,
} from "@/components/ui/resizable"

export default function Example() {
  return (
    <ResizablePanelGroup direction="horizontal">
      <ResizablePanel>One</ResizablePanel>
      <ResizableHandle withHandle />
      <ResizablePanel>Two</ResizablePanel>
    </ResizablePanelGroup>
  )
}

Credits

Built by malinskibeniamin. The source code is available on GitHub.

On this page