diff options
author | Kim <1877318+kimsible@users.noreply.github.com> | 2020-04-30 19:23:54 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-04-30 19:23:54 +0200 |
commit | d363ef5360b479d5f494ac1559fba59b2069fe9e (patch) | |
tree | 25aaf8505f9d3e826f4a1242f69abc497a074005 /client/src/app | |
parent | c285180a45e6cd342184512cae2bb56af51fe833 (diff) | |
download | PeerTube-d363ef5360b479d5f494ac1559fba59b2069fe9e.tar.gz PeerTube-d363ef5360b479d5f494ac1559fba59b2069fe9e.tar.zst PeerTube-d363ef5360b479d5f494ac1559fba59b2069fe9e.zip |
Use modal instead of dropdown menu in small/mobile views (#2674)
Co-Authored-By: Rigel Kent <par@rigelk.eu>
Diffstat (limited to 'client/src/app')
3 files changed, 101 insertions, 11 deletions
diff --git a/client/src/app/shared/menu/top-menu-dropdown.component.html b/client/src/app/shared/menu/top-menu-dropdown.component.html index 3087b2e98..d577f757d 100644 --- a/client/src/app/shared/menu/top-menu-dropdown.component.html +++ b/client/src/app/shared/menu/top-menu-dropdown.component.html | |||
@@ -1,10 +1,20 @@ | |||
1 | <div class="sub-menu"> | 1 | <div class="sub-menu" [ngClass]="{ 'no-scroll': isModalOpened }"> |
2 | <ng-container *ngFor="let menuEntry of menuEntries"> | 2 | <ng-container *ngFor="let menuEntry of menuEntries; index as id"> |
3 | 3 | ||
4 | <a *ngIf="menuEntry.routerLink" [routerLink]="menuEntry.routerLink" routerLinkActive="active" class="title-page title-page-settings">{{ menuEntry.label }}</a> | 4 | <a *ngIf="menuEntry.routerLink" [routerLink]="menuEntry.routerLink" routerLinkActive="active" class="title-page title-page-settings">{{ menuEntry.label }}</a> |
5 | 5 | ||
6 | <div *ngIf="!menuEntry.routerLink" ngbDropdown [container]="container" class="parent-entry" #dropdown="ngbDropdown" (mouseleave)="closeDropdownIfHovered(dropdown)"> | 6 | <div *ngIf="!menuEntry.routerLink" ngbDropdown [container]="container" class="parent-entry" |
7 | #dropdown="ngbDropdown" (mouseleave)="closeDropdownIfHovered(dropdown)"> | ||
7 | <span | 8 | <span |
9 | *ngIf="isInSmallView" | ||
10 | [ngClass]="{ active: !!suffixLabels[menuEntry.label] }" | ||
11 | (click)="openModal(id)" role="button" class="title-page title-page-settings"> | ||
12 | <ng-container i18n>{{ menuEntry.label }}</ng-container> | ||
13 | <ng-container *ngIf="!!suffixLabels[menuEntry.label]"> - {{ suffixLabels[menuEntry.label] }}</ng-container> | ||
14 | </span> | ||
15 | |||
16 | <span | ||
17 | *ngIf="!isInSmallView" | ||
8 | (mouseenter)="openDropdownOnHover(dropdown)" [ngClass]="{ active: !!suffixLabels[menuEntry.label] }" ngbDropdownAnchor | 18 | (mouseenter)="openDropdownOnHover(dropdown)" [ngClass]="{ active: !!suffixLabels[menuEntry.label] }" ngbDropdownAnchor |
9 | (click)="dropdownAnchorClicked(dropdown)" role="button" class="title-page title-page-settings" | 19 | (click)="dropdownAnchorClicked(dropdown)" role="button" class="title-page title-page-settings" |
10 | > | 20 | > |
@@ -20,6 +30,21 @@ | |||
20 | </a> | 30 | </a> |
21 | </div> | 31 | </div> |
22 | </div> | 32 | </div> |
23 | |||
24 | </ng-container> | 33 | </ng-container> |
25 | </div> | 34 | </div> |
35 | |||
36 | <ng-template #modal let-close="close" let-dismiss="dismiss"> | ||
37 | <div class="modal-body"> | ||
38 | <ng-container *ngFor="let menuEntry of menuEntries; index as id"> | ||
39 | <div [ngClass]="{ hidden: id !== currentMenuEntryIndex }"> | ||
40 | <a *ngFor="let menuChild of menuEntry.children" | ||
41 | [ngClass]="{ icon: hasIcons }" | ||
42 | [routerLink]="menuChild.routerLink" routerLinkActive="active" (click)="dismissOtherModals()"> | ||
43 | <my-global-icon *ngIf="menuChild.iconName" [iconName]="menuChild.iconName"></my-global-icon> | ||
44 | |||
45 | {{ menuChild.label }} | ||
46 | </a> | ||
47 | </div> | ||
48 | </ng-container> | ||
49 | </div> | ||
50 | </ng-template> | ||
diff --git a/client/src/app/shared/menu/top-menu-dropdown.component.scss b/client/src/app/shared/menu/top-menu-dropdown.component.scss index 1be699a88..5f90dcf80 100644 --- a/client/src/app/shared/menu/top-menu-dropdown.component.scss +++ b/client/src/app/shared/menu/top-menu-dropdown.component.scss | |||
@@ -25,3 +25,32 @@ | |||
25 | 25 | ||
26 | top: -1px; | 26 | top: -1px; |
27 | } | 27 | } |
28 | |||
29 | .sub-menu.no-scroll { | ||
30 | overflow-x: hidden; | ||
31 | } | ||
32 | |||
33 | .modal-body { | ||
34 | .hidden { | ||
35 | display: none; | ||
36 | } | ||
37 | |||
38 | a { | ||
39 | @include disable-default-a-behaviour; | ||
40 | |||
41 | color: currentColor; | ||
42 | box-sizing: border-box; | ||
43 | display: block; | ||
44 | font-size: 1.2rem; | ||
45 | padding: 9px 12px; | ||
46 | text-align: initial; | ||
47 | text-transform: unset; | ||
48 | width: 100%; | ||
49 | |||
50 | &.active { | ||
51 | color: var(--mainBackgroundColor) !important; | ||
52 | background-color: var(--mainHoverColor); | ||
53 | opacity: .9; | ||
54 | } | ||
55 | } | ||
56 | } | ||
diff --git a/client/src/app/shared/menu/top-menu-dropdown.component.ts b/client/src/app/shared/menu/top-menu-dropdown.component.ts index 24a083654..f98240804 100644 --- a/client/src/app/shared/menu/top-menu-dropdown.component.ts +++ b/client/src/app/shared/menu/top-menu-dropdown.component.ts | |||
@@ -1,8 +1,14 @@ | |||
1 | import { Component, Input, OnDestroy, OnInit } from '@angular/core' | 1 | import { |
2 | Component, | ||
3 | Input, | ||
4 | OnDestroy, | ||
5 | OnInit, | ||
6 | ViewChild | ||
7 | } from '@angular/core' | ||
2 | import { filter, take } from 'rxjs/operators' | 8 | import { filter, take } from 'rxjs/operators' |
3 | import { NavigationEnd, Router } from '@angular/router' | 9 | import { NavigationEnd, Router } from '@angular/router' |
4 | import { Subscription } from 'rxjs' | 10 | import { Subscription } from 'rxjs' |
5 | import { NgbDropdown } from '@ng-bootstrap/ng-bootstrap' | 11 | import { NgbDropdown, NgbModal } from '@ng-bootstrap/ng-bootstrap' |
6 | import { GlobalIconName } from '@app/shared/images/global-icon.component' | 12 | import { GlobalIconName } from '@app/shared/images/global-icon.component' |
7 | import { ScreenService } from '@app/shared/misc/screen.service' | 13 | import { ScreenService } from '@app/shared/misc/screen.service' |
8 | 14 | ||
@@ -26,31 +32,40 @@ export type TopMenuDropdownParam = { | |||
26 | export class TopMenuDropdownComponent implements OnInit, OnDestroy { | 32 | export class TopMenuDropdownComponent implements OnInit, OnDestroy { |
27 | @Input() menuEntries: TopMenuDropdownParam[] = [] | 33 | @Input() menuEntries: TopMenuDropdownParam[] = [] |
28 | 34 | ||
35 | @ViewChild('modal', { static: true }) modal: NgbModal | ||
36 | |||
29 | suffixLabels: { [ parentLabel: string ]: string } | 37 | suffixLabels: { [ parentLabel: string ]: string } |
30 | hasIcons = false | 38 | hasIcons = false |
31 | container: undefined | 'body' = undefined | 39 | container: undefined | 'body' = undefined |
40 | isModalOpened = false | ||
41 | currentMenuEntryIndex: number | ||
32 | 42 | ||
33 | private openedOnHover = false | 43 | private openedOnHover = false |
34 | private routeSub: Subscription | 44 | private routeSub: Subscription |
35 | 45 | ||
36 | constructor ( | 46 | constructor ( |
37 | private router: Router, | 47 | private router: Router, |
48 | private modalService: NgbModal, | ||
38 | private screen: ScreenService | 49 | private screen: ScreenService |
39 | ) {} | 50 | ) { } |
51 | |||
52 | get isInSmallView () { | ||
53 | return this.screen.isInSmallView() | ||
54 | } | ||
40 | 55 | ||
41 | ngOnInit () { | 56 | ngOnInit () { |
42 | this.updateChildLabels(window.location.pathname) | 57 | this.updateChildLabels(window.location.pathname) |
43 | 58 | ||
44 | this.routeSub = this.router.events | 59 | this.routeSub = this.router.events |
45 | .pipe(filter(event => event instanceof NavigationEnd)) | 60 | .pipe(filter(event => event instanceof NavigationEnd)) |
46 | .subscribe(() => this.updateChildLabels(window.location.pathname)) | 61 | .subscribe(() => this.updateChildLabels(window.location.pathname)) |
47 | 62 | ||
48 | this.hasIcons = this.menuEntries.some( | 63 | this.hasIcons = this.menuEntries.some( |
49 | e => e.children && e.children.some(c => !!c.iconName) | 64 | e => e.children && e.children.some(c => !!c.iconName) |
50 | ) | 65 | ) |
51 | 66 | ||
52 | // We have to set body for the container to avoid scroll overflow on mobile view | 67 | // We have to set body for the container to avoid scroll overflow on mobile and small views |
53 | if (this.screen.isInMobileView()) { | 68 | if (this.isInSmallView) { |
54 | this.container = 'body' | 69 | this.container = 'body' |
55 | } | 70 | } |
56 | } | 71 | } |
@@ -85,6 +100,27 @@ export class TopMenuDropdownComponent implements OnInit, OnDestroy { | |||
85 | this.openedOnHover = false | 100 | this.openedOnHover = false |
86 | } | 101 | } |
87 | 102 | ||
103 | openModal (index: number) { | ||
104 | this.currentMenuEntryIndex = index | ||
105 | this.isModalOpened = true | ||
106 | |||
107 | this.modalService.open(this.modal, { | ||
108 | centered: true, | ||
109 | beforeDismiss: async () => { | ||
110 | this.onModalDismiss() | ||
111 | return true | ||
112 | } | ||
113 | }) | ||
114 | } | ||
115 | |||
116 | onModalDismiss () { | ||
117 | this.isModalOpened = false | ||
118 | } | ||
119 | |||
120 | dismissOtherModals () { | ||
121 | this.modalService.dismissAll() | ||
122 | } | ||
123 | |||
88 | private updateChildLabels (path: string) { | 124 | private updateChildLabels (path: string) { |
89 | this.suffixLabels = {} | 125 | this.suffixLabels = {} |
90 | 126 | ||