yaminncco / vue-sidebar-menu

A Vue.js Sidebar Menu Component
MIT License
646 stars 194 forks source link

Detect click outside on mobile and collapse #260

Closed guifsdev closed 1 year ago

guifsdev commented 1 year ago

How can I implement a functionality with this sidebar for when its on mobile and the user clicks outside the element, if the sidebar is not collapsed it becomes collapsed? My idea is to completely hide the sidebar when the user clicks the toggle and isOnMobile is true, and assign :relative based on the said value.

This was my attempt:

  <sidebar-menu
    id="sidebarMenu"
    ref="sidebarMenu"
    :relative="!isOnMobile"
    :menu="menu"
    :collapsed="collapsed"
    width="220px"
    :widthCollapsed="isOnMobile ? '0' : '50px'"
    @item-click="onItemClick"
  >
And on mounted hook:
const sidebar = this.$refs.sidebarMenu;   
const element = document.getElementById("sidebar");

document.addEventListener("click", (event) => {
  event.stopPropagation();
  const isClickOutside = !element.contains(event.target);
  if (isClickOutside && !sidebar.isCollapsed && sidebar.isOnMobile) {
    sidebar.isCollapsed = true;
  }
});


Did anyone find a simpler method of achieving this? 
yaminncco commented 1 year ago

I recommend to use a new state and hide the sidebar offscreen with translateX, then with a full screen overlay you can trigger the click event

<div id="sidebar" :class="[isOnMobile && isHidden && 'isHidden']">
  <sidebar-menu
    id="sidebarMenu"
    ref="sidebarMenu"
    :relative="!isOnMobile"
    :menu="menu"
    :collapsed="collapsed"
    width="220px"
    @item-click="onItemClick"
  />
  <div
    v-if="isOnMobile && !isHidden"
    class="sidebar-overlay"
    @click="onCLickOutside"
  />
</div>

onCLickOutside() {
  this.isHidden = true
}

#sidebar .v-sidebar-menu {
  transition: 300ms all ease;
}
#sidebar.isHidden .v-sidebar-menu {
  transform: translateX(-100%);
}
#sidebar .sidebar-overlay {
  position: fixed;
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;
  background-color: #000;
  opacity: 0.5;
  z-index: 900;
}
guifsdev commented 1 year ago

Thank you @yaminncco, this worked perfectly!