"webpack-cli": "^3.0.8",
"webtorrent": "^0.102.1",
"whatwg-fetch": "^2.0.4",
- "zone.js": "~0.8.5"
+ "zone.js": "~0.8.5",
+ "focus-visible": "^4.1.5"
}
}
<div class="sub-header-container">
<my-menu *ngIf="isMenuDisplayed"></my-menu>
- <div id="right-container" class="main-col container-fluid" [ngClass]="{ expanded: isMenuDisplayed === false }">
+ <div id="content" tabindex="-1" class="main-col container-fluid" [ngClass]="{ expanded: isMenuDisplayed === false }">
<div class="main-row">
<router-outlet></router-outlet>
import { MetaLoader, MetaModule, MetaStaticLoader, PageTitlePositioning } from '@ngx-meta/core'
import { ClipboardModule } from 'ngx-clipboard'
import { HotkeyModule, IHotkeyOptions } from 'angular2-hotkeys'
+import 'focus-visible'
import { AppRoutingModule } from './app-routing.module'
import { AppComponent } from './app.component'
<div class="footer d-flex justify-content-between">
<span class="language">
- <span (click)="openLanguageChooser()" i18n-title title="Change the language" class="icon icon-language"></span>
+ <span tabindex="0" (keyup.enter)="openLanguageChooser()" (click)="openLanguageChooser()" i18n-title title="Change the language" class="icon icon-language"></span>
</span>
<span class="color-palette">
- <span (click)="toggleDarkTheme()" i18n-title title="Toggle dark interface" class="icon icon-moonsun"></span>
+ <span tabindex="0" (keyup.enter)="toggleDarkTheme()" (click)="toggleDarkTheme()" i18n-title title="Toggle dark interface" class="icon icon-moonsun"></span>
</span>
</div>
</menu>
transition: background-color .1s ease-in-out;
@include disable-default-a-behaviour;
- &:hover {
+ &:hover, &.focus-visible {
background-color: rgba(255, 255, 255, 0.15);
}
font-weight: $font-semibold;
.icon {
+ @include disable-outline;
@include icon(28px);
opacity: 0.9;
<my-video-thumbnail [video]="result"></my-video-thumbnail>
<div class="video-info">
- <a class="video-info-name" [routerLink]="['/videos/watch', result.uuid]" [attr.title]="result.name">{{ result.name }}</a>
+ <a tabindex="-1" class="video-info-name" [routerLink]="['/videos/watch', result.uuid]" [attr.title]="result.name">{{ result.name }}</a>
<span i18n class="video-info-date-views">{{ result.publishedAt | myFromNow }} - {{ result.views | myNumberFormatter }} views</span>
- <a class="video-info-account" [routerLink]="[ '/accounts', result.byAccount ]">{{ result.byAccount }}</a>
+ <a tabindex="-1" class="video-info-account" [routerLink]="[ '/accounts', result.byAccount ]">{{ result.byAccount }}</a>
</div>
</div>
</ng-container>
<div class="video-miniature-information">
<a
+ tabindex="-1"
class="video-miniature-name"
[routerLink]="[ '/videos/watch', video.uuid ]" [attr.title]="video.name" [ngClass]="{ 'blur-filter': isVideoBlur() }"
>
<span i18n class="video-miniature-created-at-views">{{ video.publishedAt | myFromNow }} - {{ video.views | myNumberFormatter }} views</span>
- <a *ngIf="displayOwnerAccount()" class="video-miniature-account" [routerLink]="[ '/accounts', video.byAccount ]">
+ <a tabindex="-1" *ngIf="displayOwnerAccount()" class="video-miniature-account" [routerLink]="[ '/accounts', video.byAccount ]">
{{ video.byAccount }}
</a>
- <a *ngIf="displayOwnerVideoChannel()" class="video-miniature-channel" [routerLink]="[ '/video-channels', video.byVideoChannel ]">
+ <a tabindex="-1" *ngIf="displayOwnerVideoChannel()" class="video-miniature-channel" [routerLink]="[ '/video-channels', video.byVideoChannel ]">
{{ video.byVideoChannel }}
</a>
</div>
text-decoration: none !important;
}
+ @include disable-outline;
+ &.focus-visible {
+ box-shadow: 0 0 0 2px var(--mainColor);
+ }
+
img {
width: $video-thumbnail-width;
height: $video-thumbnail-height;
margin-bottom: 20px;
a {
- @include disable-default-a-behaviour;
+ &:hover, &:focus:not(.focus-visible), &:active {
+ text-decoration: none;
+ outline: none;
+ }
color: var(--mainForegroundColor);
}
}
@mixin disable-outline {
- outline: none;
+ &:focus:not(.focus-visible) {
+ outline: none;
+ }
&::-moz-focus-inner {
border: 0;
version "2.1.3"
resolved "https://registry.yarnpkg.com/@angularclass/hmr/-/hmr-2.1.3.tgz#34e658ed3da37f23b0a200e2da5a89be92bb209f"
-"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.0.0-beta.35":
+"@babel/code-frame@^7.0.0-beta.35":
version "7.0.0"
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0.tgz#06e2ab19bdb535385559aabb5ba59729482800f8"
dependencies:
"@babel/highlight" "^7.0.0"
-"@babel/helper-module-imports@^7.0.0":
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz#96081b7111e486da4d2cd971ad1a4fe216cc2e3d"
- dependencies:
- "@babel/types" "^7.0.0"
-
-"@babel/helper-module-transforms@^7.0.0":
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.0.0.tgz#b01ee7d543e81e8c3fc404b19c9f26acb6e4cf4c"
- dependencies:
- "@babel/helper-module-imports" "^7.0.0"
- "@babel/helper-simple-access" "^7.0.0"
- "@babel/helper-split-export-declaration" "^7.0.0"
- "@babel/template" "^7.0.0"
- "@babel/types" "^7.0.0"
- lodash "^4.17.10"
-
-"@babel/helper-plugin-utils@^7.0.0":
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz#bbb3fbee98661c569034237cc03967ba99b4f250"
-
-"@babel/helper-simple-access@^7.0.0":
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.0.0.tgz#ff36a27983ae4c27122da2f7f294dced80ecbd08"
- dependencies:
- "@babel/template" "^7.0.0"
- "@babel/types" "^7.0.0"
-
-"@babel/helper-split-export-declaration@^7.0.0":
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0.tgz#3aae285c0311c2ab095d997b8c9a94cad547d813"
- dependencies:
- "@babel/types" "^7.0.0"
-
"@babel/highlight@^7.0.0":
version "7.0.0"
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0.tgz#f710c38c8d458e6dd9a201afb637fcb781ce99e4"
esutils "^2.0.2"
js-tokens "^4.0.0"
-"@babel/parser@^7.0.0":
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.0.0.tgz#697655183394facffb063437ddf52c0277698775"
-
-"@babel/plugin-transform-modules-commonjs@^7.0.0":
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.0.0.tgz#20b906e5ab130dd8e456b694a94d9575da0fd41f"
- dependencies:
- "@babel/helper-module-transforms" "^7.0.0"
- "@babel/helper-plugin-utils" "^7.0.0"
- "@babel/helper-simple-access" "^7.0.0"
-
-"@babel/template@^7.0.0":
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.0.0.tgz#c2bc9870405959c89a9c814376a2ecb247838c80"
- dependencies:
- "@babel/code-frame" "^7.0.0"
- "@babel/parser" "^7.0.0"
- "@babel/types" "^7.0.0"
-
-"@babel/types@^7.0.0":
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.0.0.tgz#6e191793d3c854d19c6749989e3bc55f0e962118"
- dependencies:
- esutils "^2.0.2"
- lodash "^4.17.10"
- to-fast-properties "^2.0.0"
-
"@neos21/bootstrap3-glyphicons@^1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@neos21/bootstrap3-glyphicons/-/bootstrap3-glyphicons-1.0.1.tgz#e5eeec43e0153d4b51effd9ecb58cdf7029924d7"
inherits "^2.0.1"
readable-stream "^2.0.4"
+focus-visible@^4.1.5:
+ version "4.1.5"
+ resolved "https://registry.yarnpkg.com/focus-visible/-/focus-visible-4.1.5.tgz#50b44e2e84c24b831ceca3cce84d57c2b311c855"
+
follow-redirects@^1.0.0:
version "1.5.1"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.1.tgz#67a8f14f5a1f67f962c2c46469c79eaec0a90291"
version "1.0.3"
resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47"
-to-fast-properties@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
-
to-object-path@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af"
const videoChannel = await VideoChannelModel.loadAndPopulateAccount(channelId)
if (videoChannel === null) {
res.status(400)
- .json({ error: 'Unknown video video channel on this instance.' })
+ .json({ error: 'Unknown video `video channel` on this instance.' })
.end()
return false
const videoChannel = await VideoChannelModel.loadByIdAndAccount(channelId, user.Account.id)
if (videoChannel === null) {
res.status(400)
- .json({ error: 'Unknown video video channel for this account.' })
+ .json({ error: 'Unknown video `video channel` for this account.' })
.end()
return false