Draggable Card

Premium

A physics-driven draggable card with 3D tilt, glare effect, and momentum-based spring animations. Scatter them across the screen and drag to explore.

Interactive Demo

Drag the cards

If its your first day at Fight Club, you have to fight.

Tyler Durden

Tyler Durden

The Narrator

The Narrator

Iceland

Iceland

Japan

Japan

Norway

Norway

New Zealand

New Zealand

Canada

Canada

Installation

Install the draggable-card via the shadcn CLI:

bash
npx shadcn@latest add "https://dexterityui.vercel.app/r/draggable-card.json"

Requires motion (framer-motion).

Props

DraggableCardContainer

PropTypeDescription
classNamestringAdditional CSS classes. Applies perspective: 3000px by default.
childrenReactNodeDraggableCardBody components to render inside.

DraggableCardBody

PropTypeDescription
classNamestringPosition and rotation classes (e.g. absolute top-10 left-[20%] rotate-[-5deg]).
childrenReactNodeCard content — images, text, etc.

Features

🎯3D tilt — card rotates to follow cursor position with spring physics
💎Glare effect — dynamic white overlay that shifts with mouse movement
Momentum — cards carry velocity on release with spring bounce
🖱️Drag constraints — cards stay within the viewport boundaries
🔄Spring reset — tilt smoothly resets to zero when released
📐Perspective container — 3000px perspective for realistic 3D depth

Source

tsx
"use client";
import { cn } from "@/lib/utils";
import React, { useRef, useState, useEffect } from "react";
import {
  motion,
  useMotionValue,
  useSpring,
  useTransform,
  animate,
  useVelocity,
  useAnimationControls,
} from "motion/react";

export const DraggableCardBody = ({
  className,
  children,
}: {
  className?: string;
  children?: React.ReactNode;
}) => {
  const mouseX = useMotionValue(0);
  const mouseY = useMotionValue(0);
  const cardRef = useRef<HTMLDivElement>(null);
  const controls = useAnimationControls();
  // ... spring physics, 3D tilt, glare, drag constraints
  // Full source: registry/default/draggable-card/draggable-card.tsx
};

export const DraggableCardContainer = ({
  className,
  children,
}: {
  className?: string;
  children?: React.ReactNode;
}) => {
  return (
    <div className={cn("[perspective:3000px]", className)}>{children}</div>
  );
};