From 8c2111702baa2c8d6b11318faf576cf56d5df3fc Mon Sep 17 00:00:00 2001 From: Cesar Mendivil Date: Tue, 16 Sep 2025 02:20:08 -0700 Subject: [PATCH] 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. --- README.md | 2 +- package-lock.json | 49 ++++++ package.json | 1 + src/components/Features.tsx | 239 ++++++++++++++++++++++++++--- src/components/Footer.tsx | 250 +++++++++++++++++++++++------- src/components/Header.tsx | 147 +++++++++++++----- src/components/Hero.tsx | 288 +++++++++++++++++++++++++++++------ src/components/ui/Button.tsx | 70 ++++++++- 8 files changed, 868 insertions(+), 178 deletions(-) diff --git a/README.md b/README.md index 76ae9d0..6090ca4 100644 --- a/README.md +++ b/README.md @@ -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. diff --git a/package-lock.json b/package-lock.json index 7f0d681..bf4e15f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "dependencies": { "autoprefixer": "^10.4.21", "clsx": "^2.1.1", + "framer-motion": "^12.23.12", "lucide-react": "^0.535.0", "npx": "^10.2.2", "postcss": "^8.5.6", @@ -2635,6 +2636,33 @@ "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": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -3368,6 +3396,21 @@ "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": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -8902,6 +8945,12 @@ "dev": true, "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": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", diff --git a/package.json b/package.json index 05a245a..4682911 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "dependencies": { "autoprefixer": "^10.4.21", "clsx": "^2.1.1", + "framer-motion": "^12.23.12", "lucide-react": "^0.535.0", "npx": "^10.2.2", "postcss": "^8.5.6", diff --git a/src/components/Features.tsx b/src/components/Features.tsx index 4b855d9..508f37f 100644 --- a/src/components/Features.tsx +++ b/src/components/Features.tsx @@ -1,25 +1,126 @@ import React from 'react' import { Zap, Shield, Smartphone, Code, Palette, Users } from 'lucide-react' +import { motion, useInView, useAnimation } from 'framer-motion' interface FeatureCardProps { icon: React.ReactNode title: string description: string + index: number } -const FeatureCard: React.FC = ({ icon, title, description }) => { +const FeatureCard: React.FC = ({ 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 ( -
-
- {icon} -
-

{title}

-

{description}

-
+ + + + {icon} + + + + + {title} + + + + {description} + + + {/* Hover effect overlay */} + + ) } 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 = [ { icon: , @@ -54,41 +155,129 @@ const Features: React.FC = () => { ] return ( -
+
{/* Section Header */} -
-
+ + ✨ Features -
-

+ + + Everything you need to - build amazing UIs -

-

+ build amazing UIs + + + Our comprehensive UI kit provides all the components and tools you need to create beautiful, accessible, and performant user interfaces. -

-
+ + {/* Features Grid */}
{features.map((feature, index) => ( ))}
- {/* Bottom CTA */} -
- -
+ {/* Bottom CTA with sophisticated animation */} + + + {/* Animated background gradient */} + + Explore All Components + + + + {/* Background animated elements */} + +
) diff --git a/src/components/Footer.tsx b/src/components/Footer.tsx index 321eb91..f1b26f7 100644 --- a/src/components/Footer.tsx +++ b/src/components/Footer.tsx @@ -1,95 +1,229 @@ import React from 'react' import { Github, Twitter, Linkedin, Mail } from 'lucide-react' +import { motion, useInView } from 'framer-motion' 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 ( -
+
{/* Main Footer Content */} -
+
{/* Brand Section */} -
-

Inteliq

-

+ + + Inteliq + + Modern UI components for React applications. Build beautiful interfaces faster with our comprehensive kit. -

+
- - - - - - - - - - - - + {socialIcons.map(({ Icon, href, color }, index) => ( + + + + ))}
-
+ {/* Product Links */} -
-

Product

+ + + Product + -
+ {/* Resources Links */} -
-

Resources

+ + + Resources + -
+ {/* Company Links */} -
-

Company

+ + + Company + -
+
-
+ {/* Bottom Bar */} -
+
-

+ © 2025 Inteliq UI Kit. All rights reserved. -

+
- - Privacy Policy - - - Terms of Service - - - Cookie Policy - + {['Privacy Policy', 'Terms of Service', 'Cookie Policy'].map((item, index) => ( + + {item} + + ))}
-
+
-
+ ) } diff --git a/src/components/Header.tsx b/src/components/Header.tsx index 8b52898..8bc6558 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -1,76 +1,139 @@ import React from 'react' import { Menu, X } from 'lucide-react' +import { motion, AnimatePresence } from 'framer-motion' const Header: React.FC = () => { const [isMenuOpen, setIsMenuOpen] = React.useState(false) return ( -
+
{/* Logo */} -
+

Inteliq

-
+ {/* Desktop Navigation */} {/* CTA Button */}
- +
{/* Mobile menu button */}
- + + {isMenuOpen ? ( + + + + ) : ( + + + + )} + +
{/* Mobile Navigation */} - {isMenuOpen && ( - - )} + + {isMenuOpen && ( + +
+ {['Home', 'Features', 'About', 'Contact'].map((item, index) => ( + + {item} + + ))} + + Get Started + +
+
+ )} +
-
+ ) } diff --git a/src/components/Hero.tsx b/src/components/Hero.tsx index f8c9879..7bcf03b 100644 --- a/src/components/Hero.tsx +++ b/src/components/Hero.tsx @@ -1,80 +1,272 @@ import React from 'react' import { ArrowRight, Play } from 'lucide-react' +import { motion, useInView } from 'framer-motion' 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 ( -
+
-
+ {/* Left Content */}
-
+ 🚀 New Update Available -
-

+ + + Build Amazing - UI Components -

-

+ UI Components + + + Create stunning user interfaces with our comprehensive UI kit. Designed for modern web applications with React and TypeScript. -

+
{/* CTA Buttons */} -
- - -
+ + {/* Stats */} -
-
-
50+
-
Components
-
-
-
10k+
-
Downloads
-
-
-
99%
-
Satisfaction
-
-
+ + {[ + { number: "50+", label: "Components" }, + { number: "10k+", label: "Downloads" }, + { number: "99%", label: "Satisfaction" } + ].map((stat, index) => ( + + + {stat.number} + +
{stat.label}
+
+ ))} +
- {/* Right Content - Placeholder for design */} -
-
-
+ {/* Right Content - Animated design placeholder */} + + +
-
-
-
+ {[1, 0.8, 0.6].map((width, index) => ( + + ))}
-
-
+ +
-
-
+ {[1, 0.75].map((width, index) => ( + + ))}
-
+ - {/* Floating elements */} -
-
-
-
+ {/* Floating elements with sophisticated animations */} + + + + +
) diff --git a/src/components/ui/Button.tsx b/src/components/ui/Button.tsx index a882d60..11bc87e 100644 --- a/src/components/ui/Button.tsx +++ b/src/components/ui/Button.tsx @@ -1,10 +1,12 @@ import React from 'react' import { clsx } from 'clsx' +import { motion } from 'framer-motion' interface ButtonProps extends React.ButtonHTMLAttributes { variant?: 'primary' | 'secondary' | 'outline' | 'ghost' size?: 'sm' | 'md' | 'lg' children: React.ReactNode + animated?: boolean } const Button: React.FC = ({ @@ -12,9 +14,10 @@ const Button: React.FC = ({ size = 'md', className, children, + animated = true, ...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 = { primary: 'bg-primary-600 text-white hover:bg-primary-700 focus:ring-primary-500', @@ -35,11 +38,70 @@ const Button: React.FC = ({ sizes[size], 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 ( + + ) + } return ( - + + {/* Ripple effect */} + + + {/* Gradient overlay for primary variant */} + {variant === 'primary' && ( + + )} + + {children} + ) }