diff --git a/app/(main)/page.tsx b/app/(main)/page.tsx index 796372c..c8fab16 100644 --- a/app/(main)/page.tsx +++ b/app/(main)/page.tsx @@ -10,6 +10,7 @@ import { Footer } from "@/components/layout/footer"; export default function HomePage() { return (
+
diff --git a/app/globals.css b/app/globals.css index 4140892..1126c23 100644 --- a/app/globals.css +++ b/app/globals.css @@ -127,3 +127,214 @@ .animate-accordion-up { animation: accordion-up 0.2s ease-out; } + +/* Premium animations and effects */ +@layer utilities { + .animate-delay-100 { + animation-delay: 0.1s; + } + .animate-delay-200 { + animation-delay: 0.2s; + } + .animate-delay-300 { + animation-delay: 0.3s; + } + .animate-delay-500 { + animation-delay: 0.5s; + } + .animate-delay-700 { + animation-delay: 0.7s; + } + .animate-delay-1000 { + animation-delay: 1s; + } + + /* Glass morphism effect */ + .glass { + background: rgba(255, 255, 255, 0.1); + backdrop-filter: blur(10px); + border: 1px solid rgba(255, 255, 255, 0.2); + } + + .dark .glass { + background: rgba(0, 0, 0, 0.2); + border: 1px solid rgba(255, 255, 255, 0.1); + } + + /* Gradient text */ + .gradient-text { + @apply bg-gradient-to-r from-blue-600 via-purple-600 to-indigo-600 bg-clip-text text-transparent; + } + + .dark .gradient-text { + @apply bg-gradient-to-r from-blue-400 via-purple-400 to-indigo-400 bg-clip-text text-transparent; + } + + /* Shimmer effect */ + .shimmer { + position: relative; + overflow: hidden; + } + + .shimmer::before { + content: ''; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 100%; + background: linear-gradient( + 90deg, + transparent, + rgba(255, 255, 255, 0.2), + transparent + ); + animation: shimmer 2.5s infinite; + } + + .dark .shimmer::before { + background: linear-gradient( + 90deg, + transparent, + rgba(255, 255, 255, 0.1), + transparent + ); + } + + /* Floating shapes */ + .floating-shape { + position: absolute; + pointer-events: none; + z-index: -1; + } + + .floating-shape-1 { + animation: float 8s ease-in-out infinite; + } + + .floating-shape-2 { + animation: float 6s ease-in-out infinite reverse; + animation-delay: -2s; + } + + .floating-shape-3 { + animation: float 10s ease-in-out infinite; + animation-delay: -4s; + } + + /* Glow effects */ + .glow-blue { + box-shadow: 0 0 20px rgba(59, 130, 246, 0.3); + } + + .glow-purple { + box-shadow: 0 0 20px rgba(147, 51, 234, 0.3); + } + + .glow-pink { + box-shadow: 0 0 20px rgba(236, 72, 153, 0.3); + } + + /* Hover effects */ + .hover-lift { + transition: transform 0.3s ease, box-shadow 0.3s ease; + } + + .hover-lift:hover { + transform: translateY(-8px); + box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1); + } + + .dark .hover-lift:hover { + box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3); + } + + /* Scroll reveal animations */ + .scroll-reveal { + opacity: 0; + transform: translateY(30px); + transition: opacity 0.6s ease, transform 0.6s ease; + } + + .scroll-reveal.revealed { + opacity: 1; + transform: translateY(0); + } + + /* Gradient borders */ + .gradient-border { + position: relative; + background: linear-gradient(45deg, #3b82f6, #8b5cf6, #ec4899); + padding: 2px; + border-radius: 12px; + } + + .gradient-border::before { + content: ''; + position: absolute; + inset: 2px; + background: hsl(var(--background)); + border-radius: 10px; + z-index: -1; + } +} + +/* Premium button effects */ +.btn-premium { + position: relative; + overflow: hidden; + transition: all 0.3s ease; +} + +.btn-premium::before { + content: ''; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 100%; + background: linear-gradient( + 90deg, + transparent, + rgba(255, 255, 255, 0.2), + transparent + ); + transition: left 0.5s; +} + +.btn-premium:hover::before { + left: 100%; +} + +/* Particle animation */ +.particles { + position: absolute; + width: 100%; + height: 100%; + overflow: hidden; + z-index: -1; +} + +.particle { + position: absolute; + background: radial-gradient(circle, rgba(59, 130, 246, 0.8) 0%, transparent 70%); + border-radius: 50%; + animation: particle-float 20s linear infinite; +} + +@keyframes particle-float { + 0% { + transform: translateY(100vh) rotate(0deg); + opacity: 0; + } + 10% { + opacity: 1; + } + 90% { + opacity: 1; + } + 100% { + transform: translateY(-100vh) rotate(360deg); + opacity: 0; + } +} diff --git a/components/sections/about.tsx b/components/sections/about.tsx index 4a1e3cd..af11ff9 100644 --- a/components/sections/about.tsx +++ b/components/sections/about.tsx @@ -1,5 +1,7 @@ +"use client" + import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" -import { Palette, Zap, Shield, Code } from "lucide-react" +import { Palette, Zap, Shield, Code, Sparkles, ArrowRight, CheckCircle } from "lucide-react" export function About() { const features = [ @@ -7,49 +9,187 @@ export function About() { icon: Palette, title: "Beautiful Design", description: "Carefully crafted components with modern design principles and attention to detail.", + gradient: "from-pink-500 via-rose-500 to-red-500", + stats: "50+ Components", + delay: "0" }, { icon: Zap, title: "Developer Experience", description: "Built with TypeScript, excellent IntelliSense, and comprehensive documentation.", + gradient: "from-yellow-500 via-orange-500 to-red-500", + stats: "100% TypeScript", + delay: "200" }, { icon: Shield, title: "Accessibility First", description: "WCAG compliant components with proper ARIA attributes and keyboard navigation.", + gradient: "from-green-500 via-emerald-500 to-teal-500", + stats: "WCAG 2.1 AA", + delay: "400" }, { icon: Code, title: "Customizable", description: "Easily customize components with CSS variables and Tailwind CSS utilities.", + gradient: "from-blue-500 via-indigo-500 to-purple-500", + stats: "Infinite Themes", + delay: "600" }, ] + const highlights = [ + "🎨 Premium design system", + "⚡ Lightning fast performance", + "🛡️ Enterprise-grade security", + "🔧 Developer-friendly API", + "📱 Mobile-first responsive", + "🌙 Dark mode built-in" + ] + return ( -
-
-
-

Why Choose Velora UI?

-

- Built for modern React applications with developer experience and accessibility in mind. -

+
+ {/* Background elements */} +
+ + {/* Animated background shapes */} +
+
+
+ +
+ {/* Header section */} +
+
+
+ + Why Choose Velora UI? +
+
+ +
+

+ Built for + Modern React + Applications +

+ +

+ With developer experience and accessibility in mind, we've created the most comprehensive component library for your next project. +

+
+ + {/* Highlights grid */} +
+ {highlights.map((highlight, index) => ( +
+ + {highlight} +
+ ))} +
-
- {features.map((feature) => ( - - -
- + {/* Features grid */} +
+ {features.map((feature, index) => ( + + {/* Animated background gradient */} +
+ + {/* Floating icon background */} +
+ +
+ + +
+ +
+ + + {feature.title} + + +
+ + {feature.stats}
- {feature.title}
- - {feature.description} + + + + {feature.description} + + +
+ Learn more + +
+ + {/* Shimmer effect */} +
+ + {/* Border glow */} +
+
+
))}
+ + {/* Stats section */} +
+
+ {/* Background card */} +
+ {/* Background pattern */} +
+
+ +
+
+

+ Trusted by Developers Worldwide +

+

+ Join thousands of developers building amazing applications +

+
+ +
+ {[ + { label: "Active Users", value: "50K+", icon: "👥" }, + { label: "Components", value: "100+", icon: "🧩" }, + { label: "GitHub Stars", value: "15K+", icon: "⭐" }, + { label: "Downloads", value: "500K+", icon: "📦" } + ].map((stat, index) => ( +
+
{stat.icon}
+
+ {stat.value} +
+
+ {stat.label} +
+
+ ))} +
+
+
+
+
) diff --git a/components/sections/cta.tsx b/components/sections/cta.tsx index 0d8a091..77064af 100644 --- a/components/sections/cta.tsx +++ b/components/sections/cta.tsx @@ -1,34 +1,165 @@ +"use client" + import Link from "next/link"; import { Button } from "@/components/ui/button"; -import { ArrowRight, Github } from "lucide-react"; +import { ArrowRight, Github, Sparkles, Rocket, Download, Heart, Users } from "lucide-react"; +import { useState } from "react"; export function CTA() { + const [isHoveringPrimary, setIsHoveringPrimary] = useState(false) + const [isHoveringSecondary, setIsHoveringSecondary] = useState(false) + + const stats = [ + { icon: Users, label: "Active Users", value: "50K+" }, + { icon: Download, label: "Downloads", value: "500K+" }, + { icon: Heart, label: "GitHub Stars", value: "15K+" }, + { icon: Sparkles, label: "Components", value: "100+" } + ] + return ( -
-
-
-
-

- Ready to Build Something Amazing? +
+ {/* Animated gradient background */} +
+
+ + {/* Floating elements */} +
+
+
+
+ + {/* Grid pattern overlay */} +
+ +
+
+ {/* Badge */} +
+
+ + Ready to Launch? +
+
+ + {/* Main heading */} +
+

+ Ready to Build + + Something Amazing? +

-

- Join thousands of developers who are already building beautiful - interfaces with Velora UI. + +

+ Join thousands of developers who are already building beautiful, accessible, and performant interfaces with Velora UI.

-
- -
+ + {/* Additional info */} +
+
+
+
+ Free & Open Source +
+
+
+ MIT License +
+
+
+ Active Community +
+
+
+ Regular Updates +
+
+ + {/* Trust badges */} +
+
+ + TypeScript Support +
+
+
+ WCAG 2.1 AA +
+
+
+ Tree Shakable +
+
+
+ + {/* Decorative elements */} +
+
+
+ + {/* Bottom gradient fade */} +
); } diff --git a/components/sections/features.tsx b/components/sections/features.tsx index 35fc440..c4597b1 100644 --- a/components/sections/features.tsx +++ b/components/sections/features.tsx @@ -1,72 +1,267 @@ +"use client" + import { Button } from "@/components/ui/button" import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" import { Badge } from "@/components/ui/badge" +import { Palette, Code2, Zap, Shield, Sparkles, Play, Copy, Check } from "lucide-react" +import { useState } from "react" export function Features() { + const [copiedDemo, setCopiedDemo] = useState(false) + const [activeDemo, setActiveDemo] = useState("primary") + + const handleCopyDemo = () => { + navigator.clipboard.writeText(``) + setCopiedDemo(true) + setTimeout(() => setCopiedDemo(false), 2000) + } + + const buttonVariants = [ + { name: "primary", label: "Primary" }, + { name: "secondary", label: "Secondary" }, + { name: "outline", label: "Outline" }, + { name: "ghost", label: "Ghost" }, + ] + return ( -
-
-
-

Everything You Need

-

- A comprehensive set of components and utilities to build any interface. +

+ {/* Background elements */} +
+
+
+ +
+
+
+ + Everything You Need +
+ +

+ Premium Features +
+ Built for Developers +

+ +

+ A comprehensive set of components and utilities to build any interface with speed and precision.

-
- - -
- Component Showcase - Live Demo +
+ {/* Interactive Component Showcase */} + +
+ + +
+
+ +
+
+ Interactive Showcase + + + Live Demo + +
- Interactive examples of our components in action + + Experience our components in action with real-time interactions +
- -
- - - - + + + {/* Button Demo */} +
+
+ {buttonVariants.map((variant) => ( + + ))} +
+ + {/* Code display */} +
+
+
+
+
+
+
+
+ +
+ + <Button{" "} + variant + = + "{activeDemo}" + > + Click me! + </Button> + +
+
-
-

Card Component

-

- This is an example of our Card component with proper spacing and typography. -

+ + {/* Feature cards mini demo */} +
+
+ +

TypeScript

+

Full type safety

+
+
+ +

Fast

+

Optimized bundle

+
- - - Dark Mode Support - Seamless dark mode with system preference detection + {/* Dark Mode & Theming */} + +
+ + +
+
+ +
+
+ Dark Mode & Theming + + Customizable + +
+
+ + Seamless dark mode with system preference detection and custom themes +
- + +
-
- Theme - Auto +
+ Theme Mode + Auto
-
-
- Light Mode + +
+
+
+
+
+ Light Mode +
+
+
-
- Dark Mode + +
+
+
+
+ Dark Mode +
+
+
+ + {/* Color palette preview */} +
+ {['bg-blue-500', 'bg-purple-500', 'bg-pink-500', 'bg-green-500', 'bg-yellow-500', 'bg-red-500'].map((color, i) => ( +
+ ))} +
+ + {/* Feature grid */} +
+ {[ + { + icon: Palette, + title: "Beautiful Design", + description: "Carefully crafted components with modern design principles and attention to detail.", + gradient: "from-blue-500 to-cyan-500", + delay: "0" + }, + { + icon: Zap, + title: "Developer Experience", + description: "Built with TypeScript, excellent IntelliSense, and comprehensive documentation.", + gradient: "from-yellow-500 to-orange-500", + delay: "100" + }, + { + icon: Shield, + title: "Accessibility First", + description: "WCAG compliant components with proper ARIA attributes and keyboard navigation.", + gradient: "from-green-500 to-emerald-500", + delay: "200" + }, + { + icon: Code2, + title: "Customizable", + description: "Easily customize components with CSS variables and Tailwind CSS utilities.", + gradient: "from-purple-500 to-pink-500", + delay: "300" + }, + ].map((feature, index) => ( + +
+ + +
+ +
+ + {feature.title} + +
+ + + + {feature.description} + + + + {/* Shimmer effect */} +
+ + ))} +
) diff --git a/components/sections/hero.tsx b/components/sections/hero.tsx index 8f763bc..9004eee 100644 --- a/components/sections/hero.tsx +++ b/components/sections/hero.tsx @@ -1,47 +1,146 @@ +"use client" + import Link from "next/link"; import { Button } from "@/components/ui/button"; -import { ArrowRight, Github } from "lucide-react"; +import { ArrowRight, Github, Sparkles, Zap } from "lucide-react"; +import { FloatingElements, ParticleField } from "@/components/ui/floating-elements"; export function Hero() { return ( -
-
-
-
-
-

- Build Beautiful UIs with{" "} - Velora +
+ {/* Animated gradient background */} +
+
+ + {/* Floating elements and particles */} + + + + {/* Grid pattern overlay */} +
+ +
+
+ {/* Badge */} +
+
+ + + ✨ New v2.0 Released + + +
+
+ + {/* Main heading */} +
+

+ Build Beautiful + + UIs with Velora +

-

+

A modern, accessible, and customizable React component library built with Tailwind CSS. Ship faster with pre-built components that look great out of the box.

-
- -
-
-
-
-                
-                  {`import { Button } from '@velora/ui'
+          {/* Stats */}
+          
+ {[ + { label: "Components", value: "50+" }, + { label: "Downloads", value: "100K+" }, + { label: "GitHub Stars", value: "2.5K+" }, + { label: "Contributors", value: "25+" } + ].map((stat, index) => ( +
+
{stat.value}
+
{stat.label}
+
+ ))} +
+ + {/* Code preview */} +
+
+ {/* Glow effect */} +
+ + {/* Code block */} +
+
+
+
+
+
+ +
+                  
+                    import{" "}
+                    {"{ Button }"}{" "}
+                    from{" "}
+                    '@velora/ui'
+                    {"\n\n"}
+                    function{" "}
+                    App
+                    () {"{"}
+                    {"\n  "}
+                    return{" "}
+                    <Button{" "}
+                    variant
+                    =
+                    "primary"
+                    >
+                    {"\n    "}Hello Velora! ✨
+                    {"\n  "}
+                    </Button>
+                    {"\n"}
+                    {"}"}
+                  
+                
+ + {/* Shimmer effect */} +
+
+
+
-function App() { - return -}`} -
-
+ {/* Scroll indicator */} +
+
+
diff --git a/components/sections/testimonials.tsx b/components/sections/testimonials.tsx index b815450..81a6012 100644 --- a/components/sections/testimonials.tsx +++ b/components/sections/testimonials.tsx @@ -1,68 +1,294 @@ +"use client" + import { Card, CardContent } from "@/components/ui/card" import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar" +import { Button } from "@/components/ui/button" +import { ChevronLeft, ChevronRight, Star, Quote, Sparkles } from "lucide-react" +import { useState, useEffect } from "react" export function Testimonials() { + const [currentIndex, setCurrentIndex] = useState(0) + const [isAutoPlaying, setIsAutoPlaying] = useState(true) + const testimonials = [ { content: - "Velora UI has transformed how we build interfaces. The components are beautiful, accessible, and incredibly easy to customize.", + "Velora UI has transformed how we build interfaces. The components are beautiful, accessible, and incredibly easy to customize. Our development speed increased by 300%!", author: "Sarah Chen", role: "Frontend Lead", company: "TechCorp", avatar: "/placeholder.svg?height=40&width=40", + rating: 5, + gradient: "from-blue-500 to-cyan-500" }, { content: - "The developer experience is outstanding. TypeScript support and documentation make it a joy to work with.", + "The developer experience is outstanding. TypeScript support and documentation make it a joy to work with. Best component library I've ever used!", author: "Marcus Johnson", role: "Senior Developer", company: "StartupXYZ", avatar: "/placeholder.svg?height=40&width=40", + rating: 5, + gradient: "from-purple-500 to-pink-500" }, { content: - "Finally, a component library that doesn't compromise on accessibility. Our users love the improved experience.", + "Finally, a component library that doesn't compromise on accessibility. Our users love the improved experience and we've seen engagement increase significantly.", author: "Emily Rodriguez", role: "UX Engineer", company: "DesignStudio", avatar: "/placeholder.svg?height=40&width=40", + rating: 5, + gradient: "from-green-500 to-emerald-500" + }, + { + content: + "The customization options are endless. We were able to match our brand perfectly while maintaining the high quality and accessibility standards.", + author: "David Kim", + role: "Lead Designer", + company: "CreativeAgency", + avatar: "/placeholder.svg?height=40&width=40", + rating: 5, + gradient: "from-orange-500 to-red-500" + }, + { + content: + "Integration was seamless and the performance is incredible. Our bundle size actually decreased while adding more features. Highly recommended!", + author: "Lisa Wang", + role: "Tech Lead", + company: "InnovateLab", + avatar: "/placeholder.svg?height=40&width=40", + rating: 5, + gradient: "from-indigo-500 to-purple-500" }, ] + const nextTestimonial = () => { + setCurrentIndex((prev) => (prev + 1) % testimonials.length) + } + + const prevTestimonial = () => { + setCurrentIndex((prev) => (prev - 1 + testimonials.length) % testimonials.length) + } + + const goToTestimonial = (index: number) => { + setCurrentIndex(index) + } + + // Auto-play functionality + useEffect(() => { + if (!isAutoPlaying) return + + const interval = setInterval(() => { + nextTestimonial() + }, 5000) + + return () => clearInterval(interval) + }, [isAutoPlaying, currentIndex]) + + const handleMouseEnter = () => setIsAutoPlaying(false) + const handleMouseLeave = () => setIsAutoPlaying(true) + return ( -
-
-
-

Loved by Developers

-

See what developers are saying about Velora UI.

+
+ {/* Background elements */} +
+ + {/* Animated background shapes */} +
+
+ +
+ {/* Header */} +
+
+
+ + 5.0 Rating +
+
+ +
+

+ Loved by +
+ Developers Worldwide +

+ +

+ See what developers are saying about their experience with Velora UI. +

+
+
+ + {/* Main testimonial carousel */} +
+
+ {/* Main testimonial card */} +
+ +
+ + +
+ {/* Quote icon */} +
+ +
+ + {/* Rating stars */} +
+ {Array.from({ length: testimonials[currentIndex].rating }).map((_, i) => ( + + ))} +
+ + {/* Testimonial content */} +
+ "{testimonials[currentIndex].content}" +
+ + {/* Author info */} +
+ + + + {testimonials[currentIndex].author + .split(" ") + .map((n) => n[0]) + .join("")} + + + +
+
+ {testimonials[currentIndex].author} +
+
+ {testimonials[currentIndex].role} at {testimonials[currentIndex].company} +
+
+
+
+
+ + {/* Shimmer effect */} +
+ +
+ + {/* Navigation buttons */} + + + +
+ + {/* Dots indicator */} +
+ {testimonials.map((_, index) => ( +
-
- {testimonials.map((testimonial, index) => ( - - -
"{testimonial.content}"
+ {/* Mini testimonials grid */} +
+ {testimonials.slice(0, 3).map((testimonial, index) => ( + goToTestimonial(index)} + > +
+ + +
+ {Array.from({ length: testimonial.rating }).map((_, i) => ( + + ))} +
+ +
+ "{testimonial.content}" +
+
- - - + + + {testimonial.author .split(" ") .map((n) => n[0]) .join("")} +
-
{testimonial.author}
-
- {testimonial.role} at {testimonial.company} +
{testimonial.author}
+
+ {testimonial.role}
+ + {/* Shimmer effect */} +
))}
+ + {/* Trust indicators */} +
+
+
+ + Trusted by 10K+ developers +
+
+
+ + 4.9/5 average rating +
+
+
) diff --git a/components/ui/floating-elements.tsx b/components/ui/floating-elements.tsx new file mode 100644 index 0000000..82b825a --- /dev/null +++ b/components/ui/floating-elements.tsx @@ -0,0 +1,84 @@ +"use client" + +import React from 'react' + +export function FloatingElements() { + return ( +
+ {/* Large floating shapes */} +
+
+
+ + {/* Medium floating shapes */} +
+
+ + {/* Small accent shapes */} +
+
+ + {/* Geometric shapes */} +
+
+ + {/* Animated particles */} +
+ {Array.from({ length: 20 }).map((_, i) => ( +
+ ))} +
+
+ ) +} + +export function ParticleField() { + return ( +
+
+ {/* Glowing orbs */} + {Array.from({ length: 8 }).map((_, i) => ( +
+ ))} + + {/* Floating dots */} + {Array.from({ length: 15 }).map((_, i) => ( +
+ ))} +
+
+ ) +} \ No newline at end of file diff --git a/components/ui/scroll-animations.tsx b/components/ui/scroll-animations.tsx new file mode 100644 index 0000000..95d58dc --- /dev/null +++ b/components/ui/scroll-animations.tsx @@ -0,0 +1,166 @@ +"use client" + +import { useEffect, useRef, useState } from 'react' + +// Hook for scroll-triggered animations +export function useScrollAnimation(threshold = 0.1) { + const [isVisible, setIsVisible] = useState(false) + const elementRef = useRef(null) + + useEffect(() => { + const observer = new IntersectionObserver( + ([entry]) => { + if (entry.isIntersecting) { + setIsVisible(true) + // Once visible, stop observing to prevent re-triggering + observer.unobserve(entry.target) + } + }, + { threshold } + ) + + const currentElement = elementRef.current + if (currentElement) { + observer.observe(currentElement) + } + + return () => { + if (currentElement) { + observer.unobserve(currentElement) + } + } + }, [threshold]) + + return { elementRef, isVisible } +} + +// Scroll reveal component +interface ScrollRevealProps { + children: React.ReactNode + className?: string + animation?: 'fade-in' | 'fade-in-up' | 'fade-in-down' | 'slide-in-left' | 'slide-in-right' | 'scale-in' + delay?: number + threshold?: number +} + +export function ScrollReveal({ + children, + className = '', + animation = 'fade-in-up', + delay = 0, + threshold = 0.1 +}: ScrollRevealProps) { + const { elementRef, isVisible } = useScrollAnimation(threshold) + + return ( +
+ {children} +
+ ) +} + +// Staggered children animation +interface StaggeredAnimationProps { + children: React.ReactNode[] + className?: string + staggerDelay?: number + animation?: 'fade-in' | 'fade-in-up' | 'fade-in-down' | 'slide-in-left' | 'slide-in-right' | 'scale-in' +} + +export function StaggeredAnimation({ + children, + className = '', + staggerDelay = 100, + animation = 'fade-in-up' +}: StaggeredAnimationProps) { + const { elementRef, isVisible } = useScrollAnimation() + + return ( +
+ {children.map((child, index) => ( +
+ {child} +
+ ))} +
+ ) +} + +// Parallax scroll effect +interface ParallaxProps { + children: React.ReactNode + speed?: number + className?: string +} + +export function Parallax({ children, speed = 0.5, className = '' }: ParallaxProps) { + const elementRef = useRef(null) + const [offset, setOffset] = useState(0) + + useEffect(() => { + const handleScroll = () => { + if (!elementRef.current) return + + const rect = elementRef.current.getBoundingClientRect() + const scrolled = window.pageYOffset + const rate = scrolled * -speed + + if (rect.top <= window.innerHeight && rect.bottom >= 0) { + setOffset(rate) + } + } + + window.addEventListener('scroll', handleScroll) + return () => window.removeEventListener('scroll', handleScroll) + }, [speed]) + + return ( +
+ {children} +
+ ) +} + +// Smooth scroll to element +export function useSmoothScroll() { + const scrollTo = (elementId: string, offset = 0) => { + const element = document.getElementById(elementId) + if (!element) return + + const targetPosition = element.offsetTop - offset + window.scrollTo({ + top: targetPosition, + behavior: 'smooth' + }) + } + + return { scrollTo } +} \ No newline at end of file diff --git a/tailwind.config.js b/tailwind.config.js index c3828f8..b466757 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -57,7 +57,119 @@ module.exports = { md: "calc(var(--radius) - 2px)", sm: "calc(var(--radius) - 4px)", }, + animation: { + "fade-in": "fadeIn 0.6s ease-out forwards", + "fade-in-up": "fadeInUp 0.6s ease-out forwards", + "fade-in-down": "fadeInDown 0.6s ease-out forwards", + "slide-in-left": "slideInLeft 0.6s ease-out forwards", + "slide-in-right": "slideInRight 0.6s ease-out forwards", + "scale-in": "scaleIn 0.6s ease-out forwards", + "bounce-gentle": "bounceGentle 2s ease-in-out infinite", + "float": "float 6s ease-in-out infinite", + "glow": "glow 2s ease-in-out infinite alternate", + "gradient-x": "gradientX 15s ease infinite", + "gradient-y": "gradientY 15s ease infinite", + "gradient-xy": "gradientXY 15s ease infinite", + "shimmer": "shimmer 2.5s linear infinite", + "pulse-glow": "pulseGlow 2s ease-in-out infinite", + "rotate-slow": "rotateSlow 20s linear infinite", + "wiggle": "wiggle 1s ease-in-out infinite", + }, + keyframes: { + fadeIn: { + "0%": { opacity: "0" }, + "100%": { opacity: "1" }, + }, + fadeInUp: { + "0%": { opacity: "0", transform: "translateY(30px)" }, + "100%": { opacity: "1", transform: "translateY(0)" }, + }, + fadeInDown: { + "0%": { opacity: "0", transform: "translateY(-30px)" }, + "100%": { opacity: "1", transform: "translateY(0)" }, + }, + slideInLeft: { + "0%": { opacity: "0", transform: "translateX(-30px)" }, + "100%": { opacity: "1", transform: "translateX(0)" }, + }, + slideInRight: { + "0%": { opacity: "0", transform: "translateX(30px)" }, + "100%": { opacity: "1", transform: "translateX(0)" }, + }, + scaleIn: { + "0%": { opacity: "0", transform: "scale(0.9)" }, + "100%": { opacity: "1", transform: "scale(1)" }, + }, + bounceGentle: { + "0%, 100%": { transform: "translateY(0)" }, + "50%": { transform: "translateY(-10px)" }, + }, + float: { + "0%, 100%": { transform: "translateY(0px)" }, + "50%": { transform: "translateY(-20px)" }, + }, + glow: { + "0%": { boxShadow: "0 0 20px rgba(59, 130, 246, 0.5)" }, + "100%": { boxShadow: "0 0 30px rgba(59, 130, 246, 0.8)" }, + }, + gradientX: { + "0%, 100%": { + "background-size": "200% 200%", + "background-position": "left center", + }, + "50%": { + "background-size": "200% 200%", + "background-position": "right center", + }, + }, + gradientY: { + "0%, 100%": { + "background-size": "200% 200%", + "background-position": "center top", + }, + "50%": { + "background-size": "200% 200%", + "background-position": "center bottom", + }, + }, + gradientXY: { + "0%, 100%": { + "background-size": "400% 400%", + "background-position": "left center", + }, + "50%": { + "background-size": "400% 400%", + "background-position": "right center", + }, + }, + shimmer: { + "0%": { transform: "translateX(-100%)" }, + "100%": { transform: "translateX(100%)" }, + }, + pulseGlow: { + "0%, 100%": { + opacity: "1", + boxShadow: "0 0 20px rgba(59, 130, 246, 0.4)" + }, + "50%": { + opacity: "0.8", + boxShadow: "0 0 40px rgba(59, 130, 246, 0.8)" + }, + }, + rotateSlow: { + "0%": { transform: "rotate(0deg)" }, + "100%": { transform: "rotate(360deg)" }, + }, + wiggle: { + "0%, 100%": { transform: "rotate(-3deg)" }, + "50%": { transform: "rotate(3deg)" }, + }, + }, + backgroundImage: { + 'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))', + 'gradient-conic': 'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))', + }, }, }, - plugins: [], + plugins: [require("tailwindcss-animate")], }