akveo / nebular

:boom: Customizable Angular UI Library based on Eva Design System :new_moon_with_face::sparkles:Dark Mode
https://akveo.github.io/nebular
MIT License
8.06k stars 1.51k forks source link

[Sidebar]: auto compact/collapse #2009

Open mmezian opened 5 years ago

mmezian commented 5 years ago

Issue type

Issue description

Current behavior: On low resolutions, menu should close itself when we click on a link, or when we click outside of the menu. Currently, the menu doesn't collapse on either situations, and is blocking the view of half of the content of the site on resolution width < 1200px

Expected behavior: When resolution is 1200px or lower, when the menu is expanded, when we click a menu item or click outside the menu it should close itself.

Steps to reproduce: We are using nebular 4.1.2

Related code: Haven't touched the original code for the menu.

Other information:

I found this ticket that seems related, from 2017, but it seems that it is not viable anymore as structure has changed : https://github.com/akveo/ngx-admin/issues/947

Angular, Nebular

 "dependencies": {
    "@agm/core": "^1.0.0-beta.7",
    "@angular/animations": "8.1.3",
    "@angular/cdk": "8.1.1",
    "@angular/common": "8.1.3",
    "@angular/compiler": "8.1.3",
    "@angular/core": "8.1.3",
    "@angular/forms": "8.1.3",
    "@angular/platform-browser": "8.1.3",
    "@angular/platform-browser-dynamic": "8.1.3",
    "@angular/router": "8.1.3",
    "@asymmetrik/ngx-leaflet": "3.0.1",
    "@nebular/auth": "4.1.2",
    "@nebular/eva-icons": "4.1.2",
    "@nebular/security": "4.1.2",
    "@nebular/theme": "4.1.2",
    "@swimlane/ngx-charts": "^10.0.0",
    "amazon-cognito-identity-js": "^3.0.15",
    "angular-tree-component": "7.2.0",
    "angular2-chartjs": "0.4.1",
    "angular2-toaster": "^7.0.0",
    "bootstrap": "4.3.1",
    "chart.js": "^2.8.0",
    "ckeditor": "4.7.3",
    "classlist.js": "1.1.20150312",
    "core-js": "2.5.1",
    "echarts": "^4.0.2",
    "eva-icons": "^1.1.0",
    "intl": "1.2.5",
    "ionicons": "2.0.1",
    "leaflet": "1.2.0",
    "nebular-icons": "1.1.0",
    "ng2-ckeditor": "^1.2.2",
    "ng2-completer": "2.0.8",
    "ng2-smart-table": "1.3.5",
    "ngx-echarts": "^4.0.1",
    "node-sass": "^4.12.0",
    "normalize.css": "6.0.0",
    "pace-js": "1.0.2",
    "roboto-fontface": "0.8.0",
    "rxjs": "6.5.2",
    "rxjs-compat": "6.3.0",
    "socicon": "3.0.5",
    "tinymce": "4.5.7",
    "tslib": "^1.9.0",
    "typeface-exo": "0.0.22",
    "web-animations-js": "github:angular/web-animations-js#release_pr208",
    "zone.js": "~0.9.1"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "~0.800.2",
    "@angular/cli": "^8.1.2",
    "@angular/compiler-cli": "8.1.3",
    "@angular/language-service": "8.1.3",
    "@compodoc/compodoc": "^1.1.10",
    "@fortawesome/fontawesome-free": "^5.2.0",
    "@types/d3-color": "1.0.5",
    "@types/googlemaps": "^3.30.4",
    "@types/jasmine": "2.5.54",
    "@types/jasminewd2": "2.0.3",
    "@types/leaflet": "1.2.3",
    "@types/node": "6.0.90",
    "codelyzer": "^5.0.1",
    "conventional-changelog-cli": "1.3.4",
    "husky": "0.13.3",
    "jasmine-core": "2.6.4",
    "jasmine-spec-reporter": "4.1.1",
    "karma": "^4.2.0",
    "karma-chrome-launcher": "2.1.1",
    "karma-cli": "1.0.1",
    "karma-coverage-istanbul-reporter": "1.3.0",
    "karma-jasmine": "1.1.0",
    "karma-jasmine-html-reporter": "0.2.2",
    "npm-run-all": "4.0.2",
    "protractor": "^6.0.0",
    "rimraf": "2.6.1",
    "stylelint": "^10.1.0",
    "ts-node": "3.2.2",
    "tslint": "^5.7.0",
    "tslint-language-service": "^0.9.9",
    "typescript": "3.4.5"
  }
yggg commented 5 years ago

Moving to the Nebular repository.

https://github.com/akveo/ngx-admin/pull/5531#issuecomment-539499784: I'd rather see this as a feature of the sidebar itself, not as part of ngx-admin. Sidebar already detects menu clicks to expand if needed (see sidebar source). So it also could do the opposite and automatically compact/collapse as proposed in the original issue (#2009). A few things to notice:

  1. It should take into account current media breakpoint and compact/collapse only if it needs to. Like the behavior described in the issue, except that we shouldn't hard code width and rather use compactedBreakpoints, collapsedBreakpoints to chose target state.
  2. We must be able to turn off auto collapse behavior via some configuration input.
  3. While implementing a new feature, please don't use browser api such as querySelector directly (as it's done in onClick method). I believe it could be done in a more Angular way, for example using ContentChild decorator. It would be great to get rid of query selector in onClick method as well.

I'll move the issue to the Nebular repository. We can discuss further design notes there.

rkanswers commented 5 years ago

Hello @mmezian, I encountered the same problem. I did not come up with the entire solution that has been recommended. However, I did come up with a solution for when you click on a menu item that it should close.

However, I am working in a Nebular 3.4.2. So you may need some adaptation. Add the following inside ngOnInit(){...} of header.component.ts And import NbMenuService

this.menuService.onItemSelect() .subscribe((event: { tag: string, item: any }) => { if (document.documentElement.clientWidth < 576){ this.sidebarService.toggle(true, 'menu-sidebar'); console.log('this.menuservices.onitemselect'); document.getElementById("header-sidebar").classList.remove("expand");
} });

featured14 commented 5 years ago

@rkanswers Thanks! Messing around with Nebular 4.4.0; In my case, I have all that I need in a header components just like ngx-admin example but trimmed to suit my needs. I modified your example to work without hard coding widths, rather getting the breakpoints:

const { sm } = this.breakpointService.getBreakpointsMap(); 

this.menuService.onItemSelect() 
      .pipe(takeUntil(this.destroy$))
      .subscribe((event: { tag: string, item: any }) => {
        if (document.documentElement.clientWidth < sm){
          this.sidebarService.collapse('menu-sidebar');
        }
    });
peekyou commented 5 days ago

Thank you @featured14, similarly I added this in my header.component.ts to collapse the sidebar on click outside

@HostListener('document:click', ['$event'])
  onClickOutside($event: any) {
    const { sm } = this.breakpointService.getBreakpointsMap();
    if (document.documentElement.clientWidth < sm) {
      let node = $event.target;
      let isSidebarOrMenuButtonClick = false;
      while (node && !isSidebarOrMenuButtonClick) {
        isSidebarOrMenuButtonClick = node.classList && (node.classList.contains('sidebar-toggle') || node.classList.contains('menu-sidebar'));
        node = node.parentElement;
      }

      if (!isSidebarOrMenuButtonClick) {
          this.sidebarService.collapse('menu-sidebar');
      }
    }
}

Change the class name for the menu button and the sidebar according to your needs.