JSFiddle - React, Tailwind, and code Playground

by seulbiLee

HTML

<div class="wrap-accordion-group" data-role="accordion-group" accordion-option="toggle">
            <button id="accordion-head-1" aria-level="2" aria-expanded="false" class="accordion-btn" aria-controls="accordion-region-1">
                <span>Accordion Head 1</span>
            </button>
            <div class="wrap-accordion-contents" id="accordion-region-1" role="region" aria-labelledby="accordion-head-1">
                <div class="inner-accordion-contents">
                    Accordion contents 1 Accordion contents 1 Accordion contents 1 Accordion contents 1
                    Accordion contents 1 Accordion contents 1 Accordion contents 1 Accordion contents 1
                    Accordion contents 1 Accordion contents 1 Accordion contents 1 Accordion contents 1
                    Accordion contents 1 Accordion contents 1 Accordion contents 1 Accordion contents 1
                    Accordion contents 1 Accordion contents 1 Accordion contents 1 Accordion contents 1
                    Accordion contents 1 Accordion contents 1 Accordion contents 1 Accordion contents 1
                </div>
            </div>
            <button id="accordion-head-2" aria-level="2" aria-expanded="false" class="accordion-btn" aria-controls="accordion-region-2">
                <span>Accordion Head 2</span>
            </button>
            <div class="wrap-accordion-contents" id="accordion-region-2" role="region" aria-labelledby="accordion-head-2">
                <div class="inner-accordion-contents">
                    Accordion contents 2 Accordion contents 2 Accordion contents 2 Accordion contents 2
                    Accordion contents 2 Accordion contents 2 Accordion contents 2 Accordion contents 2
                    Accordion contents 2 Accordion contents 2 Accordion contents 2 Accordion contents 2
                    Accordion contents 2 Accordion contents 2 Accordion contents 2 Accordion contents 2
                    Accordion contents 2 Accordion contents...

SCSS

.wrap-accordion-group {
  max-width: 500px;
  float: left;
  margin-right: 30px;
}
.accordion-btn {
  position: relative;
  z-index: 0;
  width: 100%;
  height: 40px;
  padding: 0 10px;
  border: 1px solid #ccc;
  background-color: #fff;
  text-align: left;
  font-size: 16px;
  cursor: pointer;
  &::after {
    display: block;
    content: '';
    position: absolute;
    top: 45%;
    right: 10px;
    width: 10px;
    height: 10px;
    box-sizing: border-box;
    border-left: 1px solid #000;
    border-bottom: 1px solid #000;
    transform: rotate(-45deg) translateY(-50%);
    transform-origin: left center;
    transition: transform .5s;
  }
  &[aria-expanded="true"]::after {
    top: 30%;
    transform: rotate(135deg) translateY(-50%);
  }
}
.wrap-accordion-contents {
  height: 0;
  overflow: hidden;
  box-sizing: border-box;
  transition: height .3s;
}
.inner-accordion-contents {
  padding: 10px;
}

JavaScript

function AccordionScript() {
		const _$this = this;
		let accordionGroups;
        
        _$this.init = {
            // 여러 개의 accordion 을 각각 독립적으로 이벤트 실행
            getAccordionGroups: () => {
                // 현재 페이지에 있는 모든 accordion 을 배열로 담음
                accordionGroups = document.querySelectorAll('[data-role="accordion-group"]');
                accordionGroups.forEach(function(accordionGroup) {
                    _$this.init.getAccordionBtns(accordionGroup);
                });
            },
            // accordion 버튼 클릭 이벤트를 독립적으로 실행
            getAccordionBtns: (accordionGroup) => {
                // 배열에 담긴 accordion 내부 버튼을 찾아서
                const accordionBtns = accordionGroup.querySelectorAll('.accordion-btn');
                accordionBtns.forEach(function(accordionBtn) {
                    // 클릭 이벤트를 실행
                    _$this.clickAction.accordionBtnClick(accordionBtn);
                    accordionBtn.nextElementSibling.style.transitionDuration = accordionBtn.nextElementSibling.scrollHeight * 0.0016 + 's';
                    // 초기 셋팅 : button 의 aria-expanded 값이 false 인 accordion contents 에 hidden 값 넣기
                    if (accordionBtn.ariaExpanded === 'false' && accordionBtn.nextElementSibling !== null) accordionBtn.nextElementSibling.setAttribute('hidden', 'true');
                    // 초기 셋팅 : button 의 aria-expanded 값이 true 인 accordion contents 에 height size 넣기
                    if (accordionBtn.ariaExpanded === 'true' && accordionBtn.nextElementSibling !== null) accordionBtn.nextElementSibling.style.height = accordionBtn.nextElementSibling.scrollHeight + 'px';
                });
            },
        };
        _$this.accordionEvent = {
            removeEvent: (target, accordionGroup) => {
                const accordionBtns = accordionGroup.querySelectorAll('.accordion-btn');
                const accordionContents = accordionGroup.querySelectorAll('[role="region"]');
                for (let accordionBtn of...