import React from 'react'
import ReactApexChart from 'react-apexcharts'
import './styles.css'

// A BUBBLE beeswarm: one bubble per game, laned by genre on a critic-score axis,
// with each bubble sized (by area) to its sales. So position reads quality and
// area reads reach, the biggest sellers pop out without leaving the swarm.
// Each datum carries value (score, X), z (copies sold, drives the radius) and a
// title (name, shown on hover). Figures are illustrative.
// Shared by the vanilla-js / React / Vue builds.
function g(name, score, sales) {
  return { name: name, value: score, z: sales }
}

var gameSeries = [
  {
    name: 'Action-Adventure',
    data: [
      g('Red Dead Redemption 2', 97, 55),
      g('God of War', 94, 23),
      g('Horizon Zero Dawn', 89, 24),
      g('Marvel’s Spider-Man', 87, 20),
      g('Uncharted 4', 93, 16),
      g('Ghost of Tsushima', 83, 13),
      g('The Last of Us Part II', 93, 10),
      g('Assassin’s Creed Odyssey', 83, 12),
    ],
  },
  {
    name: 'RPG',
    data: [
      g('Skyrim', 94, 60),
      g('The Witcher 3', 93, 50),
      g('Cyberpunk 2077', 86, 30),
      g('Elden Ring', 96, 25),
      g('Baldur’s Gate 3', 96, 15),
      g('Dark Souls III', 89, 10),
      g('Persona 5', 93, 9),
      g('Final Fantasy VII Remake', 87, 7),
    ],
  },
  {
    name: 'Racing',
    data: [
      g('Mario Kart 8 Deluxe', 92, 62),
      g('Forza Horizon 5', 92, 45),
      g('Forza Horizon 4', 92, 24),
      g('Gran Turismo 7', 87, 12),
      g('Burnout Paradise', 88, 8),
      g('F1 23', 82, 5),
      g('Need for Speed Heat', 72, 4),
      g('Dirt Rally 2.0', 84, 3),
    ],
  },
]

const ApexChart = () => {
  const [state, setState] = React.useState({
    series: gameSeries,
    options: {
      chart: {
        id: 'gameBubbleSwarm',
        type: 'unit',
        height: 460,
        fontFamily: 'inherit',
        animations: {
          enabled: true,
          speed: 700,
        },
      },
      colors: ['#2a78d6', '#eb6834', '#1baf7a'],
      legend: {
        position: 'bottom',
        markers: { radius: 12 },
      },
      plotOptions: {
        unit: {
          layout: 'scatter',
          scatter: {
            orientation: 'horizontal',
            spread: 'swarm',
            sizeField: 'z',
            sizeRange: [5, 26],
            xMin: 70,
            xMax: 100,
            tickAmount: 6,
            laneLabelWidth: 128,
            xTitle: 'Metacritic score',
          },
        },
      },
      tooltip: {
        enabled: true,
      },
    },
  })

  return (
    <div>
      <div className="wrap">
        <h1>Critic scores vs sales, by genre</h1>
        <p className="lead">
          One bubble per game, laned by genre on a critic-score axis. Position
          is the score, bubble area is copies sold, so the crowd-pleasers that
          also review well sit large and far to the right. Hover any bubble for
          the title.
        </p>

        <div className="card">
          <div id="chart">
            <ReactApexChart
              options={state.options}
              series={state.series}
              type="unit"
              height={460}
            />
          </div>
        </div>

        <div className="note">
          Adding <code>scatter.sizeRange: [min, max]</code> turns the beeswarm
          dots into area-scaled bubbles, read from each datum's{' '}
          <code>sizeField</code> (here
          <code>z</code>). The swarm still packs with no overlap, sized for the
          largest bubble, so a third measure rides on the distribution for free.
          The unit chart is a premium type, without a license it renders with a
          trial watermark.
        </div>
      </div>
    </div>
  )
}

export default ApexChart
Bubble Beeswarm - React Unit Charts | ApexCharts.js | ApexCharts.js