2025-02-16 19:49:16 +05:30

360 lines
14 KiB
TypeScript

"use client";
import { cn } from "@/lib/utils";
import React, { useState } from "react";
import { BentoGrid, BentoGridItem } from "../ui/bento-grid";
import {
IconBoxAlignRightFilled,
IconClipboardCopy,
IconFileBroken,
IconSignature,
IconTableColumn,
} from "@tabler/icons-react";
import { motion, AnimatePresence } from "framer-motion";
import { FaPlay } from "react-icons/fa";
export function BentoFeatures() {
const variants = {
hidden: { opacity: 0, y: 50 },
visible: { opacity: 1, y: 0 },
};
return (
<motion.div
initial="hidden"
whileInView="visible"
variants={variants}
transition={{ duration: 0.5 }}
className="max-w-6xl mx-auto py-20"
>
<div className="text-center mb-16">
<motion.h2
// className="text-4xl md:text-5xl bg-clip-text text-transparent bg-gradient-to-r from-purple-500 to-blue-500"
className="text-4xl md:text-5xl bg-clip-text text-white"
variants={{
hidden: { opacity: 0, y: 20 },
visible: { opacity: 1, y: 0 }
}}
>
All-in-One Platform for AI-Powered Services
</motion.h2>
</div>
<BentoGrid className="md:auto-rows-[20rem]">
{items.map((item, i) => (
<BentoGridItem
key={i}
title={item.title}
description={item.description}
header={item.header}
className={cn("[&>p:text-lg] ", item.className)}
icon={item.icon}
/>
))}
</BentoGrid>
</motion.div>
);
}
const SkeletonOne = () => {
const [isHovered, setIsHovered] = useState(false);
return (
<motion.div
className="flex flex-1 w-full h-full min-h-[6rem] bg-gradient-to-br from-purple-900/50 to-blue-900/50 flex-col space-y-2 rounded-xl overflow-hidden"
onHoverStart={() => setIsHovered(true)}
onHoverEnd={() => setIsHovered(false)}
>
<div className="flex flex-col space-y-2 p-6">
<motion.h2
className="text-4xl font-bold text-white"
animate={{ scale: isHovered ? 1.05 : 1 }}
>
No Coding Needed
</motion.h2>
<motion.div
className="h-2 w-32 bg-gradient-to-r from-blue-500 to-purple-500 rounded-full mt-4"
animate={{ width: isHovered ? "40%" : "8rem" }}
/>
<motion.p
className="text-neutral-300 mt-2 flex items-center gap-2"
animate={{ x: isHovered ? 10 : 0 }}
>
Learn more
<motion.span
animate={{ x: isHovered ? 5 : 0 }}
transition={{ repeat: isHovered ? Infinity : 0, duration: 0.6 }}
>
</motion.span>
</motion.p>
</div>
<motion.img
src="https://images.unsplash.com/photo-1603201667230-bd139210db18?q=80&w=1788&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
className="p-4 rounded-xl"
animate={{
scale: isHovered ? 1.05 : 1,
rotate: isHovered ? 1 : 0
}}
transition={{ type: "spring", stiffness: 300 }}
alt="Feature preview"
/>
</motion.div>
);
};
const SkeletonTwo = () => {
const [isTyping, setIsTyping] = useState(false);
return (
<motion.div
className="flex flex-1 w-full h-full min-h-[2rem] bg-gradient-to-br from-purple-900/20 to-blue-900/20 flex-col items-center justify-center p-6 rounded-xl cursor-pointer"
onHoverStart={() => setIsTyping(true)}
onHoverEnd={() => setIsTyping(false)}
>
<div className="flex flex-col space-y-4 w-full">
<div className="relative w-full h-20 bg-black/40 rounded-xl overflow-hidden group">
<AnimatePresence>
{isTyping && (
<motion.div
className="absolute inset-0 flex items-center justify-start px-4"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
>
<motion.div
initial={{ width: 0 }}
animate={{
width: "auto",
transition: {
duration: 2,
repeat: Infinity,
repeatType: "reverse"
}
}}
className="overflow-hidden whitespace-nowrap text-purple-300"
>
console.log("Hello World!");
</motion.div>
<motion.div
animate={{ opacity: [0, 1, 0] }}
transition={{ duration: 0.8, repeat: Infinity }}
className="text-purple-300 ml-1"
>
|
</motion.div>
</motion.div>
)}
</AnimatePresence>
</div>
<motion.div
className="space-y-2"
animate={{
opacity: isTyping ? 1 : 0.5,
transition: { duration: 1, repeat: Infinity, repeatType: "reverse" }
}}
>
<div className="h-3 w-3/4 bg-gradient-to-r from-purple-500/20 to-blue-500/20 rounded-full" />
<div className="h-3 w-1/2 bg-gradient-to-r from-purple-500/20 to-blue-500/20 rounded-full" />
<div className="h-3 w-5/6 bg-gradient-to-r from-purple-500/20 to-blue-500/20 rounded-full" />
</motion.div>
</div>
</motion.div>
);
};
const SkeletonThree = () => {
const [isHovered, setIsHovered] = useState(false);
return (
<motion.div
className="flex flex-1 w-full h-full min-h-[6rem] bg-gradient-to-br from-purple-900/20 to-blue-900/20 flex-col items-center justify-center p-6 rounded-xl"
onHoverStart={() => setIsHovered(true)}
onHoverEnd={() => setIsHovered(false)}
>
<div className="relative w-full h-full bg-black/40 rounded-xl overflow-hidden p-6">
<motion.div
className="flex flex-col space-y-4"
animate={{ y: isHovered ? -10 : 0 }}
>
<div className="flex items-center justify-between">
<div className="h-8 w-24 bg-purple-500/30 rounded-full" />
<motion.div
className="text-2xl font-bold text-green-400"
animate={{ scale: isHovered ? 1.1 : 1 }}
>
$0
</motion.div>
</div>
<motion.div
className="h-16 w-full bg-gradient-to-r from-purple-500/20 to-blue-500/20 rounded-xl"
animate={{
scale: isHovered ? 1.02 : 1,
backgroundColor: isHovered ? "rgba(139, 92, 246, 0.3)" : "rgba(139, 92, 246, 0.2)"
}}
/>
<div className="flex justify-between items-center">
<div className="h-6 w-16 bg-purple-500/30 rounded-full" />
<motion.div
className="text-xl font-bold text-green-400"
animate={{ scale: isHovered ? 1.1 : 1 }}
>
$499
</motion.div>
</div>
</motion.div>
</div>
</motion.div>
);
};
const SkeletonFour = () => {
return (
<motion.div
className="flex flex-1 w-full h-full min-h-[6rem] bg-gradient-to-br from-purple-900/20 to-blue-900/20 flex-col items-center justify-center p-8 rounded-xl"
>
<div className="flex flex-col space-y-4 w-full">
<motion.div
className="bg-purple-500/20 p-4 rounded-xl cursor-pointer group relative overflow-hidden"
whileHover={{ scale: 1.02 }}
>
<motion.div
className="absolute inset-0 bg-purple-500/20 translate-x-[-100%] group-hover:translate-x-0 transition-transform duration-300"
/>
<div className="relative flex items-center space-x-4">
<motion.div
className="p-2 bg-purple-500/40 rounded-lg"
whileHover={{ rotate: 360 }}
transition={{ duration: 0.4 }}
>
<IconBoxAlignRightFilled className="h-6 w-6 text-purple-200" />
</motion.div>
<span className="text-white font-medium">Form Builder</span>
</div>
</motion.div>
<motion.div
className="bg-white/10 p-4 rounded-xl cursor-pointer group relative overflow-hidden"
whileHover={{ scale: 1.02 }}
>
<motion.div
className="absolute inset-0 bg-white/10 translate-x-[-100%] group-hover:translate-x-0 transition-transform duration-300"
/>
<div className="relative flex items-center space-x-4">
<motion.div
className="p-2 bg-white/20 rounded-lg"
whileHover={{ rotate: 360 }}
transition={{ duration: 0.4 }}
>
<IconClipboardCopy className="h-6 w-6 text-white" />
</motion.div>
<span className="text-white font-medium">Newsletter Creator</span>
</div>
</motion.div>
</div>
</motion.div>
);
};
// const SkeletonFive = () => {
// return (
// <motion.div
// className="flex flex-1 w-full h-full min-h-[6rem] dark:bg-dot-white/[0.2] bg-dot-black/[0.2] flex-col items-center justify-center p-8"
// >
// <div className="grid grid-cols-2 gap-4 w-full">
// <div className="bg-purple-500/20 p-4 rounded-xl aspect-square flex items-center justify-center">
// <motion.div
// animate={{ rotate: 360 }}
// transition={{ duration: 8, repeat: Infinity, ease: "linear" }}
// className="w-12 h-12 rounded-full border-4 border-purple-500 border-t-transparent"
// />
// </div>
// <div className="bg-blue-500/20 p-4 rounded-xl aspect-square flex items-center justify-center">
// <motion.div
// initial={{ scale: 0.8 }}
// animate={{ scale: 1.2 }}
// transition={{ duration: 2, repeat: Infinity, repeatType: "reverse" }}
// className="w-12 h-12 bg-gradient-to-tr from-blue-500 to-purple-500 rounded-lg"
// />
// </div>
// <div className="bg-green-500/20 p-4 rounded-xl aspect-square flex items-center justify-center">
// <motion.div
// initial={{ opacity: 0.5 }}
// animate={{ opacity: 1 }}
// transition={{ duration: 2, repeat: Infinity, repeatType: "reverse" }}
// className="w-12 h-12 bg-gradient-to-br from-green-500 to-blue-500 rounded-full"
// />
// </div>
// <div className="bg-pink-500/20 p-4 rounded-xl aspect-square flex items-center justify-center">
// <motion.div
// animate={{
// scale: [1, 1.2, 1],
// rotate: [0, 90, 0]
// }}
// transition={{ duration: 4, repeat: Infinity }}
// className="w-12 h-12 bg-gradient-to-bl from-pink-500 to-purple-500 rounded-lg"
// />
// </div>
// </div>
// </motion.div>
// );
// };
const items = [
{
title: "Drag & Drop No-Code Builder",
description: (
<span className="text-sm">
Easily create robust MicroSaaS applications using our intuitive drag-and-drop interface. Empower yourself to design custom workflows without writing a single line of code, streamlining operations and enhancing efficiency.
</span>
),
header: <SkeletonOne />,
className: "md:col-span-1 md:row-span-2",
icon: <IconClipboardCopy className="h-4 w-4 text-neutral-500" />,
},
{
title: "Writing Simplified",
description: (
<span className="text-sm">
Transform your writing process with the power of AI. Use the built-in AI writer to generate, refine, or continue content effortlessly.
</span>
),
header: <SkeletonTwo />,
className: "md:col-span-1",
icon: <IconFileBroken className="h-4 w-4 text-neutral-500" />,
},
{
title: "Monetize Smarter",
description: (
<span className="text-sm">
Launch your own community or tap into our marketplace to sell AI subscriptions to SMBs and beyond. Transform your ideas into profitable ventures.
</span>
),
header: <SkeletonThree />,
className: "md:col-span-1",
icon: <IconSignature className="h-4 w-4 text-neutral-500" />,
},
{
title: "Integrated Creative Tools",
description: (
<span className="text-sm">
From forms to video editors, AI writers to newsletter creators, we've got you covered. Access a comprehensive suite of tools designed to enhance your creative workflow.
</span>
),
header: <SkeletonFour />,
className: "md:col-span-2",
icon: <IconTableColumn className="h-4 w-4 text-neutral-500" />,
},
// {
// title: "Smart Templates",
// description: (
// <span className="text-sm">
// Access a library of intelligent templates that adapt to your needs. Each template is powered by AI to provide personalized starting points.
// </span>
// ),
// header: <SkeletonFive />,
// className: "md:col-span-1",
// icon: <IconBoxAlignRightFilled className="h-4 w-4 text-neutral-500" />,
// }
];