Resizable
LayoutContainer with draggable resize handle.
Preview
Drag the edge to resize this container →
Usage
example.jsx
import { Resizable } from "@/components/ui/resizable";
export default function Example() {
return <Resizable />;
}Source Code
Copy this file into components/ui/resizable.jsx in your project.
resizable.jsx
"use client";
import { forwardRef, useState, useRef, useCallback } from "react";
import { cn } from "@/lib/utils";
const Resizable = forwardRef(({ className, children, minWidth = 100, minHeight = 100, ...props }, ref) => {
const containerRef = useRef(null);
const [size, setSize] = useState({ width: "100%", height: "auto" });
const dragging = useRef(false);
const onMouseDown = useCallback((e) => {
e.preventDefault();
dragging.current = true;
const startX = e.clientX;
const startY = e.clientY;
const rect = containerRef.current.getBoundingClientRect();
const startW = rect.width;
const startH = rect.height;
const onMouseMove = (e) => {
if (!dragging.current) return;
setSize({
width: Math.max(minWidth, startW + e.clientX - startX),
height: Math.max(minHeight, startH + e.clientY - startY),
});
};
const onMouseUp = () => { dragging.current = false; window.removeEventListener("mousemove", onMouseMove); window.removeEventListener("mouseup", onMouseUp); };
window.addEventListener("mousemove", onMouseMove);
window.addEventListener("mouseup", onMouseUp);
}, [minWidth, minHeight]);
return (
<div ref={(el) => { containerRef.current = el; if (typeof ref === "function") ref(el); else if (ref) ref.current = el; }}
className={cn("relative overflow-auto rounded-md border", className)}
style={{ width: size.width, height: size.height }}
{...props}
>
{children}
<div onMouseDown={onMouseDown} className="absolute bottom-0 right-0 h-4 w-4 cursor-se-resize" >
<svg className="h-4 w-4 text-muted-foreground" viewBox="0 0 24 24" fill="currentColor"><path d="M22 22H20V20H22V22ZM22 18H18V22H16V16H22V18ZM22 14H14V22H12V12H22V14Z" /></svg>
</div>
</div>
);
});
Resizable.displayName = "Resizable";
export { Resizable };
Quick Install
Make sure you have the cn() utility set up. It requires clsx and tailwind-merge.
npm install clsx tailwind-merge