dnd-kit-sortable
ui






src
cn.ts
TS
// npm i clsx tailwind-merge @dnd-kit/react
import { clsx, type ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
sortable.tsx
TSX
"use client"
import { useSortable } from "@dnd-kit/react/sortable";
import { cn } from "@/lib/tailwind";
interface SortableProps {
id: string;
index: number;
src: string;
className?: string;
}
export function Sortable({ id, index, src, className }: SortableProps) {
const { ref, isDragging } = useSortable({ id, index });
return (
<img className={ cn(isDragging && "shadow-2xl shadow-purple-500/60", className) }
ref={ ref }
src={ src }
alt=""/>
)
}
page.tsx
TSX
import { Sortable } from "@/examples/dnd-kit-sortable/sortable";
export default function Page() {
const images = [
{ id: "1", src: "https://cdn.pixabay.com/photo/2023/03/15/16/17/feather-7854908_1280.jpg", },
{ id: "2", src: "https://cdn.pixabay.com/photo/2022/08/05/10/22/purple-bells-7366491_1280.jpg", },
{ id: "3", src: "https://cdn.pixabay.com/photo/2023/03/02/03/01/bird-7824442_1280.jpg", },
{ id: "4", src: "https://cdn.pixabay.com/photo/2022/10/24/09/31/flower-7543035_1280.jpg", },
{ id: "5", src: "https://cdn.pixabay.com/photo/2024/12/18/01/27/lightning-9274136_1280.jpg", },
{ id: "6", src: "https://cdn.pixabay.com/photo/2025/06/23/18/09/blossom-9676411_1280.jpg", },
];
return (
<div className="grid gap-5 grid-cols-1 md:grid-cols-2 lg:grid-cols-3">
{
images.map(({ id, src }, index) => (
<Sortable className="w-full aspect-video object-center cursor-pointer select-none"
id={ id }
index={ index }
src={ src }
key={ id }/>
))
}
</div>
)
}