()
| 12 | } |
| 13 | |
| 14 | const StarWarsButton: React.FC = () => { |
| 15 | const buttonRef = useRef<HTMLButtonElement>(null) |
| 16 | const [stars, setStars] = useState<Star[]>([]) |
| 17 | const controls = useAnimation() |
| 18 | |
| 19 | useEffect(() => { |
| 20 | const generateStars = () => { |
| 21 | if (buttonRef.current) { |
| 22 | const { width, height } = buttonRef.current.getBoundingClientRect() |
| 23 | setStars( |
| 24 | Array.from({ length: 50 }, (_, i) => ({ |
| 25 | id: i, |
| 26 | x: Math.random() * width, |
| 27 | y: Math.random() * height, |
| 28 | size: Math.random() * 2 + 1, |
| 29 | speed: Math.random() * 50 + 20, |
| 30 | })), |
| 31 | ) |
| 32 | } |
| 33 | } |
| 34 | |
| 35 | generateStars() |
| 36 | window.addEventListener('resize', generateStars) |
| 37 | return () => window.removeEventListener('resize', generateStars) |
| 38 | }, []) |
| 39 | |
| 40 | return ( |
| 41 | <motion.button |
| 42 | ref={buttonRef} |
| 43 | className="text-md relative overflow-hidden rounded-full border-2 border-yellow-400 bg-black px-8 py-2.5 font-semibold text-yellow-400 focus:outline-none" |
| 44 | style={{ |
| 45 | boxShadow: |
| 46 | '0 0 10px rgba(234, 179, 8, 0.5), 0 0 20px rgba(234, 179, 8, 0.3)', |
| 47 | }} |
| 48 | animate={controls} |
| 49 | whileTap={{ scale: 0.95 }} |
| 50 | whileHover={{ |
| 51 | boxShadow: |
| 52 | '0 0 15px rgba(234, 179, 8, 0.7), 0 0 30px rgba(234, 179, 8, 0.5)', |
| 53 | }} |
| 54 | > |
| 55 | {stars.map((star) => ( |
| 56 | <motion.div |
| 57 | key={star.id} |
| 58 | className="absolute rounded-full bg-white" |
| 59 | style={{ |
| 60 | left: star.x, |
| 61 | top: star.y, |
| 62 | width: star.size, |
| 63 | height: star.size, |
| 64 | }} |
| 65 | animate={{ |
| 66 | x: `-${star.speed}%`, |
| 67 | opacity: [0, 1, 0], |
| 68 | }} |
| 69 | transition={{ |
| 70 | duration: 2, |
| 71 | repeat: Infinity, |
nothing calls this directly
no test coverage detected