locate-the-news / frontend / src / components / ClusterCircle.jsx
ClusterCircle.jsx
Raw
import React from 'react';
import { motion } from 'framer-motion';
import '../styles/animations.css';

function ClusterCircle({ count, sentiment, negativeRatio, color, size = 'medium', onClick }) {
    // Size mapping
    const sizeMap = {
        small: 40,
        medium: 60,
        large: 80
    };

    const diameter = sizeMap[size] || 60;
    const fontSize = size === 'large' ? 18 : size === 'medium' ? 14 : 12;

    return (
        <motion.div
            initial={{ scale: 0, opacity: 0 }}
            animate={{ scale: 1, opacity: 1 }}
            exit={{ scale: 0, opacity: 0 }}
            transition={{ duration: 0.3, ease: [0.4, 0, 0.2, 1] }}
            className="cluster-marker animate-pulse"
            style={{
                width: `${diameter}px`,
                height: `${diameter}px`,
                backgroundColor: `${color}33`,
                border: `3px solid ${color}`,
                color: color,
                fontSize: `${fontSize}px`,
                boxShadow: `
          0 0 20px ${color}66,
          0 0 40px ${color}33,
          inset 0 0 20px ${color}22
        `
            }}
            onClick={onClick}
            whileHover={{
                scale: 1.15,
                boxShadow: `
          0 0 30px ${color}99,
          0 0 60px ${color}66,
          inset 0 0 30px ${color}33
        `
            }}
            whileTap={{ scale: 0.95 }}
        >
            <div style={{
                display: 'flex',
                flexDirection: 'column',
                alignItems: 'center',
                justifyContent: 'center',
                height: '100%'
            }}>
                <div style={{
                    fontWeight: 700,
                    lineHeight: 1
                }}>
                    {count}
                </div>
                {size === 'large' && (
                    <div style={{
                        fontSize: '10px',
                        opacity: 0.8,
                        marginTop: '2px',
                        textTransform: 'uppercase',
                        letterSpacing: '0.5px'
                    }}>
                        news
                    </div>
                )}
            </div>

            {/* Pulsating outer ring */}
            <motion.div
                style={{
                    position: 'absolute',
                    top: '-6px',
                    left: '-6px',
                    right: '-6px',
                    bottom: '-6px',
                    borderRadius: '50%',
                    border: `2px solid ${color}`,
                    opacity: 0.4
                }}
                animate={{
                    scale: [1, 1.2, 1],
                    opacity: [0.4, 0.1, 0.4]
                }}
                transition={{
                    duration: 2,
                    repeat: Infinity,
                    ease: 'easeInOut'
                }}
            />
        </motion.div>
    );
}

export default ClusterCircle;