Skip to content

Instantly share code, notes, and snippets.

@harryparkinson101
Created February 13, 2024 12:32
Show Gist options
  • Save harryparkinson101/42449ffc9a8cb0c838b47432ce2afed0 to your computer and use it in GitHub Desktop.
Save harryparkinson101/42449ffc9a8cb0c838b47432ce2afed0 to your computer and use it in GitHub Desktop.
Framer-tilt-cards
import type { Metadata } from "next";
import { Inter as FontSans } from "next/font/google";
import "./globals.css";
import { cn } from "@/lib/utils";
export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export const fontSans = FontSans({
subsets: ["latin"],
variable: "--font-sans",
});
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
<body
className={cn(
"min-h-screen bg-background font-sans antialiased",
fontSans.variable
)}
>
{children}
</body>
</html>
);
}
"use client"
import { Card, CardContent, CardTitle } from "./ui/card";
import Tilt from "react-parallax-tilt";
import { motion } from "framer-motion";
import { useState } from "react";
const testimonials = [
{
name: "Alice",
avatar: "A",
title: "Audio Enthusiast",
description: "The audio generation is astonishing. It produces music like no other.",
},
{
name: "Victor",
avatar: "V",
title: "Video Producer",
description: "The video generation capabilities have revolutionized my content creation process.",
},
{
name: "Daniel",
avatar: "D",
title: "Code Developer",
description: "It simplifies code generation and speeds up development. It's a coder's dream tool.",
},
{
name: "Sophia",
avatar: "S",
title: "Image Artist",
description: "The image generation abilities are pure magic. It generates art that amazes me every time.",
},
{
name: "Elena",
avatar: "E",
title: "Digital Marketer",
description: "Leveraging AI for marketing has transformed how we engage with our audience, making every campaign significantly more impactful.",
},
{
name: "Marco",
avatar: "M",
title: "UX Designer",
description: "The intuitive design tools available today have revolutionized our approach to user experience, making it more immersive and user-friendly.",
},
{
name: "Liam",
avatar: "L",
title: "Blockchain Expert",
description: "The advancements in decentralized technologies are opening up new possibilities for secure and transparent digital transactions.",
},
{
name: "Zoe",
avatar: "Z",
title: "Environmental Scientist",
description: "The integration of tech in environmental science is paving the way for groundbreaking solutions to climate change.",
}
];
const staggerVariants = {
initial: {},
animate: {
transition: {
staggerChildren: 0.4,
},
},
};
const cardVariants = {
initial: { opacity: 0, x: -100 },
animate: { opacity: 1, x: 0 },
};
export const MotionCard = () => {
const [displayedTestimonials, setDisplayedTestimonials] = useState(
testimonials.slice(0, 4)
); // Show initial 6 testimonials on mobile
const showMoreTestimonials = () => {
setDisplayedTestimonials(testimonials);
};
return (
<div className="px-10 pb-20">
<h2 className="text-center text-4xl text-white font-semibold mb-10">
Testimonials
</h2>
<motion.div
className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4"
variants={staggerVariants}
initial="initial"
animate="animate"
>
{displayedTestimonials.map((item, index) => (
<motion.div key={index} variants={cardVariants}>
<Tilt
className="parallax-effect-glare-scale"
perspective={500}
glareEnable={true}
glareMaxOpacity={0.2}
glareColor="lightblue"
glarePosition="all"
tiltMaxAngleX={4}
tiltMaxAngleY={4}
>
<div className="hover:scale-105">
<Card className="bg-[#192339] border-none text-white shadow-md rounded-lg">
<CardTitle className="flex items-center pl-4 pt-4 pb-4 gap-x-3">
<div>
<p className="text-lg">{item.name}</p>
<p className="text-zinc-400 text-sm">{item.title}</p>
</div>
</CardTitle>
<CardContent className="pt-4 px-4 text-[#efaf19]">
{item.description}
</CardContent>
</Card>
</div>
</Tilt>
</motion.div>
))}
</motion.div>
{/* Conditionally render Show More Button outside the map function */}
{displayedTestimonials.length < testimonials.length && (
<div className="text-center mt-8">
<button
className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"
onClick={showMoreTestimonials}
>
Show More
</button>
</div>
)}
</div>
);
};
"use client"
import { MotionCard } from "@/components/MotionCard";
export default function Home() {
return (
<main>
<MotionCard />
</main>
);
}

Setting Up Your Next.js Project with Framer Motion, React Parallax Tilt, and @shadcn/ui

This guide walks you through the process of setting up a new Next.js project with advanced UI components and animations.

Step 1: Initialize the Next.js Project

First, create a new Next.js app using the following command:

npx create-next-app my-nextjs-project
cd my-nextjs-project

Install Dependencies

Install Framer Motion and React Parallax Tilt to add animations and tilt effects to your project:

```bash
npm install framer-motion react-parallax-tilt

Set Up @shadcn/ui

Initialize @shadcn/ui in your project to access its collection of UI components:

```bash
npx shadcn-ui@latest init

Further, add the Card component from @shadcn/ui:

``bash
npx shadcn-ui@latest add card

Prepare Your Project for Development
Clean Up Default Content

In app/page.tsx, remove the main content, leaving the file ready for custom components.
Create Components Folder

At the root level, create a components folder:

``bash
mkdir components

Add MotionCard Component

Inside the components folder, create a MotionCard.tsx file. 

Implement MotionCard in Your Application

In pages/index.tsx, import and use the MotionCard component
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment