Dropdown 구현

YunKuk Park·2021년 12월 12일
0

👣 하나씩 꾸준히

목록 보기
7/15

구현 할 사항

Page구현사항구현이미지desc
Mainuser mymenu Dropdown 구현dropdown 구현
- 실제 인스타 페이지처럼 프로필 사진 클릭 시 메뉴 박스가 생성될 수 있도록 구현
- 메뉴 박스 바깥 영역 클릭 시에는 다시 닫히도록 구현

구현

HTML


<div class="user-action-item my-menu">
  <button type="button" class="dropdown-button avatar avatar-26">
    <img src="./assets/image/yunkuk-avatar.jpg" alt="유저아바타" />
  </button>

  <div class="my-menu-content">
    <ul class="my-menu-list">
      <li class="my-menu-item">
        <i class="far fa-user-circle"></i>
        <a href="#">프로필</a>
       </li>
       <li class="my-menu-item">
         <i class="far fa-bookmark"></i>
         <a href="#">저장됨</a>
       </li>
       <li class="my-menu-item">
         <i class="fas fa-cog"></i>
         <a href="#">설정</a>
       </li>
       <li class="my-menu-item">
         <button type="button">로그아웃</button>
      </li>
    </ul>
  </div>
</div>
  1. dropdown event 를 만들어줄 button을 만든다.
  2. 형제 관계로 button을 눌렀을 시 보여줄 dropdown menu contents를 넣어준다.



CSS


.my-menu {  
/* dropdown은 absolute로 뿌려줘야 하므로 부모를 position: relative로 잡아준다 */
  position: relative;
}

.my-menu .avatar:hover::after,
.my-menu .avatar.is-active::after {
/* avatar button이 hover되었을 때나, is-active 상태일 때는 avatar를 감싸주는 테두리를 추가한다. */
/* border를 쓰지 않은 이유는 상태변화에 대해서 따로 분리를 해주고 싶었다. */
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 26px;
  height: 26px;
  border-radius: 50%;
  border: 2px solid #8e8e8e;
  content: '';
}

.my-menu-content {
  display: none;
  position: absolute;
  width: 225px;
  top: 37px;
  left: -175px;
  padding: 10px 0;
  background-color: #fff;
  font-size: 16px;
  border: 1px solid #dbdbdb;
  border-radius: 5px;
  font-size: 14px;
}

.my-menu-content.is-active {
/* dropdown 메뉴는 기본적으로 display: none 상태이고, JS를 통해 toggling된 css에서 display: block을 주었다. */
  display: block;
}

.my-menu-content::before,
.my-menu-content::after {
/* dropdown 메뉴에서 툴팁("▲")에 관한 스타일링이다. */
  position: absolute;
  left: 83%;
  transform: translateX(-50%);
  top: -24px;
  display: block;
  width: 0;
  height: 0;
  border-top: 12px solid transparent;
  border-right: 10px solid transparent;
  border-bottom: 12px solid transparent;
  border-left: 10px solid transparent;
  content: '';
}

.my-menu-content::before {
  border-bottom-color: #e0e2e7;
}
.my-menu-content::after {
  top: -22px;
  border-bottom-color: #fff;
}

/* 여기서 부터는 세부적인 dropdown menu content item들 정렬하는 스타일 */
.my-menu-item {
  display: flex;
  align-items: center;
  padding: 0 15px;
  height: 35px;
}

.my-menu-item i {
  position: relative;
  top: 2px;
  width: 14px;
  height: 14px;
  font-size: 14px;
  margin-right: 10px;
}

.my-menu-item i.fa-bookmark {
  left: 1px;
}

.my-menu-item:nth-last-child(2) {
  margin-bottom: 5px;
}

.my-menu-item:last-child {
  padding: 10px 15px 0 15px;
  border-top: 1px solid #dbdbdb;
}


JavaScript


const userActionGroup = document.querySelector('.user-action-group');
const myMenuTrigger = userActionGroup.querySelector('.dropdown-button');
const myMenuContent = userActionGroup.querySelector('.my-menu-content');

const handleMyMenu = (event) => {
  myMenuContent.classList.toggle('is-active');
  myMenuTrigger.classList.toggle('is-active');
};

const exitMyMenu = (event) => {
  const isDropDown = event.target.matches('.dropdown-button');
  const isActive = myMenuContent.classList.contains('is-active');

  if (!isDropDown && isActive) {
    myMenuContent.classList.remove('is-active');
    myMenuTrigger.classList.remove('is-active');
  }
};

const init = () => {
  window.addEventListener('click', exitMyMenu);
  myMenuTrigger.addEventListener('click', handleMyMenu);
};

init();
function기능
handleMyMenu(event)1. 메뉴 콘텐트에 is-active 클래스 toggling
2. 드롭다운을 발생시키는 버튼에 테두리를 주기 위한 is-active 클래스 toggling
3. event를 인자로 받으려는 이유는 같은 드롭다운 형태에 대해서 event.target을 사용하여 재사용을 하기 위해 받아옴
exitMyMenu(event)메뉴 박스 바깥 영역 클릭 시에는 다시 닫히도록 구현
1. 현재 드롭다운이 켜져있고 다른영역을 클릭 하였을 때 is-active 클래스 remove
profile
( • .̮ •)◞⸒⸒

0개의 댓글