Leave a star on GitHub! ⭐


Docs
Animated Card

Animated Card

A layout used to showcase the features of a product in a simple and elegant way.

You can also add content inside the card

EldoraUI

This is the best library for creating dynamic cards

If leave the card empty, it will still look good

Is Just crazy

How fast is it now to create cards

Amazing

I just have to copy paste the code and it instantly works

Unbelievable

I can't believe how easy it is to use

Installation

pnpm add lucide-react

Copy and paste the following code into your project.

components/eldoraui/animatedcard.tsx

"use client";
import { ArrowUpRightIcon } from "lucide-react";
import type { ReactNode } from "react";
import { useMouse } from "@/components/hooks/usemouse";
import { cn } from "@/lib/utils";
 
export const MainMenusGradientCard = ({
  title,
  description,
  withArrow = false,
  circleSize = 400,
  className,
  children,
}: {
  title: string;
  description: string;
  withArrow?: boolean;
  circleSize?: number;
  children?: ReactNode;
  className?: string;
}) => {
  const [mouse, parentRef] = useMouse();
 
  return (
    <div
      className="group relative transform-gpu overflow-hidden rounded-[20px] bg-white/10 p-2 transition-transform hover:scale-[1.01] active:scale-90"
      ref={parentRef}
    >
      {withArrow && (
        <ArrowUpRightIcon className="absolute right-2 top-2 z-10 size-5 translate-y-4 text-neutral-700 opacity-0 transition-all group-hover:translate-y-0 group-hover:opacity-100 dark:text-neutral-300 " />
      )}
      <div
        className={cn(
          "absolute -translate-x-1/2 -translate-y-1/2 transform-gpu rounded-full transition-transform duration-500 group-hover:scale-[3]",
          mouse.elementX === null || mouse.elementY === null
            ? "opacity-0"
            : "opacity-100",
        )}
        style={{
          maskImage: `radial-gradient(${
            circleSize / 2
          }px circle at center, white, transparent)`,
          width: `${circleSize}px`,
          height: `${circleSize}px`,
          left: `${mouse.elementX}px`,
          top: `${mouse.elementY}px`,
          background:
            "linear-gradient(135deg, #3BC4F2, #7A69F9,#F26378,#F5833F)",
        }}
      />
      <div className="absolute inset-px rounded-[19px] bg-neutral-100/80 dark:bg-neutral-900/80" />
      {children && (
        <div
          className={cn(
            "gird relative h-40 place-content-center overflow-hidden rounded-[15px] border-white bg-white/70 dark:border-neutral-950 dark:bg-black/50",
            className,
          )}
        >
          {children}
        </div>
      )}
      <div className="relative px-4 pb-2 pt-4">
        <h3 className="text-lg font-semibold text-neutral-800 dark:text-neutral-300">
          {title}
        </h3>
        <p className="mt-2 text-neutral-600 dark:text-neutral-400">
          {description}
        </p>
      </div>
    </div>
  );
};

Copy and paste the following code into your project.

components/eldoraui/hooks/usemouse.tsx

"use client";
import { type RefObject, useLayoutEffect, useRef, useState } from "react";
 
interface MouseState {
  x: number | null;
  y: number | null;
  elementX: number | null;
  elementY: number | null;
  elementPositionX: number | null;
  elementPositionY: number | null;
}
 
export function useMouse(): [MouseState, RefObject<HTMLDivElement>] {
  const [state, setState] = useState<MouseState>({
    x: null,
    y: null,
    elementX: null,
    elementY: null,
    elementPositionX: null,
    elementPositionY: null,
  });
 
  const ref = useRef<HTMLDivElement | null>(null);
 
  useLayoutEffect(() => {
    const handleMouseMove = (event: MouseEvent) => {
      const newState: Partial<MouseState> = {
        x: event.pageX,
        y: event.pageY,
      };
 
      if (ref.current instanceof Element) {
        const { left, top } = ref.current.getBoundingClientRect();
        const elementPositionX = left + window.scrollX;
        const elementPositionY = top + window.scrollY;
        const elementX = event.pageX - elementPositionX;
        const elementY = event.pageY - elementPositionY;
 
        newState.elementX = elementX;
        newState.elementY = elementY;
        newState.elementPositionX = elementPositionX;
        newState.elementPositionY = elementPositionY;
      }
 
      setState((s) => ({
        ...s,
        ...newState,
      }));
    };
 
    document.addEventListener("mousemove", handleMouseMove);
 
    return () => {
      document.removeEventListener("mousemove", handleMouseMove);
    };
  }, []);
 
  return [state, ref];
}

Update the import paths to match your project setup.

Props

Prop NameTypeDefaultDescription
titlestring-The title to display in the card.
descriptionstring-The description text to display in the card.
withArrowbooleanfalseA boolean that determines if an arrow icon will be displayed in the top right corner of the card.
circleSizenumber400The size of the circle used in the background gradient effect (measured in pixels).
childrenReactNodeundefinedAny child elements to render inside the card (optional).
classNamestringundefinedAn optional custom className for further styling of the child container.