Reactでアコーディオンを作る

サービスを作った時に作ったけど、結局使わなかったので備忘録としてここへ。

アコーディオンのアニメーションを作成する

アニメーションはgsapに任せています。
React+Typescriptでのeの型はReact.MouseEvent<HTMLElement>で取れました。

  const accordionClick = (e: React.MouseEvent<HTMLElement>) => {
    const _this: HTMLElement = e.currentTarget;
    const thisParent = _this.closest<HTMLElement>('.accordion');
    const thisContent = thisParent?.querySelector('.accordion-content');
    const thisContentInner = thisParent?.querySelector('.accordion-content-inner');

    if (thisContent && thisParent && thisContentInner) {
      //アコーディオンコンテンツの高さを取得
      const contentHeight: number = thisContentInner.clientHeight;

      //アニメーションはgsap
      if (thisParent.classList.contains('is-active')) {
        //閉じる
        gsap.to(thisContent, 0.3,
          {
            height: 0,
            minHeight: "auto",
            //アニメーションが終わったら処理
            onComplete: () => {
              thisParent.classList.remove('is-active');
            },
          }
        );
      } else {
        //開く
        gsap.to(thisContent, 0.3,
          {
            height: "auto",
            minHeight: contentHeight,
            //アニメーションが終わったら処理
            onComplete: () => {
              thisParent.classList.add('is-active');
            },
          }
        );
      }
    }
  }

//中略
  return (
    <>
      //props.openの値によって初期クラスを振り分け
      <div className={props.open ? "accordion is-active" : "accordion"}>
        //クリックイベント
        <div className="accordion-ttl" onClick={accordionClick}>
          <h2 className="accordion-ttl-txt">{props.title}</h2>
          <span className="accordion-icon"></span>
        </div>
        
        //中略

      </div>
    </>
  );