Resizable
Panels that resize by drag or keyboard.
Preview
Loading...
import {
ResizableHandle,
ResizablePanel,
ResizablePanelGroup,
} from "@/components/ui/Resizable";
export function ResizableDemo() {
return (
<div className="h-16 w-full overflow-hidden rounded-md border border-gray-6">
<ResizablePanelGroup direction="horizontal" className="h-full">
<ResizablePanel defaultSize={50} minSize={20}>
<div className="flex h-full items-center justify-center p-1 text-sm text-gray-12">
One
</div>
</ResizablePanel>
<ResizableHandle withHandle />
<ResizablePanel defaultSize={50} minSize={20}>
<div className="flex h-full items-center justify-center p-1 text-sm text-gray-12">
Two
</div>
</ResizablePanel>
</ResizablePanelGroup>
</div>
);
}Installation
Make sure that namespace is set in your component.json file. Namespace docs: Learn more about namespaces
pnpm dlx shadcn@latest add @aura/resizableManual
Install the following dependencies:
pnpm install @radix-ui/react-icons react-resizable-panelsCopy and paste the class names utility into your utils/class-names.ts file.
import { clsx, type ClassValue } from "clsx"
import { twMerge } from "tailwind-merge"
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
Copy and paste the Resizable component into your components/ui/Resizable.tsx file.
"use client";
/**
* @description Resizable panels. Drag the handle; keyboard users resize from the focused separator.
*/
import * as React from "react";
import { DragHandleDots2Icon } from "@radix-ui/react-icons";
import * as ResizablePrimitive from "react-resizable-panels";
import { cn } from "@/utils/class-names";
function ResizablePanelGroup({
className,
...props
}: React.ComponentProps<typeof ResizablePrimitive.PanelGroup>) {
return (
<ResizablePrimitive.PanelGroup
data-slot="resizable-panel-group"
className={cn(
"flex h-full w-full data-[panel-group-direction=vertical]:flex-col",
className,
)}
{...props}
/>
);
}
const ResizablePanel = ResizablePrimitive.Panel;
function ResizableHandle({
withHandle,
className,
...props
}: React.ComponentProps<typeof ResizablePrimitive.PanelResizeHandle> & {
withHandle?: boolean;
}) {
return (
<ResizablePrimitive.PanelResizeHandle
data-slot="resizable-handle"
className={cn(
"relative flex w-px items-center justify-center bg-gray-6 before:absolute before:inset-y-0 before:left-1/2 before:w-1 before:-translate-x-1/2 focus-visible:outline-2 focus-visible:outline-accent-8 data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full data-[panel-group-direction=vertical]:before:left-0 data-[panel-group-direction=vertical]:before:h-1 data-[panel-group-direction=vertical]:before:w-full data-[panel-group-direction=vertical]:before:translate-x-0 data-[panel-group-direction=vertical]:before:-translate-y-1/2 data-[panel-group-direction=vertical]:[&>div]:rotate-90",
className,
)}
{...props}
>
{withHandle ? (
<div className="z-10 flex h-3 w-2 items-center justify-center rounded-sm border border-gray-6 bg-gray-2">
<DragHandleDots2Icon className="icon" />
</div>
) : null}
</ResizablePrimitive.PanelResizeHandle>
);
}
export { ResizablePanelGroup, ResizablePanel, ResizableHandle };
Usage
Vertical
export const Vertical = () => {
return (
<div className="h-16 w-full overflow-hidden rounded-md border border-gray-6">
<ResizablePanelGroup direction="vertical" className="h-full">
<ResizablePanel defaultSize={50}>
<div className="flex h-full items-center justify-center p-1 text-sm">
Top
</div>
</ResizablePanel>
<ResizableHandle withHandle />
<ResizablePanel defaultSize={50}>
<div className="flex h-full items-center justify-center p-1 text-sm">
Bottom
</div>
</ResizablePanel>
</ResizablePanelGroup>
</div>
);
};