feat: enhance UI components with framer-motion animations
- Added framer-motion for animations in Features, Footer, Header, Hero, and Button components. - Implemented entrance animations for feature cards and section headers. - Enhanced button interactions with ripple effects and gradient overlays. - Improved mobile menu animations and transitions. - Added animated stats and placeholders in the Hero section. - Updated package.json to include framer-motion dependency.
This commit is contained in:
parent
bfb2de8298
commit
8c2111702b
@ -1,4 +1,4 @@
|
|||||||
# Inteliq UI Kit - React.js Project
|
{# Inteliq UI Kit - React.js Project
|
||||||
|
|
||||||
A modern React.js project built with Vite and TypeScript, implementing a comprehensive UI kit based on Figma designs.
|
A modern React.js project built with Vite and TypeScript, implementing a comprehensive UI kit based on Figma designs.
|
||||||
|
|
||||||
|
|||||||
49
package-lock.json
generated
49
package-lock.json
generated
@ -10,6 +10,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"autoprefixer": "^10.4.21",
|
"autoprefixer": "^10.4.21",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
|
"framer-motion": "^12.23.12",
|
||||||
"lucide-react": "^0.535.0",
|
"lucide-react": "^0.535.0",
|
||||||
"npx": "^10.2.2",
|
"npx": "^10.2.2",
|
||||||
"postcss": "^8.5.6",
|
"postcss": "^8.5.6",
|
||||||
@ -2635,6 +2636,33 @@
|
|||||||
"url": "https://github.com/sponsors/rawify"
|
"url": "https://github.com/sponsors/rawify"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/framer-motion": {
|
||||||
|
"version": "12.23.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.23.12.tgz",
|
||||||
|
"integrity": "sha512-6e78rdVtnBvlEVgu6eFEAgG9v3wLnYEboM8I5O5EXvfKC8gxGQB8wXJdhkMy10iVcn05jl6CNw7/HTsTCfwcWg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"motion-dom": "^12.23.12",
|
||||||
|
"motion-utils": "^12.23.6",
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@emotion/is-prop-valid": "*",
|
||||||
|
"react": "^18.0.0 || ^19.0.0",
|
||||||
|
"react-dom": "^18.0.0 || ^19.0.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@emotion/is-prop-valid": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/fsevents": {
|
"node_modules/fsevents": {
|
||||||
"version": "2.3.3",
|
"version": "2.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
||||||
@ -3368,6 +3396,21 @@
|
|||||||
"node": ">=16 || 14 >=14.17"
|
"node": ">=16 || 14 >=14.17"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/motion-dom": {
|
||||||
|
"version": "12.23.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.23.12.tgz",
|
||||||
|
"integrity": "sha512-RcR4fvMCTESQBD/uKQe49D5RUeDOokkGRmz4ceaJKDBgHYtZtntC/s2vLvY38gqGaytinij/yi3hMcWVcEF5Kw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"motion-utils": "^12.23.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/motion-utils": {
|
||||||
|
"version": "12.23.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.23.6.tgz",
|
||||||
|
"integrity": "sha512-eAWoPgr4eFEOFfg2WjIsMoqJTW6Z8MTUCgn/GZ3VRpClWBdnbjryiA3ZSNLyxCTmCQx4RmYX6jX1iWHbenUPNQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/ms": {
|
"node_modules/ms": {
|
||||||
"version": "2.1.3",
|
"version": "2.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||||
@ -8902,6 +8945,12 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "Apache-2.0"
|
"license": "Apache-2.0"
|
||||||
},
|
},
|
||||||
|
"node_modules/tslib": {
|
||||||
|
"version": "2.8.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
||||||
|
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
||||||
|
"license": "0BSD"
|
||||||
|
},
|
||||||
"node_modules/type-check": {
|
"node_modules/type-check": {
|
||||||
"version": "0.4.0",
|
"version": "0.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
|
||||||
|
|||||||
@ -12,6 +12,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"autoprefixer": "^10.4.21",
|
"autoprefixer": "^10.4.21",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
|
"framer-motion": "^12.23.12",
|
||||||
"lucide-react": "^0.535.0",
|
"lucide-react": "^0.535.0",
|
||||||
"npx": "^10.2.2",
|
"npx": "^10.2.2",
|
||||||
"postcss": "^8.5.6",
|
"postcss": "^8.5.6",
|
||||||
|
|||||||
@ -1,25 +1,126 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { Zap, Shield, Smartphone, Code, Palette, Users } from 'lucide-react'
|
import { Zap, Shield, Smartphone, Code, Palette, Users } from 'lucide-react'
|
||||||
|
import { motion, useInView, useAnimation } from 'framer-motion'
|
||||||
|
|
||||||
interface FeatureCardProps {
|
interface FeatureCardProps {
|
||||||
icon: React.ReactNode
|
icon: React.ReactNode
|
||||||
title: string
|
title: string
|
||||||
description: string
|
description: string
|
||||||
|
index: number
|
||||||
}
|
}
|
||||||
|
|
||||||
const FeatureCard: React.FC<FeatureCardProps> = ({ icon, title, description }) => {
|
const FeatureCard: React.FC<FeatureCardProps> = ({ icon, title, description, index }) => {
|
||||||
|
const controls = useAnimation()
|
||||||
|
const ref = React.useRef(null)
|
||||||
|
const isInView = useInView(ref, { once: true })
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (isInView) {
|
||||||
|
controls.start("visible")
|
||||||
|
}
|
||||||
|
}, [controls, isInView])
|
||||||
|
|
||||||
|
const cardVariants = {
|
||||||
|
hidden: {
|
||||||
|
opacity: 0,
|
||||||
|
y: 50,
|
||||||
|
scale: 0.8
|
||||||
|
},
|
||||||
|
visible: {
|
||||||
|
opacity: 1,
|
||||||
|
y: 0,
|
||||||
|
scale: 1,
|
||||||
|
transition: {
|
||||||
|
duration: 0.6,
|
||||||
|
delay: index * 0.1,
|
||||||
|
type: "spring" as const,
|
||||||
|
stiffness: 100,
|
||||||
|
damping: 15
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="bg-white p-8 rounded-2xl shadow-sm border border-gray-100 hover:shadow-lg transition-shadow group">
|
<motion.div
|
||||||
<div className="w-12 h-12 bg-primary-100 rounded-xl flex items-center justify-center mb-6 group-hover:bg-primary-200 transition-colors">
|
ref={ref}
|
||||||
{icon}
|
variants={cardVariants}
|
||||||
</div>
|
initial="hidden"
|
||||||
<h3 className="text-xl font-semibold text-gray-900 mb-3">{title}</h3>
|
animate={controls}
|
||||||
<p className="text-gray-600 leading-relaxed">{description}</p>
|
whileHover={{
|
||||||
</div>
|
y: -10,
|
||||||
|
scale: 1.05,
|
||||||
|
boxShadow: "0 25px 50px rgba(0, 0, 0, 0.15)",
|
||||||
|
transition: { duration: 0.3 }
|
||||||
|
}}
|
||||||
|
className="bg-white p-8 rounded-2xl shadow-sm border border-gray-100 hover:shadow-lg transition-shadow group cursor-pointer"
|
||||||
|
>
|
||||||
|
<motion.div
|
||||||
|
className="w-12 h-12 bg-primary-100 rounded-xl flex items-center justify-center mb-6 group-hover:bg-primary-200 transition-colors"
|
||||||
|
whileHover={{
|
||||||
|
rotate: 360,
|
||||||
|
scale: 1.2,
|
||||||
|
backgroundColor: "#bae6fd"
|
||||||
|
}}
|
||||||
|
transition={{ duration: 0.5 }}
|
||||||
|
>
|
||||||
|
<motion.div
|
||||||
|
animate={{
|
||||||
|
rotate: [0, 10, -10, 0],
|
||||||
|
}}
|
||||||
|
transition={{
|
||||||
|
duration: 2,
|
||||||
|
repeat: Infinity,
|
||||||
|
ease: "easeInOut"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{icon}
|
||||||
|
</motion.div>
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
<motion.h3
|
||||||
|
className="text-xl font-semibold text-gray-900 mb-3"
|
||||||
|
initial={{ opacity: 0 }}
|
||||||
|
animate={{ opacity: 1 }}
|
||||||
|
transition={{ delay: index * 0.1 + 0.3 }}
|
||||||
|
>
|
||||||
|
{title}
|
||||||
|
</motion.h3>
|
||||||
|
|
||||||
|
<motion.p
|
||||||
|
className="text-gray-600 leading-relaxed"
|
||||||
|
initial={{ opacity: 0 }}
|
||||||
|
animate={{ opacity: 1 }}
|
||||||
|
transition={{ delay: index * 0.1 + 0.5 }}
|
||||||
|
>
|
||||||
|
{description}
|
||||||
|
</motion.p>
|
||||||
|
|
||||||
|
{/* Hover effect overlay */}
|
||||||
|
<motion.div
|
||||||
|
className="absolute inset-0 bg-gradient-to-r from-primary-500/5 to-primary-600/5 rounded-2xl opacity-0"
|
||||||
|
whileHover={{ opacity: 1 }}
|
||||||
|
transition={{ duration: 0.3 }}
|
||||||
|
/>
|
||||||
|
</motion.div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const Features: React.FC = () => {
|
const Features: React.FC = () => {
|
||||||
|
const titleRef = React.useRef(null)
|
||||||
|
const isTitleInView = useInView(titleRef, { once: true })
|
||||||
|
|
||||||
|
const titleVariants = {
|
||||||
|
hidden: { opacity: 0, y: 50 },
|
||||||
|
visible: {
|
||||||
|
opacity: 1,
|
||||||
|
y: 0,
|
||||||
|
transition: {
|
||||||
|
duration: 0.8,
|
||||||
|
type: "spring" as const,
|
||||||
|
stiffness: 100
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
const features = [
|
const features = [
|
||||||
{
|
{
|
||||||
icon: <Zap className="w-6 h-6 text-primary-600" />,
|
icon: <Zap className="w-6 h-6 text-primary-600" />,
|
||||||
@ -54,41 +155,129 @@ const Features: React.FC = () => {
|
|||||||
]
|
]
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="py-20 lg:py-32 bg-gray-50">
|
<section className="py-20 lg:py-32 bg-gray-50 overflow-hidden">
|
||||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
{/* Section Header */}
|
{/* Section Header */}
|
||||||
<div className="text-center space-y-4 mb-16">
|
<motion.div
|
||||||
<div className="inline-flex items-center px-3 py-1 rounded-full text-sm font-medium bg-primary-100 text-primary-800">
|
ref={titleRef}
|
||||||
|
className="text-center space-y-4 mb-16"
|
||||||
|
variants={titleVariants}
|
||||||
|
initial="hidden"
|
||||||
|
animate={isTitleInView ? "visible" : "hidden"}
|
||||||
|
>
|
||||||
|
<motion.div
|
||||||
|
className="inline-flex items-center px-3 py-1 rounded-full text-sm font-medium bg-primary-100 text-primary-800"
|
||||||
|
whileHover={{ scale: 1.05 }}
|
||||||
|
animate={{
|
||||||
|
boxShadow: [
|
||||||
|
"0 0 0 0 rgba(2, 132, 199, 0)",
|
||||||
|
"0 0 0 10px rgba(2, 132, 199, 0.1)",
|
||||||
|
"0 0 0 0 rgba(2, 132, 199, 0)"
|
||||||
|
]
|
||||||
|
}}
|
||||||
|
transition={{ duration: 2, repeat: Infinity }}
|
||||||
|
>
|
||||||
✨ Features
|
✨ Features
|
||||||
</div>
|
</motion.div>
|
||||||
<h2 className="text-3xl lg:text-5xl font-bold text-gray-900">
|
|
||||||
|
<motion.h2
|
||||||
|
className="text-3xl lg:text-5xl font-bold text-gray-900"
|
||||||
|
initial={{ opacity: 0, y: 30 }}
|
||||||
|
animate={isTitleInView ? { opacity: 1, y: 0 } : {}}
|
||||||
|
transition={{ delay: 0.2, duration: 0.8 }}
|
||||||
|
>
|
||||||
Everything you need to
|
Everything you need to
|
||||||
<span className="text-primary-600"> build amazing UIs</span>
|
<motion.span
|
||||||
</h2>
|
className="text-primary-600"
|
||||||
<p className="text-xl text-gray-600 max-w-3xl mx-auto leading-relaxed">
|
animate={{
|
||||||
|
color: ["#0284c7", "#0ea5e9", "#38bdf8", "#0284c7"]
|
||||||
|
}}
|
||||||
|
transition={{ duration: 3, repeat: Infinity }}
|
||||||
|
> build amazing UIs</motion.span>
|
||||||
|
</motion.h2>
|
||||||
|
|
||||||
|
<motion.p
|
||||||
|
className="text-xl text-gray-600 max-w-3xl mx-auto leading-relaxed"
|
||||||
|
initial={{ opacity: 0, y: 30 }}
|
||||||
|
animate={isTitleInView ? { opacity: 1, y: 0 } : {}}
|
||||||
|
transition={{ delay: 0.4, duration: 0.8 }}
|
||||||
|
>
|
||||||
Our comprehensive UI kit provides all the components and tools you need
|
Our comprehensive UI kit provides all the components and tools you need
|
||||||
to create beautiful, accessible, and performant user interfaces.
|
to create beautiful, accessible, and performant user interfaces.
|
||||||
</p>
|
</motion.p>
|
||||||
</div>
|
</motion.div>
|
||||||
|
|
||||||
{/* Features Grid */}
|
{/* Features Grid */}
|
||||||
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-8">
|
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||||
{features.map((feature, index) => (
|
{features.map((feature, index) => (
|
||||||
<FeatureCard
|
<FeatureCard
|
||||||
key={index}
|
key={feature.title}
|
||||||
icon={feature.icon}
|
icon={feature.icon}
|
||||||
title={feature.title}
|
title={feature.title}
|
||||||
description={feature.description}
|
description={feature.description}
|
||||||
|
index={index}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Bottom CTA */}
|
{/* Bottom CTA with sophisticated animation */}
|
||||||
<div className="text-center mt-16">
|
<motion.div
|
||||||
<button className="bg-primary-600 text-white px-8 py-4 rounded-xl font-semibold hover:bg-primary-700 transition-colors">
|
className="text-center mt-16"
|
||||||
Explore All Components
|
initial={{ opacity: 0, y: 50 }}
|
||||||
</button>
|
whileInView={{ opacity: 1, y: 0 }}
|
||||||
</div>
|
viewport={{ once: true }}
|
||||||
|
transition={{ delay: 0.8, duration: 0.6 }}
|
||||||
|
>
|
||||||
|
<motion.button
|
||||||
|
className="bg-primary-600 text-white px-8 py-4 rounded-xl font-semibold hover:bg-primary-700 transition-colors relative overflow-hidden"
|
||||||
|
whileHover={{
|
||||||
|
scale: 1.05,
|
||||||
|
boxShadow: "0 20px 40px rgba(2, 132, 199, 0.3)"
|
||||||
|
}}
|
||||||
|
whileTap={{ scale: 0.95 }}
|
||||||
|
>
|
||||||
|
{/* Animated background gradient */}
|
||||||
|
<motion.div
|
||||||
|
className="absolute inset-0 bg-gradient-to-r from-primary-500 via-primary-600 to-primary-700"
|
||||||
|
animate={{
|
||||||
|
x: ["-100%", "100%"]
|
||||||
|
}}
|
||||||
|
transition={{
|
||||||
|
duration: 2,
|
||||||
|
repeat: Infinity,
|
||||||
|
ease: "linear" as const
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<span className="relative z-10">Explore All Components</span>
|
||||||
|
</motion.button>
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
{/* Background animated elements */}
|
||||||
|
<motion.div
|
||||||
|
className="absolute top-20 left-10 w-20 h-20 bg-primary-200 rounded-full opacity-20"
|
||||||
|
animate={{
|
||||||
|
scale: [1, 1.2, 1],
|
||||||
|
rotate: [0, 180, 360],
|
||||||
|
}}
|
||||||
|
transition={{
|
||||||
|
duration: 8,
|
||||||
|
repeat: Infinity,
|
||||||
|
ease: "easeInOut" as const
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<motion.div
|
||||||
|
className="absolute bottom-20 right-10 w-16 h-16 bg-primary-300 rounded-full opacity-20"
|
||||||
|
animate={{
|
||||||
|
y: [-20, 20, -20],
|
||||||
|
x: [-10, 10, -10],
|
||||||
|
}}
|
||||||
|
transition={{
|
||||||
|
duration: 6,
|
||||||
|
repeat: Infinity,
|
||||||
|
ease: "easeInOut" as const,
|
||||||
|
delay: 2
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -1,95 +1,229 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { Github, Twitter, Linkedin, Mail } from 'lucide-react'
|
import { Github, Twitter, Linkedin, Mail } from 'lucide-react'
|
||||||
|
import { motion, useInView } from 'framer-motion'
|
||||||
|
|
||||||
const Footer: React.FC = () => {
|
const Footer: React.FC = () => {
|
||||||
|
const ref = React.useRef(null)
|
||||||
|
const isInView = useInView(ref, { once: true })
|
||||||
|
|
||||||
|
const containerVariants = {
|
||||||
|
hidden: { opacity: 0 },
|
||||||
|
visible: {
|
||||||
|
opacity: 1,
|
||||||
|
transition: {
|
||||||
|
staggerChildren: 0.1,
|
||||||
|
delayChildren: 0.2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const itemVariants = {
|
||||||
|
hidden: { y: 30, opacity: 0 },
|
||||||
|
visible: {
|
||||||
|
y: 0,
|
||||||
|
opacity: 1,
|
||||||
|
transition: {
|
||||||
|
duration: 0.6,
|
||||||
|
ease: "easeOut" as const
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const socialIcons = [
|
||||||
|
{ Icon: Github, href: "#", color: "hover:text-gray-300" },
|
||||||
|
{ Icon: Twitter, href: "#", color: "hover:text-blue-400" },
|
||||||
|
{ Icon: Linkedin, href: "#", color: "hover:text-blue-500" },
|
||||||
|
{ Icon: Mail, href: "#", color: "hover:text-green-400" }
|
||||||
|
]
|
||||||
return (
|
return (
|
||||||
<footer className="bg-gray-900 text-white">
|
<motion.footer
|
||||||
|
className="bg-gray-900 text-white"
|
||||||
|
initial={{ opacity: 0 }}
|
||||||
|
whileInView={{ opacity: 1 }}
|
||||||
|
viewport={{ once: true }}
|
||||||
|
transition={{ duration: 0.8 }}
|
||||||
|
>
|
||||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
{/* Main Footer Content */}
|
{/* Main Footer Content */}
|
||||||
<div className="py-16">
|
<motion.div
|
||||||
|
ref={ref}
|
||||||
|
className="py-16"
|
||||||
|
variants={containerVariants}
|
||||||
|
initial="hidden"
|
||||||
|
animate={isInView ? "visible" : "hidden"}
|
||||||
|
>
|
||||||
<div className="grid lg:grid-cols-4 gap-8">
|
<div className="grid lg:grid-cols-4 gap-8">
|
||||||
{/* Brand Section */}
|
{/* Brand Section */}
|
||||||
<div className="lg:col-span-1">
|
<motion.div
|
||||||
<h3 className="text-2xl font-bold mb-4">Inteliq</h3>
|
className="lg:col-span-1"
|
||||||
<p className="text-gray-400 mb-6 leading-relaxed">
|
variants={itemVariants}
|
||||||
|
>
|
||||||
|
<motion.h3
|
||||||
|
className="text-2xl font-bold mb-4"
|
||||||
|
whileHover={{ scale: 1.05 }}
|
||||||
|
animate={{
|
||||||
|
textShadow: [
|
||||||
|
"0 0 0 rgba(2, 132, 199, 0)",
|
||||||
|
"0 0 20px rgba(2, 132, 199, 0.3)",
|
||||||
|
"0 0 0 rgba(2, 132, 199, 0)"
|
||||||
|
]
|
||||||
|
}}
|
||||||
|
transition={{ duration: 3, repeat: Infinity }}
|
||||||
|
>
|
||||||
|
Inteliq
|
||||||
|
</motion.h3>
|
||||||
|
<motion.p
|
||||||
|
className="text-gray-400 mb-6 leading-relaxed"
|
||||||
|
variants={itemVariants}
|
||||||
|
>
|
||||||
Modern UI components for React applications.
|
Modern UI components for React applications.
|
||||||
Build beautiful interfaces faster with our comprehensive kit.
|
Build beautiful interfaces faster with our comprehensive kit.
|
||||||
</p>
|
</motion.p>
|
||||||
<div className="flex space-x-4">
|
<div className="flex space-x-4">
|
||||||
<a href="#" className="text-gray-400 hover:text-white transition-colors">
|
{socialIcons.map(({ Icon, href, color }, index) => (
|
||||||
<Github size={20} />
|
<motion.a
|
||||||
</a>
|
key={index}
|
||||||
<a href="#" className="text-gray-400 hover:text-white transition-colors">
|
href={href}
|
||||||
<Twitter size={20} />
|
className={`text-gray-400 ${color} transition-colors`}
|
||||||
</a>
|
whileHover={{
|
||||||
<a href="#" className="text-gray-400 hover:text-white transition-colors">
|
scale: 1.2,
|
||||||
<Linkedin size={20} />
|
y: -3,
|
||||||
</a>
|
rotate: 5
|
||||||
<a href="#" className="text-gray-400 hover:text-white transition-colors">
|
}}
|
||||||
<Mail size={20} />
|
whileTap={{ scale: 0.9 }}
|
||||||
</a>
|
initial={{ opacity: 0, y: 20 }}
|
||||||
|
animate={{ opacity: 1, y: 0 }}
|
||||||
|
transition={{ delay: 0.5 + index * 0.1 }}
|
||||||
|
>
|
||||||
|
<Icon size={20} />
|
||||||
|
</motion.a>
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</motion.div>
|
||||||
|
|
||||||
{/* Product Links */}
|
{/* Product Links */}
|
||||||
<div>
|
<motion.div variants={itemVariants}>
|
||||||
<h4 className="font-semibold mb-4">Product</h4>
|
<motion.h4
|
||||||
|
className="font-semibold mb-4"
|
||||||
|
whileHover={{ color: "#38bdf8" }}
|
||||||
|
>
|
||||||
|
Product
|
||||||
|
</motion.h4>
|
||||||
<ul className="space-y-3">
|
<ul className="space-y-3">
|
||||||
<li><a href="#" className="text-gray-400 hover:text-white transition-colors">Components</a></li>
|
{['Components', 'Templates', 'Icons', 'Playground', 'Figma Kit'].map((item, index) => (
|
||||||
<li><a href="#" className="text-gray-400 hover:text-white transition-colors">Templates</a></li>
|
<motion.li
|
||||||
<li><a href="#" className="text-gray-400 hover:text-white transition-colors">Icons</a></li>
|
key={item}
|
||||||
<li><a href="#" className="text-gray-400 hover:text-white transition-colors">Playground</a></li>
|
initial={{ opacity: 0, x: -20 }}
|
||||||
<li><a href="#" className="text-gray-400 hover:text-white transition-colors">Figma Kit</a></li>
|
animate={{ opacity: 1, x: 0 }}
|
||||||
|
transition={{ delay: 0.3 + index * 0.1 }}
|
||||||
|
>
|
||||||
|
<motion.a
|
||||||
|
href="#"
|
||||||
|
className="text-gray-400 hover:text-white transition-colors"
|
||||||
|
whileHover={{ x: 5, color: "#ffffff" }}
|
||||||
|
>
|
||||||
|
{item}
|
||||||
|
</motion.a>
|
||||||
|
</motion.li>
|
||||||
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</motion.div>
|
||||||
|
|
||||||
{/* Resources Links */}
|
{/* Resources Links */}
|
||||||
<div>
|
<motion.div variants={itemVariants}>
|
||||||
<h4 className="font-semibold mb-4">Resources</h4>
|
<motion.h4
|
||||||
|
className="font-semibold mb-4"
|
||||||
|
whileHover={{ color: "#38bdf8" }}
|
||||||
|
>
|
||||||
|
Resources
|
||||||
|
</motion.h4>
|
||||||
<ul className="space-y-3">
|
<ul className="space-y-3">
|
||||||
<li><a href="#" className="text-gray-400 hover:text-white transition-colors">Documentation</a></li>
|
{['Documentation', 'Getting Started', 'Examples', 'Blog', 'Community'].map((item, index) => (
|
||||||
<li><a href="#" className="text-gray-400 hover:text-white transition-colors">Getting Started</a></li>
|
<motion.li
|
||||||
<li><a href="#" className="text-gray-400 hover:text-white transition-colors">Examples</a></li>
|
key={item}
|
||||||
<li><a href="#" className="text-gray-400 hover:text-white transition-colors">Blog</a></li>
|
initial={{ opacity: 0, x: -20 }}
|
||||||
<li><a href="#" className="text-gray-400 hover:text-white transition-colors">Community</a></li>
|
animate={{ opacity: 1, x: 0 }}
|
||||||
|
transition={{ delay: 0.4 + index * 0.1 }}
|
||||||
|
>
|
||||||
|
<motion.a
|
||||||
|
href="#"
|
||||||
|
className="text-gray-400 hover:text-white transition-colors"
|
||||||
|
whileHover={{ x: 5, color: "#ffffff" }}
|
||||||
|
>
|
||||||
|
{item}
|
||||||
|
</motion.a>
|
||||||
|
</motion.li>
|
||||||
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</motion.div>
|
||||||
|
|
||||||
{/* Company Links */}
|
{/* Company Links */}
|
||||||
<div>
|
<motion.div variants={itemVariants}>
|
||||||
<h4 className="font-semibold mb-4">Company</h4>
|
<motion.h4
|
||||||
|
className="font-semibold mb-4"
|
||||||
|
whileHover={{ color: "#38bdf8" }}
|
||||||
|
>
|
||||||
|
Company
|
||||||
|
</motion.h4>
|
||||||
<ul className="space-y-3">
|
<ul className="space-y-3">
|
||||||
<li><a href="#" className="text-gray-400 hover:text-white transition-colors">About</a></li>
|
{['About', 'Careers', 'Contact', 'Privacy', 'Terms'].map((item, index) => (
|
||||||
<li><a href="#" className="text-gray-400 hover:text-white transition-colors">Careers</a></li>
|
<motion.li
|
||||||
<li><a href="#" className="text-gray-400 hover:text-white transition-colors">Contact</a></li>
|
key={item}
|
||||||
<li><a href="#" className="text-gray-400 hover:text-white transition-colors">Privacy</a></li>
|
initial={{ opacity: 0, x: -20 }}
|
||||||
<li><a href="#" className="text-gray-400 hover:text-white transition-colors">Terms</a></li>
|
animate={{ opacity: 1, x: 0 }}
|
||||||
|
transition={{ delay: 0.5 + index * 0.1 }}
|
||||||
|
>
|
||||||
|
<motion.a
|
||||||
|
href="#"
|
||||||
|
className="text-gray-400 hover:text-white transition-colors"
|
||||||
|
whileHover={{ x: 5, color: "#ffffff" }}
|
||||||
|
>
|
||||||
|
{item}
|
||||||
|
</motion.a>
|
||||||
|
</motion.li>
|
||||||
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</motion.div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</motion.div>
|
||||||
|
|
||||||
{/* Bottom Bar */}
|
{/* Bottom Bar */}
|
||||||
<div className="border-t border-gray-800 py-8">
|
<motion.div
|
||||||
|
className="border-t border-gray-800 py-8"
|
||||||
|
initial={{ opacity: 0, y: 20 }}
|
||||||
|
whileInView={{ opacity: 1, y: 0 }}
|
||||||
|
viewport={{ once: true }}
|
||||||
|
transition={{ delay: 0.8, duration: 0.6 }}
|
||||||
|
>
|
||||||
<div className="flex flex-col md:flex-row justify-between items-center">
|
<div className="flex flex-col md:flex-row justify-between items-center">
|
||||||
<p className="text-gray-400 text-sm">
|
<motion.p
|
||||||
|
className="text-gray-400 text-sm"
|
||||||
|
animate={{
|
||||||
|
opacity: [0.7, 1, 0.7]
|
||||||
|
}}
|
||||||
|
transition={{ duration: 3, repeat: Infinity }}
|
||||||
|
>
|
||||||
© 2025 Inteliq UI Kit. All rights reserved.
|
© 2025 Inteliq UI Kit. All rights reserved.
|
||||||
</p>
|
</motion.p>
|
||||||
<div className="flex space-x-6 mt-4 md:mt-0">
|
<div className="flex space-x-6 mt-4 md:mt-0">
|
||||||
<a href="#" className="text-gray-400 hover:text-white text-sm transition-colors">
|
{['Privacy Policy', 'Terms of Service', 'Cookie Policy'].map((item, index) => (
|
||||||
Privacy Policy
|
<motion.a
|
||||||
</a>
|
key={item}
|
||||||
<a href="#" className="text-gray-400 hover:text-white text-sm transition-colors">
|
href="#"
|
||||||
Terms of Service
|
className="text-gray-400 hover:text-white text-sm transition-colors"
|
||||||
</a>
|
whileHover={{ y: -2 }}
|
||||||
<a href="#" className="text-gray-400 hover:text-white text-sm transition-colors">
|
initial={{ opacity: 0 }}
|
||||||
Cookie Policy
|
animate={{ opacity: 1 }}
|
||||||
</a>
|
transition={{ delay: 1 + index * 0.1 }}
|
||||||
|
>
|
||||||
|
{item}
|
||||||
|
</motion.a>
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</motion.div>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</motion.footer>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,76 +1,139 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { Menu, X } from 'lucide-react'
|
import { Menu, X } from 'lucide-react'
|
||||||
|
import { motion, AnimatePresence } from 'framer-motion'
|
||||||
|
|
||||||
const Header: React.FC = () => {
|
const Header: React.FC = () => {
|
||||||
const [isMenuOpen, setIsMenuOpen] = React.useState(false)
|
const [isMenuOpen, setIsMenuOpen] = React.useState(false)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<header className="bg-white shadow-sm border-b border-gray-200">
|
<motion.header
|
||||||
|
className="bg-white shadow-sm border-b border-gray-200"
|
||||||
|
initial={{ y: -100, opacity: 0 }}
|
||||||
|
animate={{ y: 0, opacity: 1 }}
|
||||||
|
transition={{ type: "spring", stiffness: 100, damping: 20 }}
|
||||||
|
>
|
||||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
<div className="flex justify-between items-center h-16">
|
<div className="flex justify-between items-center h-16">
|
||||||
{/* Logo */}
|
{/* Logo */}
|
||||||
<div className="flex-shrink-0">
|
<motion.div
|
||||||
|
className="flex-shrink-0"
|
||||||
|
whileHover={{ scale: 1.05 }}
|
||||||
|
whileTap={{ scale: 0.95 }}
|
||||||
|
>
|
||||||
<h1 className="text-2xl font-bold text-gray-900">Inteliq</h1>
|
<h1 className="text-2xl font-bold text-gray-900">Inteliq</h1>
|
||||||
</div>
|
</motion.div>
|
||||||
|
|
||||||
{/* Desktop Navigation */}
|
{/* Desktop Navigation */}
|
||||||
<nav className="hidden md:flex space-x-8">
|
<nav className="hidden md:flex space-x-8">
|
||||||
<a href="#" className="text-gray-700 hover:text-primary-600 px-3 py-2 text-sm font-medium">
|
{['Home', 'Features', 'About', 'Contact'].map((item, index) => (
|
||||||
Home
|
<motion.a
|
||||||
</a>
|
key={item}
|
||||||
<a href="#" className="text-gray-700 hover:text-primary-600 px-3 py-2 text-sm font-medium">
|
href="#"
|
||||||
Features
|
className="text-gray-700 hover:text-primary-600 px-3 py-2 text-sm font-medium relative"
|
||||||
</a>
|
whileHover={{ y: -2 }}
|
||||||
<a href="#" className="text-gray-700 hover:text-primary-600 px-3 py-2 text-sm font-medium">
|
initial={{ opacity: 0, y: 20 }}
|
||||||
About
|
animate={{ opacity: 1, y: 0 }}
|
||||||
</a>
|
transition={{ delay: index * 0.1 }}
|
||||||
<a href="#" className="text-gray-700 hover:text-primary-600 px-3 py-2 text-sm font-medium">
|
>
|
||||||
Contact
|
{item}
|
||||||
</a>
|
<motion.div
|
||||||
|
className="absolute bottom-0 left-0 w-full h-0.5 bg-primary-600"
|
||||||
|
initial={{ scaleX: 0 }}
|
||||||
|
whileHover={{ scaleX: 1 }}
|
||||||
|
transition={{ duration: 0.2 }}
|
||||||
|
/>
|
||||||
|
</motion.a>
|
||||||
|
))}
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
{/* CTA Button */}
|
{/* CTA Button */}
|
||||||
<div className="hidden md:flex items-center space-x-4">
|
<div className="hidden md:flex items-center space-x-4">
|
||||||
<button className="bg-primary-600 text-white px-6 py-2 rounded-lg font-medium hover:bg-primary-700 transition-colors">
|
<motion.button
|
||||||
|
className="bg-primary-600 text-white px-6 py-2 rounded-lg font-medium hover:bg-primary-700 transition-colors"
|
||||||
|
whileHover={{ scale: 1.05, boxShadow: "0 10px 25px rgba(2, 132, 199, 0.3)" }}
|
||||||
|
whileTap={{ scale: 0.95 }}
|
||||||
|
initial={{ opacity: 0, x: 20 }}
|
||||||
|
animate={{ opacity: 1, x: 0 }}
|
||||||
|
transition={{ delay: 0.5 }}
|
||||||
|
>
|
||||||
Get Started
|
Get Started
|
||||||
</button>
|
</motion.button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Mobile menu button */}
|
{/* Mobile menu button */}
|
||||||
<div className="md:hidden">
|
<div className="md:hidden">
|
||||||
<button
|
<motion.button
|
||||||
onClick={() => setIsMenuOpen(!isMenuOpen)}
|
onClick={() => setIsMenuOpen(!isMenuOpen)}
|
||||||
className="text-gray-700 hover:text-gray-900"
|
className="text-gray-700 hover:text-gray-900"
|
||||||
|
whileTap={{ scale: 0.9 }}
|
||||||
>
|
>
|
||||||
{isMenuOpen ? <X size={24} /> : <Menu size={24} />}
|
<AnimatePresence mode="wait">
|
||||||
</button>
|
{isMenuOpen ? (
|
||||||
|
<motion.div
|
||||||
|
key="close"
|
||||||
|
initial={{ rotate: 0 }}
|
||||||
|
animate={{ rotate: 180 }}
|
||||||
|
exit={{ rotate: 0 }}
|
||||||
|
transition={{ duration: 0.2 }}
|
||||||
|
>
|
||||||
|
<X size={24} />
|
||||||
|
</motion.div>
|
||||||
|
) : (
|
||||||
|
<motion.div
|
||||||
|
key="menu"
|
||||||
|
initial={{ rotate: 180 }}
|
||||||
|
animate={{ rotate: 0 }}
|
||||||
|
exit={{ rotate: 180 }}
|
||||||
|
transition={{ duration: 0.2 }}
|
||||||
|
>
|
||||||
|
<Menu size={24} />
|
||||||
|
</motion.div>
|
||||||
|
)}
|
||||||
|
</AnimatePresence>
|
||||||
|
</motion.button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Mobile Navigation */}
|
{/* Mobile Navigation */}
|
||||||
{isMenuOpen && (
|
<AnimatePresence>
|
||||||
<div className="md:hidden">
|
{isMenuOpen && (
|
||||||
<div className="px-2 pt-2 pb-3 space-y-1 sm:px-3 bg-white border-t border-gray-200">
|
<motion.div
|
||||||
<a href="#" className="block px-3 py-2 text-base font-medium text-gray-700 hover:text-primary-600">
|
className="md:hidden"
|
||||||
Home
|
initial={{ height: 0, opacity: 0 }}
|
||||||
</a>
|
animate={{ height: "auto", opacity: 1 }}
|
||||||
<a href="#" className="block px-3 py-2 text-base font-medium text-gray-700 hover:text-primary-600">
|
exit={{ height: 0, opacity: 0 }}
|
||||||
Features
|
transition={{ duration: 0.3, ease: "easeInOut" }}
|
||||||
</a>
|
>
|
||||||
<a href="#" className="block px-3 py-2 text-base font-medium text-gray-700 hover:text-primary-600">
|
<div className="px-2 pt-2 pb-3 space-y-1 sm:px-3 bg-white border-t border-gray-200 overflow-hidden">
|
||||||
About
|
{['Home', 'Features', 'About', 'Contact'].map((item, index) => (
|
||||||
</a>
|
<motion.a
|
||||||
<a href="#" className="block px-3 py-2 text-base font-medium text-gray-700 hover:text-primary-600">
|
key={item}
|
||||||
Contact
|
href="#"
|
||||||
</a>
|
className="block px-3 py-2 text-base font-medium text-gray-700 hover:text-primary-600"
|
||||||
<button className="w-full mt-4 bg-primary-600 text-white px-6 py-2 rounded-lg font-medium hover:bg-primary-700 transition-colors">
|
initial={{ x: -20, opacity: 0 }}
|
||||||
Get Started
|
animate={{ x: 0, opacity: 1 }}
|
||||||
</button>
|
transition={{ delay: index * 0.1 }}
|
||||||
</div>
|
whileHover={{ x: 10 }}
|
||||||
</div>
|
>
|
||||||
)}
|
{item}
|
||||||
|
</motion.a>
|
||||||
|
))}
|
||||||
|
<motion.button
|
||||||
|
className="w-full mt-4 bg-primary-600 text-white px-6 py-2 rounded-lg font-medium hover:bg-primary-700 transition-colors"
|
||||||
|
initial={{ y: 20, opacity: 0 }}
|
||||||
|
animate={{ y: 0, opacity: 1 }}
|
||||||
|
transition={{ delay: 0.4 }}
|
||||||
|
whileHover={{ scale: 1.02 }}
|
||||||
|
whileTap={{ scale: 0.98 }}
|
||||||
|
>
|
||||||
|
Get Started
|
||||||
|
</motion.button>
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
)}
|
||||||
|
</AnimatePresence>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</motion.header>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,80 +1,272 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { ArrowRight, Play } from 'lucide-react'
|
import { ArrowRight, Play } from 'lucide-react'
|
||||||
|
import { motion, useInView } from 'framer-motion'
|
||||||
|
|
||||||
const Hero: React.FC = () => {
|
const Hero: React.FC = () => {
|
||||||
|
const ref = React.useRef(null)
|
||||||
|
const isInView = useInView(ref, { once: true })
|
||||||
|
|
||||||
|
const containerVariants = {
|
||||||
|
hidden: { opacity: 0 },
|
||||||
|
visible: {
|
||||||
|
opacity: 1,
|
||||||
|
transition: {
|
||||||
|
staggerChildren: 0.2,
|
||||||
|
delayChildren: 0.3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const itemVariants = {
|
||||||
|
hidden: { y: 50, opacity: 0 },
|
||||||
|
visible: {
|
||||||
|
y: 0,
|
||||||
|
opacity: 1,
|
||||||
|
transition: {
|
||||||
|
type: "spring" as const,
|
||||||
|
stiffness: 100,
|
||||||
|
damping: 20
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<section className="bg-gradient-to-br from-primary-50 to-white">
|
<section className="bg-gradient-to-br from-primary-50 to-white overflow-hidden">
|
||||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-20 lg:py-32">
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-20 lg:py-32">
|
||||||
<div className="grid lg:grid-cols-2 gap-12 items-center">
|
<motion.div
|
||||||
|
ref={ref}
|
||||||
|
className="grid lg:grid-cols-2 gap-12 items-center"
|
||||||
|
variants={containerVariants}
|
||||||
|
initial="hidden"
|
||||||
|
animate={isInView ? "visible" : "hidden"}
|
||||||
|
>
|
||||||
{/* Left Content */}
|
{/* Left Content */}
|
||||||
<div className="space-y-8">
|
<div className="space-y-8">
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="inline-flex items-center px-3 py-1 rounded-full text-sm font-medium bg-primary-100 text-primary-800">
|
<motion.div
|
||||||
|
className="inline-flex items-center px-3 py-1 rounded-full text-sm font-medium bg-primary-100 text-primary-800"
|
||||||
|
variants={itemVariants}
|
||||||
|
whileHover={{ scale: 1.05 }}
|
||||||
|
>
|
||||||
🚀 New Update Available
|
🚀 New Update Available
|
||||||
</div>
|
</motion.div>
|
||||||
<h1 className="text-4xl lg:text-6xl font-bold text-gray-900 leading-tight">
|
|
||||||
|
<motion.h1
|
||||||
|
className="text-4xl lg:text-6xl font-bold text-gray-900 leading-tight"
|
||||||
|
variants={itemVariants}
|
||||||
|
>
|
||||||
Build Amazing
|
Build Amazing
|
||||||
<span className="text-primary-600"> UI Components</span>
|
<motion.span
|
||||||
</h1>
|
className="text-primary-600"
|
||||||
<p className="text-xl text-gray-600 leading-relaxed">
|
initial={{ backgroundPosition: "0% 50%" }}
|
||||||
|
animate={{ backgroundPosition: "100% 50%" }}
|
||||||
|
transition={{ duration: 3, repeat: Infinity, repeatType: "reverse" }}
|
||||||
|
style={{
|
||||||
|
background: "linear-gradient(90deg, #0284c7, #0ea5e9, #38bdf8, #0284c7)",
|
||||||
|
backgroundSize: "200% 100%",
|
||||||
|
WebkitBackgroundClip: "text",
|
||||||
|
WebkitTextFillColor: "transparent",
|
||||||
|
backgroundClip: "text"
|
||||||
|
}}
|
||||||
|
> UI Components</motion.span>
|
||||||
|
</motion.h1>
|
||||||
|
|
||||||
|
<motion.p
|
||||||
|
className="text-xl text-gray-600 leading-relaxed"
|
||||||
|
variants={itemVariants}
|
||||||
|
>
|
||||||
Create stunning user interfaces with our comprehensive UI kit.
|
Create stunning user interfaces with our comprehensive UI kit.
|
||||||
Designed for modern web applications with React and TypeScript.
|
Designed for modern web applications with React and TypeScript.
|
||||||
</p>
|
</motion.p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* CTA Buttons */}
|
{/* CTA Buttons */}
|
||||||
<div className="flex flex-col sm:flex-row gap-4">
|
<motion.div
|
||||||
<button className="bg-primary-600 text-white px-8 py-4 rounded-xl font-semibold hover:bg-primary-700 transition-colors flex items-center justify-center group">
|
className="flex flex-col sm:flex-row gap-4"
|
||||||
|
variants={itemVariants}
|
||||||
|
>
|
||||||
|
<motion.button
|
||||||
|
className="bg-primary-600 text-white px-8 py-4 rounded-xl font-semibold hover:bg-primary-700 transition-colors flex items-center justify-center group"
|
||||||
|
whileHover={{
|
||||||
|
scale: 1.05,
|
||||||
|
boxShadow: "0 20px 40px rgba(2, 132, 199, 0.3)",
|
||||||
|
y: -5
|
||||||
|
}}
|
||||||
|
whileTap={{ scale: 0.95 }}
|
||||||
|
>
|
||||||
Get Started
|
Get Started
|
||||||
<ArrowRight size={20} className="ml-2 group-hover:translate-x-1 transition-transform" />
|
<motion.div
|
||||||
</button>
|
className="ml-2"
|
||||||
<button className="border border-gray-300 text-gray-700 px-8 py-4 rounded-xl font-semibold hover:bg-gray-50 transition-colors flex items-center justify-center">
|
animate={{ x: [0, 5, 0] }}
|
||||||
<Play size={20} className="mr-2" />
|
transition={{ duration: 1.5, repeat: Infinity }}
|
||||||
|
>
|
||||||
|
<ArrowRight size={20} />
|
||||||
|
</motion.div>
|
||||||
|
</motion.button>
|
||||||
|
|
||||||
|
<motion.button
|
||||||
|
className="border border-gray-300 text-gray-700 px-8 py-4 rounded-xl font-semibold hover:bg-gray-50 transition-colors flex items-center justify-center group"
|
||||||
|
whileHover={{
|
||||||
|
scale: 1.05,
|
||||||
|
borderColor: "#0284c7",
|
||||||
|
boxShadow: "0 10px 25px rgba(0, 0, 0, 0.1)"
|
||||||
|
}}
|
||||||
|
whileTap={{ scale: 0.95 }}
|
||||||
|
>
|
||||||
|
<motion.div
|
||||||
|
className="mr-2"
|
||||||
|
whileHover={{ scale: 1.2, rotate: 360 }}
|
||||||
|
transition={{ duration: 0.3 }}
|
||||||
|
>
|
||||||
|
<Play size={20} />
|
||||||
|
</motion.div>
|
||||||
Watch Demo
|
Watch Demo
|
||||||
</button>
|
</motion.button>
|
||||||
</div>
|
</motion.div>
|
||||||
|
|
||||||
{/* Stats */}
|
{/* Stats */}
|
||||||
<div className="flex flex-wrap gap-8 pt-8">
|
<motion.div
|
||||||
<div>
|
className="flex flex-wrap gap-8 pt-8"
|
||||||
<div className="text-3xl font-bold text-gray-900">50+</div>
|
variants={itemVariants}
|
||||||
<div className="text-gray-600">Components</div>
|
>
|
||||||
</div>
|
{[
|
||||||
<div>
|
{ number: "50+", label: "Components" },
|
||||||
<div className="text-3xl font-bold text-gray-900">10k+</div>
|
{ number: "10k+", label: "Downloads" },
|
||||||
<div className="text-gray-600">Downloads</div>
|
{ number: "99%", label: "Satisfaction" }
|
||||||
</div>
|
].map((stat, index) => (
|
||||||
<div>
|
<motion.div
|
||||||
<div className="text-3xl font-bold text-gray-900">99%</div>
|
key={stat.label}
|
||||||
<div className="text-gray-600">Satisfaction</div>
|
initial={{ scale: 0, opacity: 0 }}
|
||||||
</div>
|
animate={{ scale: 1, opacity: 1 }}
|
||||||
</div>
|
transition={{ delay: 1 + index * 0.2, type: "spring", stiffness: 200 }}
|
||||||
|
whileHover={{ scale: 1.1, y: -5 }}
|
||||||
|
>
|
||||||
|
<motion.div
|
||||||
|
className="text-3xl font-bold text-gray-900"
|
||||||
|
animate={{ color: ["#111827", "#0284c7", "#111827"] }}
|
||||||
|
transition={{ duration: 2, repeat: Infinity, delay: index * 0.5 }}
|
||||||
|
>
|
||||||
|
{stat.number}
|
||||||
|
</motion.div>
|
||||||
|
<div className="text-gray-600">{stat.label}</div>
|
||||||
|
</motion.div>
|
||||||
|
))}
|
||||||
|
</motion.div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Right Content - Placeholder for design */}
|
{/* Right Content - Animated design placeholder */}
|
||||||
<div className="relative">
|
<motion.div
|
||||||
<div className="bg-white rounded-2xl shadow-2xl p-8 space-y-6">
|
className="relative"
|
||||||
<div className="h-4 bg-gray-200 rounded animate-pulse"></div>
|
variants={itemVariants}
|
||||||
|
>
|
||||||
|
<motion.div
|
||||||
|
className="bg-white rounded-2xl shadow-2xl p-8 space-y-6"
|
||||||
|
whileHover={{
|
||||||
|
y: -10,
|
||||||
|
boxShadow: "0 25px 50px rgba(0, 0, 0, 0.15)"
|
||||||
|
}}
|
||||||
|
animate={{
|
||||||
|
y: [-10, 10, -10]
|
||||||
|
}}
|
||||||
|
transition={{
|
||||||
|
duration: 3,
|
||||||
|
repeat: Infinity,
|
||||||
|
ease: "easeInOut" as const
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<motion.div
|
||||||
|
className="h-4 bg-gray-200 rounded"
|
||||||
|
animate={{ opacity: [0.3, 1, 0.3] }}
|
||||||
|
transition={{ duration: 2, repeat: Infinity }}
|
||||||
|
/>
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
<div className="h-3 bg-gray-200 rounded animate-pulse"></div>
|
{[1, 0.8, 0.6].map((width, index) => (
|
||||||
<div className="h-3 bg-gray-200 rounded w-5/6 animate-pulse"></div>
|
<motion.div
|
||||||
<div className="h-3 bg-gray-200 rounded w-4/6 animate-pulse"></div>
|
key={index}
|
||||||
|
className="h-3 bg-gray-200 rounded"
|
||||||
|
style={{ width: `${width * 100}%` }}
|
||||||
|
animate={{ opacity: [0.5, 1, 0.5] }}
|
||||||
|
transition={{
|
||||||
|
duration: 1.5,
|
||||||
|
repeat: Infinity,
|
||||||
|
delay: index * 0.3
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex space-x-4">
|
<div className="flex space-x-4">
|
||||||
<div className="w-20 h-10 bg-primary-200 rounded animate-pulse"></div>
|
<motion.div
|
||||||
<div className="w-20 h-10 bg-gray-200 rounded animate-pulse"></div>
|
className="w-20 h-10 bg-primary-200 rounded"
|
||||||
|
whileHover={{ scale: 1.1, backgroundColor: "#bae6fd" }}
|
||||||
|
animate={{ opacity: [0.7, 1, 0.7] }}
|
||||||
|
transition={{ duration: 2, repeat: Infinity }}
|
||||||
|
/>
|
||||||
|
<motion.div
|
||||||
|
className="w-20 h-10 bg-gray-200 rounded"
|
||||||
|
whileHover={{ scale: 1.1 }}
|
||||||
|
animate={{ opacity: [0.5, 0.8, 0.5] }}
|
||||||
|
transition={{ duration: 2.5, repeat: Infinity }}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<div className="h-2 bg-gray-200 rounded animate-pulse"></div>
|
{[1, 0.75].map((width, index) => (
|
||||||
<div className="h-2 bg-gray-200 rounded w-3/4 animate-pulse"></div>
|
<motion.div
|
||||||
|
key={index}
|
||||||
|
className="h-2 bg-gray-200 rounded"
|
||||||
|
style={{ width: `${width * 100}%` }}
|
||||||
|
animate={{ scaleX: [0.8, 1, 0.8] }}
|
||||||
|
transition={{
|
||||||
|
duration: 2,
|
||||||
|
repeat: Infinity,
|
||||||
|
delay: index * 0.5
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</motion.div>
|
||||||
|
|
||||||
{/* Floating elements */}
|
{/* Floating elements with sophisticated animations */}
|
||||||
<div className="absolute -top-4 -right-4 w-8 h-8 bg-primary-500 rounded-full opacity-20"></div>
|
<motion.div
|
||||||
<div className="absolute -bottom-4 -left-4 w-6 h-6 bg-primary-300 rounded-full opacity-30"></div>
|
className="absolute -top-4 -right-4 w-8 h-8 bg-primary-500 rounded-full"
|
||||||
</div>
|
animate={{
|
||||||
</div>
|
scale: [1, 1.2, 1],
|
||||||
|
rotate: [0, 180, 360],
|
||||||
|
opacity: [0.2, 0.8, 0.2]
|
||||||
|
}}
|
||||||
|
transition={{
|
||||||
|
duration: 4,
|
||||||
|
repeat: Infinity,
|
||||||
|
ease: "easeInOut" as const
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<motion.div
|
||||||
|
className="absolute -bottom-4 -left-4 w-6 h-6 bg-primary-300 rounded-full"
|
||||||
|
animate={{
|
||||||
|
scale: [1, 0.8, 1],
|
||||||
|
x: [-10, 10, -10],
|
||||||
|
opacity: [0.3, 0.9, 0.3]
|
||||||
|
}}
|
||||||
|
transition={{
|
||||||
|
duration: 3,
|
||||||
|
repeat: Infinity,
|
||||||
|
ease: "easeInOut" as const,
|
||||||
|
delay: 1
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<motion.div
|
||||||
|
className="absolute top-1/2 -left-8 w-4 h-4 bg-primary-400 rounded-full"
|
||||||
|
animate={{
|
||||||
|
y: [-20, 20, -20],
|
||||||
|
opacity: [0.4, 1, 0.4]
|
||||||
|
}}
|
||||||
|
transition={{
|
||||||
|
duration: 2.5,
|
||||||
|
repeat: Infinity,
|
||||||
|
ease: "easeInOut" as const,
|
||||||
|
delay: 0.5
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</motion.div>
|
||||||
|
</motion.div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -1,10 +1,12 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { clsx } from 'clsx'
|
import { clsx } from 'clsx'
|
||||||
|
import { motion } from 'framer-motion'
|
||||||
|
|
||||||
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
||||||
variant?: 'primary' | 'secondary' | 'outline' | 'ghost'
|
variant?: 'primary' | 'secondary' | 'outline' | 'ghost'
|
||||||
size?: 'sm' | 'md' | 'lg'
|
size?: 'sm' | 'md' | 'lg'
|
||||||
children: React.ReactNode
|
children: React.ReactNode
|
||||||
|
animated?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const Button: React.FC<ButtonProps> = ({
|
const Button: React.FC<ButtonProps> = ({
|
||||||
@ -12,9 +14,10 @@ const Button: React.FC<ButtonProps> = ({
|
|||||||
size = 'md',
|
size = 'md',
|
||||||
className,
|
className,
|
||||||
children,
|
children,
|
||||||
|
animated = true,
|
||||||
...props
|
...props
|
||||||
}) => {
|
}) => {
|
||||||
const baseClasses = 'inline-flex items-center justify-center font-medium rounded-lg transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2'
|
const baseClasses = 'inline-flex items-center justify-center font-medium rounded-lg transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 relative overflow-hidden'
|
||||||
|
|
||||||
const variants = {
|
const variants = {
|
||||||
primary: 'bg-primary-600 text-white hover:bg-primary-700 focus:ring-primary-500',
|
primary: 'bg-primary-600 text-white hover:bg-primary-700 focus:ring-primary-500',
|
||||||
@ -35,11 +38,70 @@ const Button: React.FC<ButtonProps> = ({
|
|||||||
sizes[size],
|
sizes[size],
|
||||||
className
|
className
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const buttonVariants = {
|
||||||
|
hover: {
|
||||||
|
scale: 1.05,
|
||||||
|
boxShadow: variant === 'primary'
|
||||||
|
? "0 10px 25px rgba(2, 132, 199, 0.3)"
|
||||||
|
: "0 10px 25px rgba(0, 0, 0, 0.1)",
|
||||||
|
transition: { duration: 0.2 }
|
||||||
|
},
|
||||||
|
tap: { scale: 0.95 }
|
||||||
|
}
|
||||||
|
|
||||||
|
const rippleVariants = {
|
||||||
|
initial: { scale: 0, opacity: 0.8 },
|
||||||
|
animate: {
|
||||||
|
scale: 4,
|
||||||
|
opacity: 0,
|
||||||
|
transition: { duration: 0.6, ease: "easeOut" as const }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!animated) {
|
||||||
|
return (
|
||||||
|
<button className={classes} {...props}>
|
||||||
|
{children}
|
||||||
|
</button>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button className={classes} {...props}>
|
<motion.button
|
||||||
{children}
|
className={classes}
|
||||||
</button>
|
variants={buttonVariants}
|
||||||
|
whileHover="hover"
|
||||||
|
whileTap="tap"
|
||||||
|
{...(props as any)}
|
||||||
|
>
|
||||||
|
{/* Ripple effect */}
|
||||||
|
<motion.span
|
||||||
|
className="absolute inset-0 bg-white rounded-lg"
|
||||||
|
initial="initial"
|
||||||
|
whileTap="animate"
|
||||||
|
variants={rippleVariants}
|
||||||
|
style={{ mixBlendMode: variant === 'primary' ? 'overlay' : 'multiply' }}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{/* Gradient overlay for primary variant */}
|
||||||
|
{variant === 'primary' && (
|
||||||
|
<motion.div
|
||||||
|
className="absolute inset-0 bg-gradient-to-r from-primary-500 via-primary-600 to-primary-700 rounded-lg"
|
||||||
|
animate={{
|
||||||
|
x: ["-100%", "100%"]
|
||||||
|
}}
|
||||||
|
transition={{
|
||||||
|
duration: 3,
|
||||||
|
repeat: Infinity,
|
||||||
|
ease: "linear" as const,
|
||||||
|
repeatDelay: 2
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<span className="relative z-10">{children}</span>
|
||||||
|
</motion.button>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user