Skip to content
Primitives

Resizable

Draggable split panes with a signal-armed seam and an optional sharp grip reticle; horizontal or vertical.

● LIVE
SEC // NAV
CH-01
SEC // VIEWPORT
CH-02
SEC // READOUT
CH-03
npx shadcn@latest add https://okibi.cndr.dev/r/resizable.json

Installation

Install the theme first, then add the component:

npx shadcn@latest add https://okibi.cndr.dev/r/resizable.json

Install the required dependencies:

npm install lucide-react react-resizable-panels

Copy the source from the Code tab above into components/ui/resizable.tsx. It uses the cn helper and the okibi theme tokens — install the theme first if you haven't.

Usage

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

<ResizablePanelGroup orientation="horizontal">
  <ResizablePanel defaultSize={50}>One</ResizablePanel>
  <ResizableHandle withHandle />
  <ResizablePanel defaultSize={50}>Two</ResizablePanel>
</ResizablePanelGroup>

Anatomy

<ResizablePanelGroup orientation="horizontal">  {/* sets the split axis */}
  <ResizablePanel defaultSize={50} />            {/* sizing via defaultSize/minSize */}
  <ResizableHandle withHandle />                 {/* draggable seam + grip reticle */}
  <ResizablePanel defaultSize={50} />
</ResizablePanelGroup>

Examples

Vertical

Set orientation="vertical" on the group to stack panels and resize along the Y axis — the grip reticle rotates to follow the seam. Nest a vertical group inside a horizontal panel (as the main demo does) for grid layouts.

● LIVE
CH-01
CH-02

Handle

Pass withHandle to render the sharp grip reticle on the seam — an always-visible drag affordance that arms to signal on hover and drag. Omit it for a minimal hairline seam (the library still provides a wide, accessible hit-target either way).

● LIVE
SEC-A
SEC-B

API Reference

ResizablePanelGroup

PropTypeDefaultDescription
orientation"horizontal" | "vertical""horizontal"Split axis. (The okibi wrapper exposes orientation, not the library's direction.)

ResizableHandle

PropTypeDefaultDescription
withHandlebooleanfalseRender the sharp grip reticle on the seam.

Accessibility

  • Built on react-resizable-panels v4, which ships full keyboard resize on the handle: arrow keys nudge the split and Home/End jump to the extremes.
  • The seam takes the standard square signal focus ring (ring-2 ring-ring with offset) so keyboard focus on the resize handle is always visible.
  • Set withHandle to render the grip reticle — a clear visual affordance that the seam is a draggable, focusable control.
  • The library owns a wider hit-target than the 1px visual seam, so the drag and focus zone stays comfortable without manual padding.
  • Orientation is threaded through context (the v4 Group owns orientation), so the handle lays its seam and rotates the grip on the correct axis for keyboard and pointer alike.

Guidelines

Do

  • Stack panes vertically with orientation='vertical' on the group — that is the prop the okibi wrapper reads.
  • Add withHandle when the seam is the primary interaction, so the grip reticle signals it is draggable.
  • Set sensible minSize/defaultSize on panels so a drag can't collapse content to an unusable sliver.

Don't

  • Do not pass direction — the library's prop is shadowed here; the wrapper consumes orientation and the rest is ignored.
  • Do not wrap the seam in your own hit-target padding; the library already widens the drag zone past the 1px rule.
  • Do not put a resizable group inside an auto-height container — it needs a bounded h-full/w-full parent to compute splits.

On this page