shadcn.io is not affiliated with official shadcn/ui
Shadcn Resizable for React and Tailwind
Divides the interface into resizable sections.
One
Two
Three
Installation
bunx --bun shadcn@latest add https://kit.dev/r/resizable.jsonpnpm dlx shadcn@latest add https://kit.dev/r/resizable.jsonnpx shadcn@latest add https://kit.dev/r/resizable.jsonyarn shadcn@latest add https://kit.dev/r/resizable.jsonInstall the following dependencies:
bun add @ark-ui/react lucide-reactpnpm add @ark-ui/react lucide-reactnpm install @ark-ui/react lucide-reactyarn add @ark-ui/react lucide-reactCopy and paste the following code into your project.
"use client";
import {
Splitter as ArkSplitter,
useSplitterContext,
} from "@ark-ui/react/splitter";
import { GripVertical } from "lucide-react";
import type React from "react";
import { cn } from "@/lib/utils";
export const useResizable = useSplitterContext;
export const Resizable = (
props: React.ComponentProps<typeof ArkSplitter.Root>
) => {
const { className, ...rest } = props;
return (
<ArkSplitter.Root
className={cn("flex size-full", className)}
data-slot="resizable"
{...rest}
/>
);
};
export const ResizablePanel = (
props: React.ComponentProps<typeof ArkSplitter.Panel>
) => <ArkSplitter.Panel data-slot="resizable-panel" {...props} />;
interface ResizableResizeTriggerProps
extends React.ComponentProps<typeof ArkSplitter.ResizeTrigger> {
/**
* Whether to show the handle
*
* @default false
*/
withHandle?: boolean;
}
export const ResizableResizeTrigger = (props: ResizableResizeTriggerProps) => {
const { withHandle = false, className, ...rest } = props;
return (
<ArkSplitter.ResizeTrigger
aria-label="Resize"
className={cn(
"relative bg-border",
"flex w-px items-center justify-center",
"after:-translate-x-1/2 data-[orientation=vertical]:after:-translate-y-1/2",
"after:absolute after:inset-s-1/2 after:inset-y-0 after:w-1",
"focus-visible:outline-hidden focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-1",
"data-[orientation=vertical]:h-px data-[orientation=vertical]:w-full",
"data-[orientation=vertical]:after:inset-s-0 data-[orientation=vertical]:after:h-1 data-[orientation=vertical]:after:w-full",
"data-[orientation=vertical]:after:translate-x-0",
"[&[data-orientation=vertical]>div]:rotate-90",
className
)}
data-slot="resizable-resize-trigger"
{...rest}
>
{withHandle && (
<div
className={cn(
"z-10",
"h-4 w-3",
"flex items-center justify-center",
"bg-border",
"rounded-xs border"
)}
>
<GripVertical className="size-2.5" />
</div>
)}
</ArkSplitter.ResizeTrigger>
);
};Update the import paths to match your project setup.
Anatomy
Resizable
├── ResizablePanel
└── ResizableResizeTriggerUsage
import {
Resizable,
ResizablePanel,
ResizableResizeTrigger,
} from "@/components/ui/resizable";<Resizable>
<ResizablePanel id="1" />
<ResizableResizeTrigger id="1:2" />
<ResizablePanel id="2" />
</Resizable>Orientation
Use the orientation prop to control the orientation of the resizable panels.
Horizontal
Set orientation="horizontal" to place panels side by side (default).
Vertical
Set orientation="vertical" to stack panels vertically.
Examples
Handle
Use the withHandle prop on ResizableResizeTrigger to show a visible grip handle for resizing.
Min / Max Size
Use panels with minSize and maxSize to constrain how small or large a panel can be resized.
Multiple Panels
API Reference
Resizable
Root component. Manages resizable panel layout.
| Prop | Type | Default |
|---|---|---|
panels | PanelData[] | - |
defaultSize | number[] | - |
size | number[] | - |
orientation | "horizontal" | "vertical" | "horizontal" |
keyboardResizeBy | number | - |
onResize | (details: ResizeDetails) => void | - |
onResizeStart | () => void | - |
onResizeEnd | (details: ResizeEndDetails) => void | - |
onCollapse | (details: ExpandCollapseDetails) => void | - |
onExpand | (details: ExpandCollapseDetails) => void | - |
className | string | - |
ResizablePanel
A resizable panel. Multiple panels share the available space.
| Prop | Type | Default |
|---|---|---|
id | string | - |
asChild | boolean | false |
className | string | - |
ResizableResizeTrigger
Draggable handle between panels for resizing.
| Prop | Type | Default |
|---|---|---|
id | ${string}:${string} | - |
withHandle | boolean | false |
disabled | boolean | - |
asChild | boolean | false |
className | string | - |
For a complete list of props, see the Ark UI documentation.