HeroCarousel.tsx 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. import { useState, useEffect } from 'react';
  2. import { ChevronLeft, ChevronRight } from 'lucide-react';
  3. import { carouselData } from '@/data/mockData';
  4. export function HeroCarousel() {
  5. const [currentIndex, setCurrentIndex] = useState(0);
  6. const [isHovering, setIsHovering] = useState(false);
  7. useEffect(() => {
  8. if (isHovering) return;
  9. const interval = setInterval(() => {
  10. setCurrentIndex((prev) => (prev + 1) % carouselData.length);
  11. }, 5000);
  12. return () => clearInterval(interval);
  13. }, [isHovering]);
  14. const goToSlide = (index: number) => {
  15. setCurrentIndex(index);
  16. };
  17. const prevSlide = () => {
  18. setCurrentIndex((prev) => (prev - 1 + carouselData.length) % carouselData.length);
  19. };
  20. const nextSlide = () => {
  21. setCurrentIndex((prev) => (prev + 1) % carouselData.length);
  22. };
  23. return (
  24. <div
  25. className="relative w-full overflow-hidden"
  26. style={{ height: '85vh', minHeight: '600px' }}
  27. onMouseEnter={() => setIsHovering(true)}
  28. onMouseLeave={() => setIsHovering(false)}
  29. >
  30. <div className="absolute inset-0 overflow-hidden">
  31. {carouselData.map((slide, index) => (
  32. <div
  33. key={slide.id}
  34. className={`absolute inset-0 bg-gradient-to-br ${slide.bgGradient} transition-opacity duration-1000 ${
  35. index === currentIndex ? 'opacity-100 z-10' : 'opacity-0 z-0'
  36. }`}
  37. >
  38. <div className="absolute inset-0 bg-[url('data:image/svg+xml,%3Csvg%20width%3D%2260%22%20height%3D%2260%22%20viewBox%3D%220%200%2060%2060%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Cg%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%3Cg%20fill%3D%22%23ffffff%22%20fill-opacity%3D%220.03%22%3E%3Cpath%20d%3D%22M36%2034v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zm0-30V0h-2v4h-4v2h4v4h2V6h4V4h-4zM6%2034v-4H4v4H0v2h4v4h2v-4h4v-2H6zM6%204V0H4v4H0v2h4v4h2V6h4V4H6z%22%2F%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E')] opacity-50" />
  39. <div className="absolute top-1/4 left-1/4 w-96 h-96 bg-glow-green/10 rounded-full blur-3xl animate-pulse" />
  40. <div className="absolute bottom-1/4 right-1/4 w-96 h-96 bg-tech-cyan-500/10 rounded-full blur-3xl animate-pulse" style={{ animationDelay: '1s' }} />
  41. <div className="absolute inset-0">
  42. {[...Array(30)].map((_, i) => (
  43. <div
  44. key={i}
  45. className="absolute w-1 h-1 bg-glow-green/30 rounded-full animate-float"
  46. style={{
  47. left: `${Math.random() * 100}%`,
  48. top: `${Math.random() * 100}%`,
  49. animationDelay: `${Math.random() * 5}s`,
  50. animationDuration: `${5 + Math.random() * 5}s`,
  51. }}
  52. />
  53. ))}
  54. </div>
  55. </div>
  56. ))}
  57. </div>
  58. <div className="relative z-20 h-full flex flex-col items-center justify-center px-4">
  59. <div className="text-center">
  60. <h1 className="text-3xl md:text-4xl lg:text-5xl font-bold text-white mb-6 leading-tight transition-all duration-1000">
  61. {carouselData[currentIndex].title}
  62. </h1>
  63. <p className="text-base md:text-lg lg:text-xl text-white/90 mb-6 max-w-4xl mx-auto leading-relaxed transition-all duration-1000">
  64. {carouselData[currentIndex].subtitle}
  65. </p>
  66. <p className="text-sm md:text-base lg:text-lg text-white/70 max-w-2xl mx-auto transition-all duration-1000">
  67. {carouselData[currentIndex].testimonial}
  68. </p>
  69. </div>
  70. </div>
  71. <button
  72. onClick={prevSlide}
  73. className="absolute left-4 md:left-8 top-1/2 -translate-y-1/2 z-30 w-12 h-12 bg-white/10 backdrop-blur-sm rounded-full flex items-center justify-center text-white hover:bg-white/20 transition-all"
  74. >
  75. <ChevronLeft className="w-6 h-6" />
  76. </button>
  77. <button
  78. onClick={nextSlide}
  79. className="absolute right-4 md:right-8 top-1/2 -translate-y-1/2 z-30 w-12 h-12 bg-white/10 backdrop-blur-sm rounded-full flex items-center justify-center text-white hover:bg-white/20 transition-all"
  80. >
  81. <ChevronRight className="w-6 h-6" />
  82. </button>
  83. <div className="absolute bottom-12 left-1/2 -translate-x-1/2 z-30 flex gap-3">
  84. {carouselData.map((_, index) => (
  85. <button
  86. key={index}
  87. onClick={() => goToSlide(index)}
  88. className={`w-3 h-3 rounded-full transition-all ${
  89. index === currentIndex ? 'bg-glow-green w-8' : 'bg-white/30 hover:bg-white/50'
  90. }`}
  91. />
  92. ))}
  93. </div>
  94. </div>
  95. );
  96. }