Fix notification dropdown accessibility
This commit is contained in:
parent
8ce037b0c0
commit
fff5a323fd
|
@ -79,7 +79,7 @@
|
|||
</div>
|
||||
|
||||
@defer (when isLoggedIn) {
|
||||
<my-notification (navigate)="onActiveLinkScrollToAnchor($event)"></my-notification>
|
||||
<my-notification-dropdown (navigate)="onActiveLinkScrollToAnchor($event)"></my-notification-dropdown>
|
||||
}
|
||||
</div>
|
||||
|
||||
|
|
|
@ -116,7 +116,7 @@ nav {
|
|||
}
|
||||
}
|
||||
|
||||
my-notification {
|
||||
my-notification-dropdown {
|
||||
@include margin-left(auto);
|
||||
@include margin-right(15px);
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ import debug from 'debug'
|
|||
import { forkJoin, Subscription } from 'rxjs'
|
||||
import { first, switchMap } from 'rxjs/operators'
|
||||
import { LanguageChooserComponent } from './language-chooser.component'
|
||||
import { NotificationComponent } from './notification.component'
|
||||
import { NotificationDropdownComponent } from './notification-dropdown.component'
|
||||
import { QuickSettingsModalComponent } from './quick-settings-modal.component'
|
||||
|
||||
const debugLogger = debug('peertube:menu:MenuComponent')
|
||||
|
@ -39,7 +39,7 @@ const debugLogger = debug('peertube:menu:MenuComponent')
|
|||
standalone: true,
|
||||
imports: [
|
||||
CommonModule,
|
||||
NotificationComponent,
|
||||
NotificationDropdownComponent,
|
||||
ActorAvatarComponent,
|
||||
InputSwitchComponent,
|
||||
SignupLabelComponent,
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
<ng-template #notificationNumber>
|
||||
<div *ngIf="unreadNotifications > 0 && unreadNotifications < 100" class="unread-notifications">{{ unreadNotifications }}</div>
|
||||
<div *ngIf="unreadNotifications >= 100" class="unread-notifications">99+</div>
|
||||
</ng-template>
|
||||
|
||||
@if (isInMobileView) {
|
||||
<div i18n-title title="View your notifications" class="notification-inbox-link">
|
||||
<ng-container *ngTemplateOutlet="notificationNumber"></ng-container>
|
||||
|
||||
<a routerLink="/my-account/notifications" routerLinkActive="active" #link (click)="onNavigate(link)">
|
||||
<my-global-icon iconName="bell"></my-global-icon>
|
||||
</a>
|
||||
</div>
|
||||
} @else {
|
||||
<div
|
||||
ngbDropdown autoClose="outside" placement="bottom" container="body" dropdownClass="dropdown-notifications"
|
||||
#dropdown="ngbDropdown" (shown)="onDropdownShown()" (hidden)="onDropdownHidden()"
|
||||
>
|
||||
<button
|
||||
i18n-title title="View your notifications"
|
||||
class="border-0 text-start disable-dropdown-caret" [ngClass]="{ 'notification-inbox-dropdown': true, 'shown': opened, 'hidden': isInMobileView }"
|
||||
ngbDropdownToggle
|
||||
>
|
||||
<ng-container *ngTemplateOutlet="notificationNumber"></ng-container>
|
||||
|
||||
<my-global-icon iconName="bell"></my-global-icon>
|
||||
</button>
|
||||
|
||||
<div ngbDropdownMenu>
|
||||
<div class="content" [ngClass]="{ loaded: loaded }">
|
||||
<div class="notifications-header">
|
||||
<div i18n>Notifications</div>
|
||||
|
||||
<div>
|
||||
<button
|
||||
*ngIf="unreadNotifications"
|
||||
i18n-title title="Mark all as read" class="me-2"
|
||||
(click)="markAllAsRead()"
|
||||
>
|
||||
<my-global-icon iconName="tick"></my-global-icon>
|
||||
</button>
|
||||
|
||||
<a
|
||||
i18n-title title="Update your notification preferences"
|
||||
routerLink="/my-account/settings" fragment="notifications"
|
||||
#settingsNotifications (click)="onNavigate(settingsNotifications)"
|
||||
>
|
||||
<my-global-icon iconName="cog"></my-global-icon>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div *ngIf="!loaded" class="loader mt-4">
|
||||
<my-loader size="xl" [loading]="!loaded"></my-loader>
|
||||
</div>
|
||||
|
||||
<my-user-notifications
|
||||
[ignoreLoadingBar]="true" [infiniteScroll]="false" [itemsPerPage]="10"
|
||||
[markAllAsReadSubject]="markAllAsReadSubject" (notificationsLoaded)="onNotificationLoaded()"
|
||||
></my-user-notifications>
|
||||
|
||||
<a *ngIf="loaded" class="all-notifications" routerLink="/my-account/notifications" #notifications (click)="onNavigate(notifications)">
|
||||
<my-global-icon class="me-1" iconName="bell" aria-hidden="true"></my-global-icon>
|
||||
<span i18n>See all your notifications</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
}
|
|
@ -5,7 +5,7 @@
|
|||
scrollbar-color: auto;
|
||||
}
|
||||
|
||||
.notification-inbox-popover {
|
||||
.notification-inbox-dropdown {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,7 @@
|
|||
padding: 13px 10px;
|
||||
}
|
||||
|
||||
.notification-inbox-popover,
|
||||
.notification-inbox-dropdown,
|
||||
.notification-inbox-link a {
|
||||
transition: all .1s ease-in-out;
|
||||
border-radius: 25px;
|
||||
|
@ -33,7 +33,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
.notification-inbox-popover.shown,
|
||||
.notification-inbox-dropdown.shown,
|
||||
.notification-inbox-link a.active {
|
||||
background-color: rgba(255, 255, 255, 0.28);
|
||||
box-shadow: inset 0 3px 5px rgba(0, 0, 0, .325);
|
||||
|
@ -41,21 +41,17 @@
|
|||
@include apply-svg-color(#fff);
|
||||
}
|
||||
|
||||
.notification-inbox-popover.hidden {
|
||||
.notification-inbox-dropdown.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
::ng-deep {
|
||||
.popover-notifications.popover {
|
||||
.dropdown-notifications {
|
||||
max-width: none;
|
||||
top: -6px !important;
|
||||
left: 7px !important;
|
||||
|
||||
.arrow {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.popover-body {
|
||||
.dropdown-menu {
|
||||
padding: 0;
|
||||
font-size: 14px;
|
||||
font-family: $main-fonts;
|
||||
|
@ -130,20 +126,23 @@
|
|||
}
|
||||
|
||||
.all-notifications {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.1);
|
||||
margin-top: -1px; // To not have 2 borders with the last notification
|
||||
text-align: center;
|
||||
font-weight: $font-semibold;
|
||||
color: pvar(--mainForegroundColor);
|
||||
padding: 7px 0;
|
||||
margin-top: auto;
|
||||
text-decoration: none;
|
||||
padding: 0.75rem 0;
|
||||
text-decoration: underline !important;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.85;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.notification-inbox-popover,
|
||||
.notification-inbox-dropdown,
|
||||
.notification-inbox-link {
|
||||
cursor: pointer;
|
||||
position: relative;
|
|
@ -6,14 +6,14 @@ import { GlobalIconComponent } from '@app/shared/shared-icons/global-icon.compon
|
|||
import { LoaderComponent } from '@app/shared/shared-main/loaders/loader.component'
|
||||
import { UserNotificationService } from '@app/shared/shared-main/users/user-notification.service'
|
||||
import { UserNotificationsComponent } from '@app/shared/standalone-notifications/user-notifications.component'
|
||||
import { NgbPopover, NgbPopoverModule } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { NgbDropdown, NgbDropdownModule, NgbPopoverModule } from '@ng-bootstrap/ng-bootstrap'
|
||||
import { Subject, Subscription } from 'rxjs'
|
||||
import { filter } from 'rxjs/operators'
|
||||
|
||||
@Component({
|
||||
selector: 'my-notification',
|
||||
templateUrl: './notification.component.html',
|
||||
styleUrls: [ './notification.component.scss' ],
|
||||
selector: 'my-notification-dropdown',
|
||||
templateUrl: './notification-dropdown.component.html',
|
||||
styleUrls: [ './notification-dropdown.component.scss' ],
|
||||
standalone: true,
|
||||
imports: [
|
||||
CommonModule,
|
||||
|
@ -22,11 +22,12 @@ import { filter } from 'rxjs/operators'
|
|||
GlobalIconComponent,
|
||||
LoaderComponent,
|
||||
RouterLink,
|
||||
RouterLinkActive
|
||||
RouterLinkActive,
|
||||
NgbDropdownModule
|
||||
]
|
||||
})
|
||||
export class NotificationComponent implements OnInit, OnDestroy {
|
||||
@ViewChild('popover', { static: true }) popover: NgbPopover
|
||||
export class NotificationDropdownComponent implements OnInit, OnDestroy {
|
||||
@ViewChild('dropdown', { static: false }) dropdown: NgbDropdown
|
||||
|
||||
@Output() navigate = new EventEmitter<HTMLAnchorElement>()
|
||||
|
||||
|
@ -61,7 +62,7 @@ export class NotificationComponent implements OnInit, OnDestroy {
|
|||
|
||||
this.routeSub = this.router.events
|
||||
.pipe(filter(event => event instanceof NavigationEnd))
|
||||
.subscribe(() => this.closePopover())
|
||||
.subscribe(() => this.closeDropdown())
|
||||
}
|
||||
|
||||
ngOnDestroy () {
|
||||
|
@ -73,29 +74,17 @@ export class NotificationComponent implements OnInit, OnDestroy {
|
|||
return this.screenService.isInMobileView()
|
||||
}
|
||||
|
||||
closePopover () {
|
||||
this.popover.close()
|
||||
closeDropdown () {
|
||||
if (this.dropdown) this.dropdown.close()
|
||||
}
|
||||
|
||||
onPopoverShown () {
|
||||
onDropdownShown () {
|
||||
this.opened = true
|
||||
|
||||
document.querySelector('nav').scrollTo(0, 0) // Reset menu scroll to easy lock
|
||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||
document.querySelector('nav').addEventListener('scroll', this.onMenuScrollEvent)
|
||||
}
|
||||
|
||||
onPopoverHidden () {
|
||||
onDropdownHidden () {
|
||||
this.loaded = false
|
||||
this.opened = false
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||
document.querySelector('nav').removeEventListener('scroll', this.onMenuScrollEvent)
|
||||
}
|
||||
|
||||
// Lock menu scroll when menu scroll to avoid fleeing / detached dropdown
|
||||
onMenuScrollEvent () {
|
||||
document.querySelector('nav').scrollTo(0, 0)
|
||||
}
|
||||
|
||||
onNotificationLoaded () {
|
||||
|
@ -103,7 +92,7 @@ export class NotificationComponent implements OnInit, OnDestroy {
|
|||
}
|
||||
|
||||
onNavigate (link: HTMLAnchorElement) {
|
||||
this.closePopover()
|
||||
this.closeDropdown()
|
||||
this.navigate.emit(link)
|
||||
}
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
<ng-template #notificationNumber>
|
||||
<div *ngIf="unreadNotifications > 0 && unreadNotifications < 100" class="unread-notifications">{{ unreadNotifications }}</div>
|
||||
<div *ngIf="unreadNotifications >= 100" class="unread-notifications">99+</div>
|
||||
</ng-template>
|
||||
|
||||
<button
|
||||
[ngbPopover]="popContent" autoClose="outside" placement="bottom" container="body" popoverClass="popover-notifications"
|
||||
i18n-title title="View your notifications"
|
||||
class="border-0 text-start" [ngClass]="{ 'notification-inbox-popover': true, 'shown': opened, 'hidden': isInMobileView }"
|
||||
#popover="ngbPopover" (shown)="onPopoverShown()" (hidden)="onPopoverHidden()"
|
||||
>
|
||||
<ng-container *ngTemplateOutlet="notificationNumber"></ng-container>
|
||||
|
||||
<my-global-icon iconName="bell"></my-global-icon>
|
||||
</button>
|
||||
|
||||
<div *ngIf="isInMobileView" i18n-title title="View your notifications" class="notification-inbox-link">
|
||||
<ng-container *ngTemplateOutlet="notificationNumber"></ng-container>
|
||||
|
||||
<a routerLink="/my-account/notifications" routerLinkActive="active" #link (click)="onNavigate(link)">
|
||||
<my-global-icon iconName="bell"></my-global-icon>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<ng-template #popContent>
|
||||
<div class="content" [ngClass]="{ loaded: loaded }">
|
||||
<div class="notifications-header">
|
||||
<div i18n>Notifications</div>
|
||||
|
||||
<div>
|
||||
<button
|
||||
*ngIf="unreadNotifications"
|
||||
i18n-title title="Mark all as read" class="me-2"
|
||||
(click)="markAllAsRead()"
|
||||
>
|
||||
<my-global-icon iconName="tick"></my-global-icon>
|
||||
</button>
|
||||
|
||||
<a
|
||||
i18n-title title="Update your notification preferences"
|
||||
routerLink="/my-account/settings" fragment="notifications"
|
||||
#settingsNotifications (click)="onNavigate(settingsNotifications)"
|
||||
>
|
||||
<my-global-icon iconName="cog"></my-global-icon>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div *ngIf="!loaded" class="loader mt-4">
|
||||
<my-loader size="xl" [loading]="!loaded"></my-loader>
|
||||
</div>
|
||||
|
||||
<my-user-notifications
|
||||
[ignoreLoadingBar]="true" [infiniteScroll]="false" [itemsPerPage]="10"
|
||||
[markAllAsReadSubject]="markAllAsReadSubject" (notificationsLoaded)="onNotificationLoaded()"
|
||||
></my-user-notifications>
|
||||
|
||||
<a *ngIf="loaded" class="all-notifications" routerLink="/my-account/notifications" #notifications (click)="onNavigate(notifications)">
|
||||
<my-global-icon class="me-1" iconName="bell" aria-hidden="true"></my-global-icon>
|
||||
<span i18n>See all your notifications</span>
|
||||
</a>
|
||||
</div>
|
||||
</ng-template>
|
|
@ -102,6 +102,10 @@ body {
|
|||
margin: 0.3rem 0;
|
||||
}
|
||||
|
||||
.disable-dropdown-caret::after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Alert
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
Loading…
Reference in New Issue