Resizable

A component for building resizable panel groups with draggable handles.

Overview

The Resizable component provides a flexible system for creating resizable panel layouts. Built on react-resizable-panels, it supports horizontal and vertical orientations, customizable handles, and flexible sizing constraints.

Usage

import { ResizablePanelGroup, ResizablePanel, ResizableHandle } from "@tilt-legal/cubitt-components/primitives";
<ResizablePanelGroup orientation="horizontal">
  <ResizablePanel>One</ResizablePanel>
  <ResizableHandle />
  <ResizablePanel>Two</ResizablePanel>
</ResizablePanelGroup>

Examples

Vertical

Use orientation="vertical" to stack panels vertically.

With Handle

Add withHandle to display a visible drag handle on the resize bar.

Custom Handle

Pass a custom React element to withHandle for full control over the handle appearance.

Pixel-Based Sizing

Use numeric values for pixel-based constraints. The second panel automatically fills remaining space.


API Reference

ResizablePanelGroup

Container component that manages the resizable panel layout.

PropTypeDefaultDescription
orientation"horizontal" | "vertical""horizontal"The orientation of the panel layout.
onLayoutChange(layout: Layout) => voidCallback when panel sizes change.
classNamestringAdditional CSS classes for the panel group.

ResizablePanel

Individual panel within the group.

Size props accept flexible units:

  • Numbers are pixels (e.g., defaultSize={420} = 420px)
  • Strings without units are percentages (e.g., defaultSize="50" = 50%)
  • Strings with units use that unit (e.g., "10rem", "50vh")
PropTypeDefaultDescription
defaultSizenumber | stringInitial size (pixels, percentage, or CSS unit).
minSizenumber | stringMinimum size constraint.
maxSizenumber | stringMaximum size constraint.
collapsiblebooleanfalseWhether the panel can be collapsed.
collapsedSizenumber | stringSize when collapsed.
onResize(size) => voidCallback when panel is resized.
classNamestringAdditional CSS classes for the panel.

ResizableHandle

Draggable handle between panels.

PropTypeDefaultDescription
withHandleboolean | React.ReactNodefalseShow a visible grip handle. Pass true for default, or a custom element.
disabledbooleanfalseDisable resizing via this handle.
classNamestringAdditional CSS classes for the handle.

Hooks

useResizablePanelRef

Get a ref to imperatively control a panel (collapse, expand, resize).

import { useResizablePanelRef } from "@tilt-legal/cubitt-components/primitives";

function Component() {
  const panelRef = useResizablePanelRef();

  return (
    <ResizablePanelGroup orientation="horizontal">
      <ResizablePanel panelRef={panelRef} collapsible>
        Sidebar
      </ResizablePanel>
      <ResizableHandle />
      <ResizablePanel>Content</ResizablePanel>
    </ResizablePanelGroup>
  );
}

// Imperative methods:
panelRef.current?.collapse(); // Collapse the panel
panelRef.current?.expand(); // Expand the panel
panelRef.current?.isCollapsed(); // Check if collapsed
panelRef.current?.getSize(); // { asPercentage: number, inPixels: number }

useResizableGroupRef

Get a ref to imperatively control the entire group layout.

import { useResizableGroupRef } from "@tilt-legal/cubitt-components/primitives";

function Component() {
  const groupRef = useResizableGroupRef();

  const resetLayout = () => {
    groupRef.current?.setLayout({ left: 30, right: 70 });
  };

  return (
    <ResizablePanelGroup groupRef={groupRef} orientation="horizontal">
      <ResizablePanel id="left">Left</ResizablePanel>
      <ResizableHandle />
      <ResizablePanel id="right">Right</ResizablePanel>
    </ResizablePanelGroup>
  );
}

// Imperative methods:
groupRef.current?.getLayout();          // { [panelId]: percentage }
groupRef.current?.setLayout({ ... });   // Set new layout by panel IDs

useResizableDefaultLayout

Persist and restore layouts to storage (localStorage, sessionStorage, or custom).

import { useResizableDefaultLayout } from "@tilt-legal/cubitt-components/primitives";

function Component() {
  const { defaultLayout } = useResizableDefaultLayout({
    panelIds: ["sidebar", "content"],
    storage: localStorage,
  });

  return (
    <ResizablePanelGroup defaultLayout={defaultLayout} orientation="horizontal">
      <ResizablePanel id="sidebar" defaultSize={280}>
        Sidebar
      </ResizablePanel>
      <ResizableHandle />
      <ResizablePanel id="content">Content</ResizablePanel>
    </ResizablePanelGroup>
  );
}

Types

import type {
  ResizablePanelGroupHandle,
  ResizablePanelHandle,
  ResizableLayout,
  ResizablePanelSize,
} from "@tilt-legal/cubitt-components/primitives";

Credits

Built with react-resizable-panels.

On this page