Resizable Handle

DnD & Interaction

Draggable handle for resizing elements.

Preview

Left Panel
Right Panel

Usage

example.jsx
import { ResizableHandle } from "@/components/ui/resizable-handle";

export default function Example() {
  return <ResizableHandle />;
}

Source Code

Copy this file into components/ui/resizable-handle.jsx in your project.

resizable-handle.jsx
"use client";

import { forwardRef, useRef, useCallback } from "react";
import { cn } from "@/lib/utils";

const ResizableHandle = forwardRef(({ className, direction = "horizontal", onResize, ...props }, ref) => {
  const onMouseDown = useCallback((e) => {
    e.preventDefault();
    const startX = e.clientX;
    const startY = e.clientY;
    const onMove = (e) => {
      const dx = e.clientX - startX;
      const dy = e.clientY - startY;
      onResize?.(direction === "horizontal" ? dx : dy);
    };
    const onUp = () => { window.removeEventListener("mousemove", onMove); window.removeEventListener("mouseup", onUp); };
    window.addEventListener("mousemove", onMove);
    window.addEventListener("mouseup", onUp);
  }, [direction, onResize]);

  return (
    <div ref={ref}
      className={cn("flex items-center justify-center bg-border transition-colors hover:bg-primary/20",
        direction === "horizontal" ? "w-1.5 cursor-col-resize" : "h-1.5 cursor-row-resize",
        className
      )}
      onMouseDown={onMouseDown}
      {...props}
    >
      <div className={cn("rounded-full bg-muted-foreground/50",
        direction === "horizontal" ? "h-6 w-0.5" : "h-0.5 w-6"
      )} />
    </div>
  );
});
ResizableHandle.displayName = "ResizableHandle";

export { ResizableHandle };

Quick Install

Make sure you have the cn() utility set up. It requires clsx and tailwind-merge.

npm install clsx tailwind-merge