add keyboard navigation for video actions (#2854)
Co-authored-by: Rigel Kent <sendmemail@rigelk.eu>
This commit is contained in:
parent
45800f7e63
commit
adcf921271
|
@ -12,7 +12,7 @@
|
|||
|
||||
<div class="result-title" *ngIf="!isSearching">
|
||||
<ng-container *ngIf="!search">
|
||||
<my-global-icon iconName="trending"></my-global-icon>
|
||||
<my-global-icon iconName="trending" aria-hidden="true"></my-global-icon>
|
||||
<ng-container i18n>Popular</ng-container>
|
||||
</ng-container>
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<div class="dropdown-root" ngbDropdown [placement]="placement" [container]="container" *ngIf="areActionsDisplayed(actions, entry)">
|
||||
<div
|
||||
<button
|
||||
class="action-button" [ngClass]="{ small: buttonSize === 'small', grey: theme === 'grey', orange: theme === 'orange', 'button-styled': buttonStyled }"
|
||||
ngbDropdownToggle role="button"
|
||||
>
|
||||
|
@ -7,7 +7,7 @@
|
|||
<my-global-icon *ngIf="!label && buttonDirection === 'vertical'" class="more-icon" iconName="more-vertical"></my-global-icon>
|
||||
|
||||
<span *ngIf="label" class="dropdown-toggle">{{ label }}</span>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<div ngbDropdownMenu class="dropdown-menu">
|
||||
<ng-container *ngFor="let actions of getActions()">
|
||||
|
@ -16,7 +16,7 @@
|
|||
<ng-container *ngIf="action.isDisplayed === undefined || action.isDisplayed(entry) === true">
|
||||
|
||||
<ng-template #templateActionLabel let-action>
|
||||
<my-global-icon *ngIf="action.iconName" [iconName]="action.iconName" [ngClass]="'icon-' + action.iconName"></my-global-icon>
|
||||
<my-global-icon *ngIf="action.iconName" [iconName]="action.iconName" [ngClass]="'icon-' + action.iconName" aria-hidden="true"></my-global-icon>
|
||||
|
||||
<div class="d-flex flex-column">
|
||||
<span i18n>{{ action.label }}</span>
|
||||
|
@ -33,14 +33,14 @@
|
|||
|
||||
<span
|
||||
*ngIf="!action.linkBuilder && !action.isHeader" [ngClass]="{ 'with-icon': !!action.iconName }"
|
||||
class="custom-action dropdown-item" role="button" [title]="action.title || ''" (click)="action.handler(entry)"
|
||||
class="custom-action dropdown-item" tabindex="0" role="button" [title]="action.title || ''" (click)="action.handler(entry)" (keyup.enter)="action.handler(entry)"
|
||||
>
|
||||
<ng-container *ngTemplateOutlet="templateActionLabel; context:{ $implicit: action }"></ng-container>
|
||||
</span>
|
||||
|
||||
<h6
|
||||
*ngIf="!action.linkBuilder && action.isHeader" [ngClass]="{ 'with-icon': !!action.iconName }"
|
||||
class="dropdown-header" role="button" [title]="action.title || ''" (click)="action.handler(entry)"
|
||||
class="dropdown-header" tabindex="0" role="button" [title]="action.title || ''" (click)="action.handler(entry)" (keyup.enter)="action.handler(entry)"
|
||||
>
|
||||
<ng-container *ngTemplateOutlet="templateActionLabel; context:{ $implicit: action }"></ng-container>
|
||||
</h6>
|
||||
|
|
|
@ -7,10 +7,12 @@
|
|||
height: $avatar-size;
|
||||
position: relative;
|
||||
margin-right: 5px;
|
||||
margin-bottom: 5px;
|
||||
|
||||
&.avatar-sm {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
|
||||
a {
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
<div ngbDropdownMenu>
|
||||
<a *ngFor="let menuChild of menuEntry.children" class="dropdown-item" [ngClass]="{ icon: hasIcons }" [routerLink]="menuChild.routerLink">
|
||||
<my-global-icon *ngIf="menuChild.iconName" [iconName]="menuChild.iconName"></my-global-icon>
|
||||
<my-global-icon *ngIf="menuChild.iconName" [iconName]="menuChild.iconName" aria-hidden="true"></my-global-icon>
|
||||
|
||||
{{ menuChild.label }}
|
||||
</a>
|
||||
|
@ -40,7 +40,7 @@
|
|||
<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>
|
||||
<my-global-icon *ngIf="menuChild.iconName" [iconName]="menuChild.iconName" aria-hidden="true"></my-global-icon>
|
||||
|
||||
{{ menuChild.label }}
|
||||
</a>
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
</ng-template>
|
||||
|
||||
<ng-template #noVideo>
|
||||
<my-global-icon iconName="alert"></my-global-icon>
|
||||
<my-global-icon iconName="alert" aria-hidden="true"></my-global-icon>
|
||||
|
||||
<div class="message" i18n>
|
||||
The notification concerns a video now unavailable
|
||||
|
@ -27,7 +27,7 @@
|
|||
</ng-container>
|
||||
|
||||
<ng-container *ngSwitchCase="UserNotificationType.UNBLACKLIST_ON_MY_VIDEO">
|
||||
<my-global-icon iconName="undo"></my-global-icon>
|
||||
<my-global-icon iconName="undo" aria-hidden="true"></my-global-icon>
|
||||
|
||||
<div class="message" i18n>
|
||||
Your video <a (click)="markAsRead(notification)" [routerLink]="notification.videoUrl">{{ notification.video.name }}</a> has been unblocked
|
||||
|
@ -35,7 +35,7 @@
|
|||
</ng-container>
|
||||
|
||||
<ng-container *ngSwitchCase="UserNotificationType.BLACKLIST_ON_MY_VIDEO">
|
||||
<my-global-icon iconName="no"></my-global-icon>
|
||||
<my-global-icon iconName="no" aria-hidden="true"></my-global-icon>
|
||||
|
||||
<div class="message" i18n>
|
||||
Your video <a (click)="markAsRead(notification)" [routerLink]="notification.videoUrl">{{ notification.videoBlacklist.video.name }}</a> has been blocked
|
||||
|
@ -43,7 +43,7 @@
|
|||
</ng-container>
|
||||
|
||||
<ng-container *ngSwitchCase="UserNotificationType.NEW_VIDEO_ABUSE_FOR_MODERATORS">
|
||||
<my-global-icon iconName="alert"></my-global-icon>
|
||||
<my-global-icon iconName="alert" aria-hidden="true"></my-global-icon>
|
||||
|
||||
<div class="message" i18n>
|
||||
<a (click)="markAsRead(notification)" [routerLink]="notification.videoAbuseUrl">A new video abuse</a> has been created on video <a (click)="markAsRead(notification)" [routerLink]="notification.videoUrl">{{ notification.videoAbuse.video.name }}</a>
|
||||
|
@ -51,7 +51,7 @@
|
|||
</ng-container>
|
||||
|
||||
<ng-container *ngSwitchCase="UserNotificationType.VIDEO_AUTO_BLACKLIST_FOR_MODERATORS">
|
||||
<my-global-icon iconName="no"></my-global-icon>
|
||||
<my-global-icon iconName="no" aria-hidden="true"></my-global-icon>
|
||||
|
||||
<div class="message" i18n>
|
||||
The recently added video <a (click)="markAsRead(notification)" [routerLink]="notification.videoUrl">{{ notification.videoBlacklist.video.name }}</a> has been <a (click)="markAsRead(notification)" [routerLink]="notification.videoAutoBlacklistUrl">automatically blocked</a>
|
||||
|
@ -72,7 +72,7 @@
|
|||
</ng-template>
|
||||
|
||||
<ng-template #noComment>
|
||||
<my-global-icon iconName="alert"></my-global-icon>
|
||||
<my-global-icon iconName="alert" aria-hidden="true"></my-global-icon>
|
||||
|
||||
<div class="message" i18n>
|
||||
The notification concerns a comment now unavailable
|
||||
|
@ -105,7 +105,7 @@
|
|||
</ng-container>
|
||||
|
||||
<ng-container *ngSwitchCase="UserNotificationType.NEW_USER_REGISTRATION">
|
||||
<my-global-icon iconName="user-add"></my-global-icon>
|
||||
<my-global-icon iconName="user-add" aria-hidden="true"></my-global-icon>
|
||||
|
||||
<div class="message" i18n>
|
||||
User <a (click)="markAsRead(notification)" [routerLink]="notification.accountUrl">{{ notification.account.name }}</a> registered on your instance
|
||||
|
@ -136,7 +136,7 @@
|
|||
</ng-container>
|
||||
|
||||
<ng-container *ngSwitchCase="UserNotificationType.NEW_INSTANCE_FOLLOWER">
|
||||
<my-global-icon iconName="users"></my-global-icon>
|
||||
<my-global-icon iconName="users" aria-hidden="true"></my-global-icon>
|
||||
|
||||
<div class="message" i18n>
|
||||
Your instance has <a (click)="markAsRead(notification)" [routerLink]="notification.instanceFollowUrl">a new follower</a> ({{ notification.actorFollow?.follower.host }})
|
||||
|
@ -145,7 +145,7 @@
|
|||
</ng-container>
|
||||
|
||||
<ng-container *ngSwitchCase="UserNotificationType.AUTO_INSTANCE_FOLLOWING">
|
||||
<my-global-icon iconName="users"></my-global-icon>
|
||||
<my-global-icon iconName="users" aria-hidden="true"></my-global-icon>
|
||||
|
||||
<div class="message" i18n>
|
||||
Your instance automatically followed <a (click)="markAsRead(notification)" [routerLink]="notification.instanceFollowUrl">{{ notification.actorFollow.following.host }}</a>
|
||||
|
@ -153,7 +153,7 @@
|
|||
</ng-container>
|
||||
|
||||
<ng-container *ngSwitchDefault>
|
||||
<my-global-icon iconName="alert"></my-global-icon>
|
||||
<my-global-icon iconName="alert" aria-hidden="true"></my-global-icon>
|
||||
|
||||
<div class="message" i18n>
|
||||
The notification points to a content now unavailable
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
<div class="action-block" *ngIf="actions.length > 0">
|
||||
<a [routerLink]="action.routerLink" routerLinkActive="active" *ngFor="let action of actions">
|
||||
<button class="btn">
|
||||
<my-global-icon [iconName]="action.iconName"></my-global-icon>
|
||||
<my-global-icon [iconName]="action.iconName" aria-hidden="true"></my-global-icon>
|
||||
<span>{{ action.label }}</span>
|
||||
</button>
|
||||
</a>
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
<div class="video-bottom">
|
||||
<div class="video-miniature-information">
|
||||
<div class="d-inline-flex">
|
||||
<div class="d-inline-flex video-miniature-meta">
|
||||
<div *ngIf="displayOptions.avatar" class="avatar">
|
||||
<img [src]="getAvatarUrl()" alt="Avatar" />
|
||||
</div>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
@import '_mixins';
|
||||
@import '_miniature';
|
||||
|
||||
$more-button-width: 41px;
|
||||
$more-button-width: 40px;
|
||||
$more-margin-right: 15px;
|
||||
|
||||
.video-miniature {
|
||||
|
@ -11,7 +11,6 @@ $more-margin-right: 15px;
|
|||
padding-bottom: $video-miniature-margin-bottom;
|
||||
height: 195px;
|
||||
vertical-align: top;
|
||||
overflow: hidden;
|
||||
|
||||
.video-bottom {
|
||||
display: flex;
|
||||
|
@ -32,6 +31,11 @@ $more-margin-right: 15px;
|
|||
@include miniature-name;
|
||||
}
|
||||
|
||||
.video-miniature-meta {
|
||||
width: calc(100% + #{$more-button-width});
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.video-miniature-created-at-views {
|
||||
display: block;
|
||||
font-size: 13px;
|
||||
|
@ -122,7 +126,7 @@ $more-margin-right: 15px;
|
|||
width: 100% !important;
|
||||
|
||||
.video-miniature-information {
|
||||
width: calc(100% - 40px) !important;
|
||||
width: calc(100% - #{$more-button-width}) !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<div *ngIf="!hasImportedVideo" class="upload-video-container" dragDrop (fileDropped)="setTorrentFile($event)">
|
||||
<div class="first-step-block">
|
||||
<my-global-icon class="upload-icon" iconName="upload"></my-global-icon>
|
||||
<my-global-icon class="upload-icon" iconName="upload" aria-hidden="true"></my-global-icon>
|
||||
|
||||
<div class="button-file form-control" [ngbTooltip]="'(extensions: .torrent)'">
|
||||
<span i18n>Select the torrent to import</span>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<div *ngIf="!hasImportedVideo" class="upload-video-container">
|
||||
<div class="first-step-block">
|
||||
<my-global-icon class="upload-icon" iconName="upload"></my-global-icon>
|
||||
<my-global-icon class="upload-icon" iconName="upload" aria-hidden="true"></my-global-icon>
|
||||
|
||||
<div class="form-group">
|
||||
<label i18n for="targetUrl">URL</label>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<div *ngIf="!isUploadingVideo" class="upload-video-container" dragDrop (fileDropped)="setVideoFile($event)">
|
||||
<div class="first-step-block">
|
||||
<my-global-icon class="upload-icon" iconName="upload"></my-global-icon>
|
||||
<my-global-icon class="upload-icon" iconName="upload" aria-hidden="true"></my-global-icon>
|
||||
|
||||
<div class="button-file form-control" [ngbTooltip]="'(extensions: ' + videoExtensions + ')'">
|
||||
<span i18n>Select the file to upload</span>
|
||||
|
|
|
@ -59,38 +59,38 @@
|
|||
|
||||
<div class="video-actions-rates">
|
||||
<div class="video-actions fullWidth justify-content-end">
|
||||
<div
|
||||
[ngbPopover]="getRatePopoverText()" [ngClass]="{ 'activated': userRating === 'like' }" (click)="setLike()"
|
||||
class="action-button action-button-like" role="button" [attr.aria-pressed]="userRating === 'like'"
|
||||
<button
|
||||
[ngbPopover]="getRatePopoverText()" [ngClass]="{ 'activated': userRating === 'like' }" (click)="setLike()" (keyup.enter)="setLike()"
|
||||
class="action-button action-button-like" [attr.aria-pressed]="userRating === 'like'" [attr.aria-label]="tooltipLike"
|
||||
[ngbTooltip]="tooltipLike"
|
||||
placement="bottom auto"
|
||||
>
|
||||
<my-global-icon iconName="like"></my-global-icon>
|
||||
<span *ngIf="video.likes" class="count">{{ video.likes }}</span>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<div
|
||||
[ngbPopover]="getRatePopoverText()" [ngClass]="{ 'activated': userRating === 'dislike' }" (click)="setDislike()"
|
||||
class="action-button action-button-dislike" role="button" [attr.aria-pressed]="userRating === 'dislike'"
|
||||
<button
|
||||
[ngbPopover]="getRatePopoverText()" [ngClass]="{ 'activated': userRating === 'dislike' }" (click)="setDislike()" (keyup.enter)="setDislike()"
|
||||
class="action-button action-button-dislike" [attr.aria-pressed]="userRating === 'dislike'" [attr.aria-label]="tooltipDislike"
|
||||
[ngbTooltip]="tooltipDislike"
|
||||
placement="bottom auto"
|
||||
>
|
||||
<my-global-icon iconName="dislike"></my-global-icon>
|
||||
<span *ngIf="video.dislikes" class="count">{{ video.dislikes }}</span>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<div *ngIf="video.support" (click)="showSupportModal()" class="action-button action-button-support"
|
||||
<button *ngIf="video.support" (click)="showSupportModal()" (keyup.enter)="showSupportModal()" class="action-button action-button-support" [attr.aria-label]="tooltipSupport"
|
||||
[ngbTooltip]="tooltipSupport"
|
||||
placement="bottom auto"
|
||||
>
|
||||
<my-global-icon iconName="support"></my-global-icon>
|
||||
<my-global-icon iconName="support" aria-hidden="true"></my-global-icon>
|
||||
<span class="icon-text" i18n>SUPPORT</span>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<div (click)="showShareModal()" class="action-button" role="button">
|
||||
<button (click)="showShareModal()" (keyup.enter)="showShareModal()" class="action-button">
|
||||
<my-global-icon iconName="share" aria-hidden="true"></my-global-icon>
|
||||
<span class="icon-text" i18n>SHARE</span>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<div
|
||||
class="action-dropdown" ngbDropdown placement="top" role="button" autoClose="outside"
|
||||
|
@ -98,10 +98,10 @@
|
|||
[ngbTooltip]="tooltipSaveToPlaylist"
|
||||
placement="bottom auto"
|
||||
>
|
||||
<div class="action-button action-button-save" ngbDropdownToggle role="button">
|
||||
<button class="action-button action-button-save" ngbDropdownToggle>
|
||||
<my-global-icon iconName="playlist-add" aria-hidden="true"></my-global-icon>
|
||||
<span class="icon-text" i18n>SAVE</span>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<div ngbDropdownMenu>
|
||||
<my-video-add-to-playlist #addContent [video]="video"></my-video-add-to-playlist>
|
||||
|
|
|
@ -86,6 +86,11 @@ input, textarea {
|
|||
color: pvar(--mainForegroundColor);
|
||||
}
|
||||
|
||||
button {
|
||||
background: unset;
|
||||
@include disable-outline;
|
||||
}
|
||||
|
||||
label {
|
||||
font-weight: $font-bold;
|
||||
font-size: 15px;
|
||||
|
|
Loading…
Reference in New Issue