Skip to content

Commit

Permalink
Moving cards animation featuers
Browse files Browse the repository at this point in the history
  • Loading branch information
barchakuz committed May 11, 2024
1 parent 8e0f7e3 commit aa2cf6a
Show file tree
Hide file tree
Showing 4 changed files with 188 additions and 0 deletions.
59 changes: 59 additions & 0 deletions app/components/MusicSchoolCards.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
'use client'
import { InfiniteMovingCards } from "./ui/infinite-moving-cards";

const musicSchoolTestimonials = [
{
quote:
'Joining the music school transformed my understanding of music and helped me to truly discover my own sound. The instructors are world-class!',
name: 'Alex Johnson',
title: 'Guitar Student',
},
{
quote:
"The community and support at this school are unmatched. I've grown not just as a pianist, but also as a performer, thanks to their comprehensive approach.",
name: 'Samantha Lee',
title: 'Piano Student',
},
{
quote:
"This school offered me the tools and confidence to take my singing to the next level. I'm endlessly grateful for the personalized coaching.",
name: 'Michael Chen',
title: 'Vocal Student',
},
{
quote:
'As a violinist, finding the right mentor can be challenging, but this school matched me with a teacher who truly understands my goals and challenges.',
name: 'Emily Taylor',
title: 'Violin Student',
},
{
quote:
'The production courses here opened my eyes to the intricacies of music production. Highly recommend for any aspiring producers!',
name: 'Chris Morales',
title: 'Music Production Student',
},
];

function MusicSchoolCards() {
return (
<div className="h-[40rem] w-full dark:bg-black dark:bg-grid-white/[0.2] relative flex flex-col items-center justify-center overflow-hidden">
<h2 className="text-3xl font-bold text-center mb-8 z-10">Hear our Harmony: Voices of success</h2>
<div className="flex justify-center w-full overflow-hidden px-4 sm:px-6 lg:px-8">
<div className="w-full max-w-6xl">
<InfiniteMovingCards
items={musicSchoolTestimonials}
direction="left"
speed="slow"
/>
<InfiniteMovingCards
items={musicSchoolTestimonials}
direction="right"
speed="slow"
/>
</div>
</div>
</div>
)
}

export default MusicSchoolCards
121 changes: 121 additions & 0 deletions app/components/ui/infinite-moving-cards.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
"use client";

import { cn } from "@/app/utils/cn";
import React, { useEffect, useState } from "react";

export const InfiniteMovingCards = ({
items,
direction = "left",
speed = "fast",
pauseOnHover = true,
className,
}: {
items: {
quote: string;
name: string;
title: string;
}[];
direction?: "left" | "right";
speed?: "fast" | "normal" | "slow";
pauseOnHover?: boolean;
className?: string;
}) => {
const containerRef = React.useRef<HTMLDivElement>(null);
const scrollerRef = React.useRef<HTMLUListElement>(null);

useEffect(() => {
addAnimation();
}, []);
const [start, setStart] = useState(false);
function addAnimation() {
if (containerRef.current && scrollerRef.current) {
const scrollerContent = Array.from(scrollerRef.current.children);

scrollerContent.forEach((item) => {
const duplicatedItem = item.cloneNode(true);
if (scrollerRef.current) {
scrollerRef.current.appendChild(duplicatedItem);
}
});

getDirection();
getSpeed();
setStart(true);
}
}
const getDirection = () => {
if (containerRef.current) {
if (direction === "left") {
containerRef.current.style.setProperty(
"--animation-direction",
"forwards"
);
} else {
containerRef.current.style.setProperty(
"--animation-direction",
"reverse"
);
}
}
};
const getSpeed = () => {
if (containerRef.current) {
if (speed === "fast") {
containerRef.current.style.setProperty("--animation-duration", "20s");
} else if (speed === "normal") {
containerRef.current.style.setProperty("--animation-duration", "40s");
} else {
containerRef.current.style.setProperty("--animation-duration", "80s");
}
}
};
return (
<div
ref={containerRef}
className={cn(
"scroller relative z-20 max-w-7xl overflow-hidden [mask-image:linear-gradient(to_right,transparent,white_20%,white_80%,transparent)]",
className
)}
>
<ul
ref={scrollerRef}
className={cn(
" flex min-w-full shrink-0 gap-4 py-4 w-max flex-nowrap",
start && "animate-scroll ",
pauseOnHover && "hover:[animation-play-state:paused]"
)}
>
{items.map((item, idx) => (
<li
className="w-[350px] max-w-full relative rounded-2xl border border-b-0 flex-shrink-0 border-slate-700 px-8 py-6 md:w-[450px]"
style={{
background:
"linear-gradient(180deg, var(--slate-800), var(--slate-900)",
}}
key={item.name}
>
<blockquote>
<div
aria-hidden="true"
className="user-select-none -z-1 pointer-events-none absolute -left-0.5 -top-0.5 h-[calc(100%_+_4px)] w-[calc(100%_+_4px)]"
></div>
<span className=" relative z-20 text-sm leading-[1.6] text-gray-100 font-normal">
{item.quote}
</span>
<div className="relative z-20 mt-6 flex flex-row items-center">
<span className="flex flex-col gap-1">
<span className=" text-sm leading-[1.6] text-gray-400 font-normal">
{item.name}
</span>
<span className=" text-sm leading-[1.6] text-gray-400 font-normal">
{item.title}
</span>
</span>
</div>
</blockquote>
</li>
))}
</ul>
</div>
);
};
2 changes: 2 additions & 0 deletions app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ import Image from "next/image";
import HeroSection from "./components/HeroSection";
import FeaturedCourse from "./components/FeaturedCourse";
import WhyChooseUs from "./components/WhyChooseUs";
import MusicSchoolCards from "./components/MusicSchoolCards";

export default function Home() {
return (
<>
<HeroSection />
<FeaturedCourse />
<WhyChooseUs />
<MusicSchoolCards />
</>
);
}
6 changes: 6 additions & 0 deletions tailwind.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const config: Config = {
},
animation: {
spotlight: "spotlight 2s ease .75s 1 forwards",
scroll:"scroll var(--animation-duration, 40s) var(--animation-direction, forwards) linear infinite",
},
keyframes: {
spotlight: {
Expand All @@ -30,6 +31,11 @@ const config: Config = {
"100%": {opacity: '1',
transform: "translate(-50%,-40%) scale(1)",}
},
scroll: {
to: {
transform: "translate(calc(-50% - 0.5rem))",
},
},
},
},
},
Expand Down

0 comments on commit aa2cf6a

Please sign in to comment.