CSS modules Heart button

```scss
// アニメーションの時間
$animateTime: 800ms;
// パーティクルの数
$particleNum: 14;

@mixin centering {
  transform-origin: 250px 250px;
}

@mixin animationFill {
  animation-fill-mode: forwards;
}

.likeButton {
  cursor: pointer;

  .border {
    fill: rgb(255, 255, 255);
  }
  .explosion {
    transform-origin: 250px 250px;
    transform: scale(0.02);
    stroke: rgb(224, 183, 201);
    fill: none;
    opacity: 0;
    stroke-width: 1;
    @include centering;
  }

  .particleLayer {
    opacity: 0;

    circle {
      opacity: 0;
      @include centering;
    }
  }

  .heart {
    fill: rgba(6, 6, 6, 0.24);
    transform: scale(0.8);
    @include centering;
  } 
  
  &.unClicked {
    .heart {
      fill: rgba(6, 6, 6, 0.24);
    }
  }

  &.clicked {
    .explosion {
      animation: explosionAnime $animateTime;
      @include animationFill;
    }

    .heart {
      animation: heartAnime $animateTime;
      @include animationFill;
    }

    .particleLayer {
      animation: particleLayerAnime $animateTime;
      @include animationFill;

      @for $index from 1 through $particleNum {
        circle:nth-child(#{$index}) {
          animation: particleAnimate#{$index} $animateTime;
          @include animationFill;
        }
      }
    }
  }
  
  &.isActive {
    .heart {
      fill: #404040;
    }
  }
}

// 爆発のアニメーション
@keyframes explosionAnime {
  0% {
    opacity: 0;
    transform: scale(0.01);
  }
  1% {
    opacity: 1;
    transform: scale(0.01);
  }

  5% {
    stroke-width: 200;
  }

  20% {
    stroke-width: 300;
  }

  50% {
    stroke: rgb(104, 72, 125);
    transform: scale(1.1);
    stroke-width: 1;
  }
  50.1% {
    stroke-width: 0;
  }

  100% {
    stroke: rgb(81, 57, 97);
    transform: scale(1.1);
    stroke-width: 0;
  }
}

// パーティクル全体のアニメーション
@keyframes particleLayerAnime {
  0% {
    transform: translate(0, 0);
    opacity: 0;
  }
  30% {
    opacity: 0;
  }
  31% {
    opacity: 1;
  }

  60% {
    transform: translate(0, 0);
  }

  70% {
    opacity: 1;
  }

  100% {
    opacity: 0;
    transform: translate(0, -20px);
  }
}

// パーティクルの個別アニメーション

// 各点の移動位置
// 1点目のx座標, 1点目のy座標, 2点目のx座標, 2点目のy座標,...と並んでいる
$points: -16, -59,
41, 43,
50, -48,
-39, 36,
-39, 32,
48, 6,
-69, -36,
-12, -52,
-43, -21,
-10, 47,
66, -9,
40, -45,
29, 24,
-10, 50;

$pointer: 1;

@for $index from 1 through $particleNum {
  @keyframes particleAnimate#{$index} {
    0% {
      transform: translate(0, 0);
    }
    30% {
      opacity: 1;
      transform: translate(0, 0);
    }
    80% {
      transform: translate(#{nth($points, $pointer)}px, #{nth($points, $pointer + 1)}px);
    }
    90% {
      transform: translate(#{nth($points, $pointer)}px, #{nth($points, $pointer + 1)}px);
    }
    100% {
      opacity: 1;
      transform: translate(#{nth($points, $pointer)}px, #{nth($points, $pointer + 1)}px);
    }
  }
  $pointer: $pointer + 2;
}

// ハートのアニメーション
@keyframes heartAnime {
  0% {
    transform: scale(0);
    fill: #404040;
  }
  39% {
    transform: scale(0);
  }
  60% {
    transform: scale(1.2, 1.2);
  }
  70% {
    transform: scale(1, 1) translate(0%, -10%);
  }
  75% {
    transform: scale(1.1, 0.9) translate(0%, 5%);
  }
  80% {
    transform: scale(0.95, 1.05) translate(0%, -3%);
  }
  100% {
    transform: scale(1.0, 1.0) translate(0%, 0%);
    fill: #404040;
  }
}
```

```tsx
import classNames from 'classnames';
import { FaHeart, FaRegHeart } from 'react-icons/fa';
import styles from './Favorite.module.scss';

type Props = {
  isActive: boolean;
  isClicked?: boolean;
};
export default function Favorite(props: Props) {
  const { isActive, isClicked } = props;
  return (
    <span className={classNames('text-[10px] text-dark md:text-[12px]')}>
      <svg className={classNames(styles.likeButton, isClicked ? styles.clicked : styles.unClicked, isActive ? styles.isActive : '' )} width="50px" height="50px" viewBox="0 0 500 500">
        <circle className={styles.explosion} r="150" cx="250" cy="250"/>
        <g className={styles.particleLayer}>
          <circle fill="#8CE8C3" cx="130" cy="126.5" r="12.5"/>
          <circle fill="#8CE8C3" cx="411" cy="313.5" r="12.5"/>
          <circle fill="#91D2FA" cx="279" cy="86.5" r="12.5"/>
          <circle fill="#91D2FA" cx="155" cy="390.5" r="12.5"/>
          <circle fill="#CC8EF5" cx="89" cy="292.5" r="10.5"/>
          <circle fill="#9BDFBA" cx="414" cy="282.5" r="10.5"/>
          <circle fill="#9BDFBA" cx="115" cy="149.5" r="10.5"/>
          <circle fill="#9FC7FA" cx="250" cy="80.5" r="10.5"/>
          <circle fill="#9FC7FA" cx="78" cy="261.5" r="10.5"/>
          <circle fill="#96D8E9" cx="182" cy="402.5" r="10.5"/>
          <circle fill="#CC8EF5" cx="401.5" cy="166" r="13"/>
          <circle fill="#DB92D0" cx="379" cy="141.5" r="10.5"/>
          <circle fill="#DB92D0" cx="327" cy="397.5" r="10.5"/>
          <circle fill="#DD99B8" cx="296" cy="392.5" r="10.5"/>
        </g>
        <path className={styles.heart} d="M250,187.4c-31.8-47.8-95.5-19.8-95.5,32.2c0,35.2,31.8,60.3,55.7,79.2c24.9,19.7,31.8,23.9,39.8,31.8 c7.9-7.9,14.6-12.6,39.8-31.8c24.3-18.5,55.7-44.4,55.7-79.6C345.5,167.6,281.8,139.7,250,187.4z"/>
      </svg>
      {/* {props.isActive ? <FaHeart size='1.5em' /> : <FaRegHeart size='1.5em' />} */}
    </span>
  );
}


```