[PS-329] A11y: make view, copy, etc controls for ciphers/items keyboard focusable/operable, add screen reader improvements (#2507)
This commit is contained in:
parent
17c3fdd68b
commit
9df22d3601
|
@ -1,4 +1,5 @@
|
||||||
<span
|
<button
|
||||||
|
type="button"
|
||||||
class="row-btn"
|
class="row-btn"
|
||||||
(click)="view()"
|
(click)="view()"
|
||||||
appStopClick
|
appStopClick
|
||||||
|
@ -7,9 +8,10 @@
|
||||||
*ngIf="showView"
|
*ngIf="showView"
|
||||||
>
|
>
|
||||||
<i class="bwi bwi-lg bwi-list-alt" aria-hidden="true"></i>
|
<i class="bwi bwi-lg bwi-list-alt" aria-hidden="true"></i>
|
||||||
</span>
|
</button>
|
||||||
<ng-container *ngIf="cipher.type === cipherType.Login">
|
<ng-container *ngIf="cipher.type === cipherType.Login">
|
||||||
<span
|
<button
|
||||||
|
type="button"
|
||||||
class="row-btn"
|
class="row-btn"
|
||||||
appStopClick
|
appStopClick
|
||||||
appStopProp
|
appStopProp
|
||||||
|
@ -17,71 +19,84 @@
|
||||||
(click)="launchCipher()"
|
(click)="launchCipher()"
|
||||||
*ngIf="!showView"
|
*ngIf="!showView"
|
||||||
[ngClass]="{ disabled: !cipher.login.canLaunch }"
|
[ngClass]="{ disabled: !cipher.login.canLaunch }"
|
||||||
|
[attr.disabled]="!cipher.login.canLaunch ? '' : null"
|
||||||
>
|
>
|
||||||
<i class="bwi bwi-lg bwi-share-square" aria-hidden="true"></i>
|
<i class="bwi bwi-lg bwi-share-square" aria-hidden="true"></i>
|
||||||
</span>
|
</button>
|
||||||
<span
|
<button
|
||||||
|
type="button"
|
||||||
class="row-btn"
|
class="row-btn"
|
||||||
appStopClick
|
appStopClick
|
||||||
appStopProp
|
appStopProp
|
||||||
appA11yTitle="{{ 'copyUsername' | i18n }}"
|
appA11yTitle="{{ 'copyUsername' | i18n }}"
|
||||||
(click)="copy(cipher, cipher.login.username, 'username', 'Username')"
|
(click)="copy(cipher, cipher.login.username, 'username', 'Username')"
|
||||||
[ngClass]="{ disabled: !cipher.login.username }"
|
[ngClass]="{ disabled: !cipher.login.username }"
|
||||||
|
[attr.disabled]="!cipher.login.username ? '' : null"
|
||||||
>
|
>
|
||||||
<i class="bwi bwi-lg bwi-user" aria-hidden="true"></i>
|
<i class="bwi bwi-lg bwi-user" aria-hidden="true"></i>
|
||||||
</span>
|
</button>
|
||||||
<span
|
<button
|
||||||
|
type="button"
|
||||||
class="row-btn"
|
class="row-btn"
|
||||||
appStopClick
|
appStopClick
|
||||||
appStopProp
|
appStopProp
|
||||||
appA11yTitle="{{ 'copyPassword' | i18n }}"
|
appA11yTitle="{{ 'copyPassword' | i18n }}"
|
||||||
(click)="copy(cipher, cipher.login.password, 'password', 'Password')"
|
(click)="copy(cipher, cipher.login.password, 'password', 'Password')"
|
||||||
[ngClass]="{ disabled: !cipher.login.password || !cipher.viewPassword }"
|
[ngClass]="{ disabled: !cipher.login.password || !cipher.viewPassword }"
|
||||||
|
[attr.disabled]="!cipher.login.password ? '' : null"
|
||||||
>
|
>
|
||||||
<i class="bwi bwi-lg bwi-key" aria-hidden="true"></i>
|
<i class="bwi bwi-lg bwi-key" aria-hidden="true"></i>
|
||||||
</span>
|
</button>
|
||||||
<span
|
<button
|
||||||
|
type="button"
|
||||||
class="row-btn"
|
class="row-btn"
|
||||||
appStopClick
|
appStopClick
|
||||||
appStopProp
|
appStopProp
|
||||||
appA11yTitle="{{ 'copyVerificationCode' | i18n }}"
|
appA11yTitle="{{ 'copyVerificationCode' | i18n }}"
|
||||||
(click)="copy(cipher, cipher.login.totp, 'verificationCodeTotp', 'TOTP')"
|
(click)="copy(cipher, cipher.login.totp, 'verificationCodeTotp', 'TOTP')"
|
||||||
[ngClass]="{ disabled: !displayTotpCopyButton(cipher) }"
|
[ngClass]="{ disabled: !displayTotpCopyButton(cipher) }"
|
||||||
|
[attr.disabled]="!displayTotpCopyButton(cipher) ? '' : null"
|
||||||
>
|
>
|
||||||
<i class="bwi bwi-lg bwi-clock" aria-hidden="true"></i>
|
<i class="bwi bwi-lg bwi-clock" aria-hidden="true"></i>
|
||||||
</span>
|
</button>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-container *ngIf="cipher.type === cipherType.Card">
|
<ng-container *ngIf="cipher.type === cipherType.Card">
|
||||||
<span
|
<button
|
||||||
|
type="button"
|
||||||
class="row-btn"
|
class="row-btn"
|
||||||
appStopClick
|
appStopClick
|
||||||
appStopProp
|
appStopProp
|
||||||
appA11yTitle="{{ 'copyNumber' | i18n }}"
|
appA11yTitle="{{ 'copyNumber' | i18n }}"
|
||||||
(click)="copy(cipher, cipher.card.number, 'number', 'Card Number')"
|
(click)="copy(cipher, cipher.card.number, 'number', 'Card Number')"
|
||||||
[ngClass]="{ disabled: !cipher.card.number }"
|
[ngClass]="{ disabled: !cipher.card.number }"
|
||||||
|
[attr.disabled]="!cipher.card.number ? '' : null"
|
||||||
>
|
>
|
||||||
<i class="bwi bwi-lg bwi-hashtag" aria-hidden="true"></i>
|
<i class="bwi bwi-lg bwi-hashtag" aria-hidden="true"></i>
|
||||||
</span>
|
</button>
|
||||||
<span
|
<button
|
||||||
|
type="button"
|
||||||
class="row-btn"
|
class="row-btn"
|
||||||
appStopClick
|
appStopClick
|
||||||
appStopProp
|
appStopProp
|
||||||
appA11yTitle="{{ 'copySecurityCode' | i18n }}"
|
appA11yTitle="{{ 'copySecurityCode' | i18n }}"
|
||||||
(click)="copy(cipher, cipher.card.code, 'securityCode', 'Security Code')"
|
(click)="copy(cipher, cipher.card.code, 'securityCode', 'Security Code')"
|
||||||
[ngClass]="{ disabled: !cipher.card.code }"
|
[ngClass]="{ disabled: !cipher.card.code }"
|
||||||
|
[attr.disabled]="!cipher.card.code ? '' : null"
|
||||||
>
|
>
|
||||||
<i class="bwi bwi-lg bwi-key" aria-hidden="true"></i>
|
<i class="bwi bwi-lg bwi-key" aria-hidden="true"></i>
|
||||||
</span>
|
</button>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-container *ngIf="cipher.type === cipherType.SecureNote">
|
<ng-container *ngIf="cipher.type === cipherType.SecureNote">
|
||||||
<span
|
<button
|
||||||
|
type="button"
|
||||||
class="row-btn"
|
class="row-btn"
|
||||||
appStopClick
|
appStopClick
|
||||||
appStopProp
|
appStopProp
|
||||||
appA11yTitle="{{ 'copyNote' | i18n }}"
|
appA11yTitle="{{ 'copyNote' | i18n }}"
|
||||||
(click)="copy(cipher, cipher.notes, 'note', 'Note')"
|
(click)="copy(cipher, cipher.notes, 'note', 'Note')"
|
||||||
[ngClass]="{ disabled: !cipher.notes }"
|
[ngClass]="{ disabled: !cipher.notes }"
|
||||||
|
[attr.disabled]="!cipher.notes ? '' : null"
|
||||||
>
|
>
|
||||||
<i class="bwi bwi-lg bwi-clone" aria-hidden="true"></i>
|
<i class="bwi bwi-lg bwi-clone" aria-hidden="true"></i>
|
||||||
</span>
|
</button>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
|
@ -1,13 +1,17 @@
|
||||||
<button
|
<div
|
||||||
type="button"
|
role="group"
|
||||||
(click)="selectCipher(cipher)"
|
appA11yTitle="{{ cipher.name }}"
|
||||||
(dblclick)="launchCipher(cipher)"
|
|
||||||
appStopClick
|
|
||||||
title="{{ title }} - {{ cipher.name }}"
|
|
||||||
class="box-content-row box-content-row-flex virtual-scroll-item"
|
class="box-content-row box-content-row-flex virtual-scroll-item"
|
||||||
[ngClass]="{ 'override-last': !last }"
|
[ngClass]="{ 'override-last': !last }"
|
||||||
>
|
>
|
||||||
<div class="row-main">
|
<button
|
||||||
|
type="button"
|
||||||
|
(click)="selectCipher(cipher)"
|
||||||
|
(dblclick)="launchCipher(cipher)"
|
||||||
|
appStopClick
|
||||||
|
title="{{ title }} - {{ cipher.name }}"
|
||||||
|
class="row-main"
|
||||||
|
>
|
||||||
<app-vault-icon [cipher]="cipher"></app-vault-icon>
|
<app-vault-icon [cipher]="cipher"></app-vault-icon>
|
||||||
<div class="row-main-content">
|
<div class="row-main-content">
|
||||||
<span class="text">
|
<span class="text">
|
||||||
|
@ -31,7 +35,7 @@
|
||||||
</span>
|
</span>
|
||||||
<span class="detail">{{ cipher.subTitle }}</span>
|
<span class="detail">{{ cipher.subTitle }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</button>
|
||||||
<app-action-buttons
|
<app-action-buttons
|
||||||
[cipher]="cipher"
|
[cipher]="cipher"
|
||||||
[showView]="showView"
|
[showView]="showView"
|
||||||
|
@ -40,4 +44,4 @@
|
||||||
class="action-buttons"
|
class="action-buttons"
|
||||||
>
|
>
|
||||||
</app-action-buttons>
|
</app-action-buttons>
|
||||||
</button>
|
</div>
|
||||||
|
|
|
@ -136,6 +136,7 @@
|
||||||
.row-main {
|
.row-main {
|
||||||
display: flex;
|
display: flex;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
|
align-items: normal;
|
||||||
|
|
||||||
.row-main-content {
|
.row-main-content {
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
|
@ -283,6 +284,7 @@
|
||||||
.text,
|
.text,
|
||||||
.detail {
|
.detail {
|
||||||
display: block;
|
display: block;
|
||||||
|
text-align: left;
|
||||||
|
|
||||||
@include themify($themes) {
|
@include themify($themes) {
|
||||||
color: themed("textColor");
|
color: themed("textColor");
|
||||||
|
|
Loading…
Reference in New Issue