dnd-use-sortable
ui
src
cn.ts
ts
// npm i clsx tailwind-merge
import { clsx, type ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
sortable.tsx
tsx
// npm i @dnd-kit/react
"use client"
import { ReactElement } from "react";
import { useSortable } from "@dnd-kit/react/sortable";
import { cn } from "@/lib/tailwind";
interface SortableProps {
id: number;
index: number;
className?: string;
children: ReactElement;
}
export function Sortable({ id, index, className, children }: SortableProps) {
const { ref, isDragging } = useSortable({ id, index });
return (
<li ref={ ref } className={ cn(className, isDragging && "z-50 shadow-2xl blur-xs duration-300") }>
{ children }
</li>
)
}
page.tsx
tsx
import { Sortable } from "@/examples/dnd-use-sortable/Sortable";
export default function Page() {
const images = [
{
id: 1,
url: "https://cdn.pixabay.com/photo/2023/10/25/19/25/blue-8341156_1280.jpg"
},
{
id: 2,
url: "https://cdn.pixabay.com/photo/2020/02/05/22/37/seagulls-4822595_1280.jpg"
},
{
id: 3,
url: "https://cdn.pixabay.com/photo/2017/08/07/08/23/sea-2601374_1280.jpg"
},
{
id: 4,
url: "https://cdn.pixabay.com/photo/2022/09/07/18/25/stone-7439317_1280.jpg"
},
{
id: 5,
url: "https://cdn.pixabay.com/photo/2019/06/01/09/58/water-4243762_1280.jpg"
},
{
id: 6,
url: "https://cdn.pixabay.com/photo/2020/02/11/10/24/lake-4839058_1280.jpg"
}
];
return (
<ul className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-5">
{
images.map(({ url, id }, i) => (
<Sortable id={ id } index={ i } key={ id }>
<img className="w-full aspect-video cursor-pointer" src={ url } alt=""/>
</Sortable>
))
}
</ul>
)
}