Drag Items
The Drag Items component allows users to rearrange items by dragging them.
The Drag Items component allows users to rearrange items by dragging them.
Follow these simple steps to add the Drag Items component to your project:
Install Dependencies
pnpm add motion
Create a new file: components/motions/drag-items.tsx
and copy the code below:
"use client";
import React, { useEffect } from "react";
import {
useMotionValue,
Reorder,
useDragControls,
motion,
MotionValue,
animate,
DragControls,
} from "motion/react";
import {
Card,
} from "@/components/ui/card";
import { Grip } from "lucide-react";
/*eslint-disable @typescript-eslint/no-explicit-any*/
export const DragItems = ({
items,
onReorder,
children,
}: {
items: any[];
onReorder: (newItems: any[]) => void;
children: React.ReactNode;
}) => {
return (
<Reorder.Group
axis="y"
values={items}
onReorder={onReorder}
className="mx-auto w-full max-w-2xl space-y-3"
>
{children}
</Reorder.Group>
);
};
export const Item = ({
children,
item,
}: {
children: React.ReactNode;
item: any;
}) => {
const y = useMotionValue(0);
const boxShadow = useRaisedShadow(y);
const dragControls = useDragControls();
return (
<Reorder.Item
value={item}
style={{ boxShadow, y }}
dragListener={false}
dragControls={dragControls}
className="w-full"
>
<Card className="overflow-hidden border transition-all duration-300">
<div className="flex items-center justify-center">
<div className="flex-1">{children}</div>
<ReorderIcon dragControls={dragControls} />
</div>
</Card>
</Reorder.Item>
);
};
const ReorderIcon = ({ dragControls }: { dragControls: DragControls }) => {
return (
<motion.div
// whileTap={{ scale: 0.85 }}
onPointerDown={(e) => {
e.preventDefault();
dragControls.start(e);
}}
className="mr-3 cursor-grab active:cursor-grabbing"
>
<Grip size={20} />
</motion.div>
);
};
const inactiveShadow = "0px 0px 0px rgba(0,0,0,0)";
const useRaisedShadow = (value: MotionValue<number>) => {
const boxShadow = useMotionValue(inactiveShadow);
useEffect(() => {
let isActive = false;
value.onChange((latest) => {
const wasActive = isActive;
if (latest !== 0) {
isActive = true;
if (isActive !== wasActive) {
animate(boxShadow, "0px 0px 0px rgba(0,0,0,0)");
}
} else {
isActive = false;
if (isActive !== wasActive) {
animate(boxShadow, inactiveShadow);
}
}
});
}, [value, boxShadow]);
return boxShadow;
};
/*eslint-enable @typescript-eslint/no-explicit-any*/
Adjust the import paths in both files according to your project's structure.
Drag to reorder
Get more update follow me on X
If you like star the repo
if you like it, please Share it with your friend