Docs

Music Card

An animated beam of light which travels along the border of its container.

Installation

Install dependencies

npm install framer-motion lucide-react

Run the following command

It will create a new file music-card.tsx inside the components/mage-ui/card directory.

mkdir -p components/mage-ui/card && touch components/mage-ui/card/music-card.tsx

Paste the code

Open the newly created file and paste the following code:

"use client";
 
import { Button } from "@/components/ui/button";
import {
  Card,
  CardContent,
  CardDescription,
  CardFooter,
  CardHeader,
  CardTitle,
} from "@/components/ui/card";
import { cn } from "@/lib/utils";
import { motion, MotionStyle, Transition } from "framer-motion";
import React from "react";
import { Play, SkipBack, SkipForward } from "lucide-react";
 
interface BorderBeamProps {
  size?: number;
  duration?: number;
  delay?: number;
  colorFrom?: string;
  colorTo?: string;
  transition?: Transition;
  className?: string;
  style?: React.CSSProperties;
  reverse?: boolean;
  initialOffset?: number;
}
 
const BorderBeam: React.FC<BorderBeamProps> = ({
  className,
  size = 50,
  delay = 0,
  duration = 6,
  colorFrom = "#ffaa40",
  colorTo = "#9c40ff",
  transition,
  style,
  reverse = false,
  initialOffset = 0,
}) => {
  return (
    <div className="pointer-events-none absolute inset-0 rounded-[inherit] border border-transparent [mask-clip:padding-box,border-box] [mask-composite:intersect] [mask-image:linear-gradient(transparent,transparent),linear-gradient(#000,#000)]">
      <motion.div
        className={cn(
          "absolute aspect-square",
          "bg-gradient-to-l from-[var(--color-from)] via-[var(--color-to)] to-transparent",
          className
        )}
        style={{
          width: size,
          offsetPath: `rect(0 auto auto 0 round ${size}px)`,
          "--color-from": colorFrom,
          "--color-to": colorTo,
          ...style,
        } as MotionStyle}
        initial={{ offsetDistance: `${initialOffset}%` }}
        animate={{
          offsetDistance: reverse
            ? [`${100 - initialOffset}%`, `${-initialOffset}%`]
            : [`${initialOffset}%`, `${100 + initialOffset}%`],
        }}
        transition={{
          repeat: Infinity,
          ease: "linear",
          duration,
          delay: -delay,
          ...transition,
        }}
      />
    </div>
  );
};
 
const MusicPlayer: React.FC = () => {
  return (
    <Card className="relative w-[350px] overflow-hidden">
      <CardHeader>
        <CardTitle>Now Playing</CardTitle>
        <CardDescription>Stairway to Heaven - Led Zeppelin</CardDescription>
      </CardHeader>
      <CardContent>
        <div className="flex flex-col items-center gap-4">
          <div className="h-48 w-48 rounded-lg bg-gradient-to-br from-purple-500 to-pink-500" />
          <div className="h-1 w-full rounded-full bg-secondary">
            <div className="h-full w-1/3 rounded-full bg-primary" />
          </div>
          <div className="flex w-full justify-between text-sm text-muted-foreground">
            <span>2:45</span>
            <span>8:02</span>
          </div>
        </div>
      </CardContent>
      <CardFooter className="flex justify-center gap-4">
        <Button variant="outline" size="icon" className="rounded-full">
          <SkipBack className="size-4" />
        </Button>
        <Button size="icon" className="rounded-full">
          <Play className="size-4" />
        </Button>
        <Button variant="outline" size="icon" className="rounded-full">
          <SkipForward className="size-4" />
        </Button>
      </CardFooter>
      <BorderBeam duration={6} size={400} className="from-transparent via-red-500 to-transparent" />
      <BorderBeam duration={6} delay={3} size={400} className="from-transparent via-blue-500 to-transparent" />
    </Card>
  );
};
 
const Page: React.FC = () => {
  return (
    <div className="flex flex-col items-center gap-8 p-8">
      <MusicPlayer />
    </div>
  );
};
 
export default Page;

Props

PropertyTypeDefaultDescription
childrenReact.ReactNode-The content that will be magnified by the lens
zoomFactornumber1.3The magnification factor of the lens
lensSizenumber170The size of the lens in pixels (works as a diameter)
positionPosition-The current position of the lens
defaultPositionPosition-The initial position of the lens
isStaticbooleanfalseDetermines if the lens will remain in a fixed position
durationnumber0.1Duration of the animation when the lens moves (in seconds)
lensColorstring-The color of the lens (CSS color value)
ariaLabelstring-Accessibility label for the lens component