1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-16 16:23:44 +00:00

[PM-16100][A11y][Extension] Usernames not being read by screen readers like they used to be (#13800)

* update autofill a11y

* fixes to cipher item title
This commit is contained in:
Jordan Aasen
2025-03-27 11:57:24 -07:00
committed by GitHub
parent 10695fd971
commit b2ad50b14d
6 changed files with 51 additions and 19 deletions

View File

@@ -4279,6 +4279,20 @@
} }
} }
}, },
"viewItemTitleWithField": {
"message": "View item - $ITEMNAME$ - $FIELD$",
"description": "Title for a link that opens a view for an item.",
"placeholders": {
"itemname": {
"content": "$1",
"example": "Secret Item"
},
"field": {
"content": "$2",
"example": "Username"
}
}
},
"autofillTitle": { "autofillTitle": {
"message": "Autofill - $ITEMNAME$", "message": "Autofill - $ITEMNAME$",
"description": "Title for a button that autofills a login item.", "description": "Title for a button that autofills a login item.",
@@ -4289,6 +4303,20 @@
} }
} }
}, },
"autofillTitleWithField": {
"message": "Autofill - $ITEMNAME$ - $FIELD$",
"description": "Title for a button that autofills a login item.",
"placeholders": {
"itemname": {
"content": "$1",
"example": "Secret Item"
},
"field": {
"content": "$2",
"example": "Username"
}
}
},
"copyFieldValue": { "copyFieldValue": {
"message": "Copy $FIELD$, $VALUE$", "message": "Copy $FIELD$, $VALUE$",
"description": "Title for a button that copies a field value to the clipboard.", "description": "Title for a button that copies a field value to the clipboard.",

View File

@@ -7,6 +7,6 @@
[description]="(showEmptyAutofillTip$ | async) ? ('autofillSuggestionsTip' | i18n) : null" [description]="(showEmptyAutofillTip$ | async) ? ('autofillSuggestionsTip' | i18n) : null"
showAutofillButton showAutofillButton
[disableDescriptionMargin]="showEmptyAutofillTip$ | async" [disableDescriptionMargin]="showEmptyAutofillTip$ | async"
[primaryActionAutofill]="clickItemsToAutofillVaultView" [primaryActionAutofill]="clickItemsToAutofillVaultView$ | async"
[groupByType]="groupByType()" [groupByType]="groupByType()"
></app-vault-list-items-container> ></app-vault-list-items-container>

View File

@@ -1,7 +1,7 @@
import { CommonModule } from "@angular/common"; import { CommonModule } from "@angular/common";
import { Component, OnInit } from "@angular/core"; import { Component } from "@angular/core";
import { toSignal } from "@angular/core/rxjs-interop"; import { toSignal } from "@angular/core/rxjs-interop";
import { combineLatest, firstValueFrom, map, Observable } from "rxjs"; import { combineLatest, map, Observable } from "rxjs";
import { JslibModule } from "@bitwarden/angular/jslib.module"; import { JslibModule } from "@bitwarden/angular/jslib.module";
import { VaultSettingsService } from "@bitwarden/common/vault/abstractions/vault-settings/vault-settings.service"; import { VaultSettingsService } from "@bitwarden/common/vault/abstractions/vault-settings/vault-settings.service";
@@ -33,7 +33,7 @@ import { VaultListItemsContainerComponent } from "../vault-list-items-container/
selector: "app-autofill-vault-list-items", selector: "app-autofill-vault-list-items",
templateUrl: "autofill-vault-list-items.component.html", templateUrl: "autofill-vault-list-items.component.html",
}) })
export class AutofillVaultListItemsComponent implements OnInit { export class AutofillVaultListItemsComponent {
/** /**
* The list of ciphers that can be used to autofill the current page. * The list of ciphers that can be used to autofill the current page.
* @protected * @protected
@@ -47,7 +47,9 @@ export class AutofillVaultListItemsComponent implements OnInit {
*/ */
protected showRefresh: boolean = BrowserPopupUtils.inSidebar(window); protected showRefresh: boolean = BrowserPopupUtils.inSidebar(window);
clickItemsToAutofillVaultView = false; /** Flag indicating whether the login item should automatically autofill when clicked */
protected clickItemsToAutofillVaultView$: Observable<boolean> =
this.vaultSettingsService.clickItemsToAutofillVaultView$;
protected groupByType = toSignal( protected groupByType = toSignal(
this.vaultPopupItemsService.hasFilterApplied$.pipe(map((hasFilter) => !hasFilter)), this.vaultPopupItemsService.hasFilterApplied$.pipe(map((hasFilter) => !hasFilter)),
@@ -84,12 +86,6 @@ export class AutofillVaultListItemsComponent implements OnInit {
// TODO: Migrate logic to show Autofill policy toast PM-8144 // TODO: Migrate logic to show Autofill policy toast PM-8144
} }
async ngOnInit() {
this.clickItemsToAutofillVaultView = await firstValueFrom(
this.vaultSettingsService.clickItemsToAutofillVaultView$,
);
}
/** /**
* Refreshes the current tab to re-populate the autofill ciphers. * Refreshes the current tab to re-populate the autofill ciphers.
* @protected * @protected

View File

@@ -99,7 +99,9 @@
type="button" type="button"
(click)="primaryActionOnSelect(cipher)" (click)="primaryActionOnSelect(cipher)"
(dblclick)="launchCipher(cipher)" (dblclick)="launchCipher(cipher)"
[appA11yTitle]="cipherItemTitleKey | async | i18n: cipher.name" [appA11yTitle]="
cipherItemTitleKey(cipher) | async | i18n: cipher.name : cipher.login.username
"
class="{{ itemHeightClass }}" class="{{ itemHeightClass }}"
> >
<div slot="start" class="tw-justify-start tw-w-7 tw-flex"> <div slot="start" class="tw-justify-start tw-w-7 tw-flex">

View File

@@ -206,11 +206,14 @@ export class VaultListItemsContainerComponent implements OnInit, AfterViewInit {
/** /**
* Resolved i18n key to use for suggested cipher items * Resolved i18n key to use for suggested cipher items
*/ */
cipherItemTitleKey = this.currentURIIsBlocked$.pipe( cipherItemTitleKey = (cipher: CipherView) =>
map((uriIsBlocked) => this.currentURIIsBlocked$.pipe(
this.primaryActionAutofill && !uriIsBlocked ? "autofillTitle" : "viewItemTitle", map((uriIsBlocked) => {
), const hasUsername = cipher.login?.username != null;
); const key = this.primaryActionAutofill && !uriIsBlocked ? "autofillTitle" : "viewItemTitle";
return hasUsername ? `${key}WithField` : key;
}),
);
/** /**
* Option to show the autofill button for each item. * Option to show the autofill button for each item.

View File

@@ -1,4 +1,4 @@
import { Observable, map } from "rxjs"; import { Observable, map, shareReplay } from "rxjs";
import { ActiveUserState, GlobalState, StateProvider } from "../../../platform/state"; import { ActiveUserState, GlobalState, StateProvider } from "../../../platform/state";
import { VaultSettingsService as VaultSettingsServiceAbstraction } from "../../abstractions/vault-settings/vault-settings.service"; import { VaultSettingsService as VaultSettingsServiceAbstraction } from "../../abstractions/vault-settings/vault-settings.service";
@@ -46,7 +46,10 @@ export class VaultSettingsService implements VaultSettingsServiceAbstraction {
* {@link VaultSettingsServiceAbstraction.clickItemsToAutofillVaultView$$} * {@link VaultSettingsServiceAbstraction.clickItemsToAutofillVaultView$$}
*/ */
readonly clickItemsToAutofillVaultView$: Observable<boolean> = readonly clickItemsToAutofillVaultView$: Observable<boolean> =
this.clickItemsToAutofillVaultViewState.state$.pipe(map((x) => x ?? false)); this.clickItemsToAutofillVaultViewState.state$.pipe(
map((x) => x ?? false),
shareReplay({ bufferSize: 1, refCount: false }),
);
constructor(private stateProvider: StateProvider) {} constructor(private stateProvider: StateProvider) {}