Use modal instead of dropdown menu in small/mobile views (#2674)

Co-Authored-By: Rigel Kent <par@rigelk.eu>
pull/2706/head
Kim 2020-04-30 19:23:54 +02:00 committed by GitHub
parent c285180a45
commit d363ef5360
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 101 additions and 11 deletions

View File

@ -1,10 +1,20 @@
<div class="sub-menu">
<ng-container *ngFor="let menuEntry of menuEntries">
<div class="sub-menu" [ngClass]="{ 'no-scroll': isModalOpened }">
<ng-container *ngFor="let menuEntry of menuEntries; index as id">
<a *ngIf="menuEntry.routerLink" [routerLink]="menuEntry.routerLink" routerLinkActive="active" class="title-page title-page-settings">{{ menuEntry.label }}</a>
<div *ngIf="!menuEntry.routerLink" ngbDropdown [container]="container" class="parent-entry" #dropdown="ngbDropdown" (mouseleave)="closeDropdownIfHovered(dropdown)">
<div *ngIf="!menuEntry.routerLink" ngbDropdown [container]="container" class="parent-entry"
#dropdown="ngbDropdown" (mouseleave)="closeDropdownIfHovered(dropdown)">
<span
*ngIf="isInSmallView"
[ngClass]="{ active: !!suffixLabels[menuEntry.label] }"
(click)="openModal(id)" role="button" class="title-page title-page-settings">
<ng-container i18n>{{ menuEntry.label }}</ng-container>
<ng-container *ngIf="!!suffixLabels[menuEntry.label]"> - {{ suffixLabels[menuEntry.label] }}</ng-container>
</span>
<span
*ngIf="!isInSmallView"
(mouseenter)="openDropdownOnHover(dropdown)" [ngClass]="{ active: !!suffixLabels[menuEntry.label] }" ngbDropdownAnchor
(click)="dropdownAnchorClicked(dropdown)" role="button" class="title-page title-page-settings"
>
@ -20,6 +30,21 @@
</a>
</div>
</div>
</ng-container>
</div>
<ng-template #modal let-close="close" let-dismiss="dismiss">
<div class="modal-body">
<ng-container *ngFor="let menuEntry of menuEntries; index as id">
<div [ngClass]="{ hidden: id !== currentMenuEntryIndex }">
<a *ngFor="let menuChild of menuEntry.children"
[ngClass]="{ icon: hasIcons }"
[routerLink]="menuChild.routerLink" routerLinkActive="active" (click)="dismissOtherModals()">
<my-global-icon *ngIf="menuChild.iconName" [iconName]="menuChild.iconName"></my-global-icon>
{{ menuChild.label }}
</a>
</div>
</ng-container>
</div>
</ng-template>

View File

@ -25,3 +25,32 @@
top: -1px;
}
.sub-menu.no-scroll {
overflow-x: hidden;
}
.modal-body {
.hidden {
display: none;
}
a {
@include disable-default-a-behaviour;
color: currentColor;
box-sizing: border-box;
display: block;
font-size: 1.2rem;
padding: 9px 12px;
text-align: initial;
text-transform: unset;
width: 100%;
&.active {
color: var(--mainBackgroundColor) !important;
background-color: var(--mainHoverColor);
opacity: .9;
}
}
}

View File

@ -1,8 +1,14 @@
import { Component, Input, OnDestroy, OnInit } from '@angular/core'
import {
Component,
Input,
OnDestroy,
OnInit,
ViewChild
} from '@angular/core'
import { filter, take } from 'rxjs/operators'
import { NavigationEnd, Router } from '@angular/router'
import { Subscription } from 'rxjs'
import { NgbDropdown } from '@ng-bootstrap/ng-bootstrap'
import { NgbDropdown, NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { GlobalIconName } from '@app/shared/images/global-icon.component'
import { ScreenService } from '@app/shared/misc/screen.service'
@ -26,31 +32,40 @@ export type TopMenuDropdownParam = {
export class TopMenuDropdownComponent implements OnInit, OnDestroy {
@Input() menuEntries: TopMenuDropdownParam[] = []
@ViewChild('modal', { static: true }) modal: NgbModal
suffixLabels: { [ parentLabel: string ]: string }
hasIcons = false
container: undefined | 'body' = undefined
isModalOpened = false
currentMenuEntryIndex: number
private openedOnHover = false
private routeSub: Subscription
constructor (
private router: Router,
private modalService: NgbModal,
private screen: ScreenService
) {}
) { }
get isInSmallView () {
return this.screen.isInSmallView()
}
ngOnInit () {
this.updateChildLabels(window.location.pathname)
this.routeSub = this.router.events
.pipe(filter(event => event instanceof NavigationEnd))
.subscribe(() => this.updateChildLabels(window.location.pathname))
.pipe(filter(event => event instanceof NavigationEnd))
.subscribe(() => this.updateChildLabels(window.location.pathname))
this.hasIcons = this.menuEntries.some(
e => e.children && e.children.some(c => !!c.iconName)
)
// We have to set body for the container to avoid scroll overflow on mobile view
if (this.screen.isInMobileView()) {
// We have to set body for the container to avoid scroll overflow on mobile and small views
if (this.isInSmallView) {
this.container = 'body'
}
}
@ -85,6 +100,27 @@ export class TopMenuDropdownComponent implements OnInit, OnDestroy {
this.openedOnHover = false
}
openModal (index: number) {
this.currentMenuEntryIndex = index
this.isModalOpened = true
this.modalService.open(this.modal, {
centered: true,
beforeDismiss: async () => {
this.onModalDismiss()
return true
}
})
}
onModalDismiss () {
this.isModalOpened = false
}
dismissOtherModals () {
this.modalService.dismissAll()
}
private updateChildLabels (path: string) {
this.suffixLabels = {}