1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-19 19:04:01 +00:00

[PM-29819][CL-806] Fix focus mgmt on search and filter page navigations (#18007)

This commit is contained in:
Vicki League
2025-12-22 16:55:20 -05:00
committed by jaasen-livefront
parent da5dd1f5f1
commit 505d2fff00
5 changed files with 19 additions and 11 deletions

View File

@@ -587,6 +587,9 @@ export class VaultComponent implements OnInit, OnDestroy {
queryParams: { search: Utils.isNullOrEmpty(searchText) ? null : searchText }, queryParams: { search: Utils.isNullOrEmpty(searchText) ? null : searchText },
queryParamsHandling: "merge", queryParamsHandling: "merge",
replaceUrl: true, replaceUrl: true,
state: {
focusMainAfterNav: false,
},
}), }),
); );

View File

@@ -74,6 +74,9 @@ export class RoutedVaultFilterService implements OnDestroy {
type: filter.type ?? null, type: filter.type ?? null,
}, },
queryParamsHandling: "merge", queryParamsHandling: "merge",
state: {
focusMainAfterNav: false,
},
}; };
return [commands, extras]; return [commands, extras];
} }

View File

@@ -424,6 +424,9 @@ export class VaultComponent<C extends CipherViewLike> implements OnInit, OnDestr
queryParams: { search: Utils.isNullOrEmpty(searchText) ? null : searchText }, queryParams: { search: Utils.isNullOrEmpty(searchText) ? null : searchText },
queryParamsHandling: "merge", queryParamsHandling: "merge",
replaceUrl: true, replaceUrl: true,
state: {
focusMainAfterNav: false,
},
}), }),
); );

View File

@@ -1,7 +1,7 @@
import { inject, Injectable } from "@angular/core"; import { inject, Injectable } from "@angular/core";
import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
import { NavigationEnd, Router } from "@angular/router"; import { NavigationEnd, Router } from "@angular/router";
import { skip, filter, map, combineLatestWith, tap } from "rxjs"; import { skip, filter, combineLatestWith, tap } from "rxjs";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum"; import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
@@ -19,8 +19,10 @@ export class RouterFocusManagerService {
* *
* By default, we focus the `main` after an internal route navigation. * By default, we focus the `main` after an internal route navigation.
* *
* Consumers can opt out of the passing the following to the `info` input: * Consumers can opt out of the passing the following to the `state` input. Using `state`
* `<a [routerLink]="route()" [info]="{ focusMainAfterNav: false }"></a>` * allows us to access the value between browser back/forward arrows.
* In template: `<a [routerLink]="route()" [state]="{ focusMainAfterNav: false }"></a>`
* In typescript: `this.router.navigate([], { state: { focusMainAfterNav: false }})`
* *
* Or, consumers can use the autofocus directive on an applicable interactive element. * Or, consumers can use the autofocus directive on an applicable interactive element.
* The autofocus directive will take precedence over this route focus pipeline. * The autofocus directive will take precedence over this route focus pipeline.
@@ -44,15 +46,12 @@ export class RouterFocusManagerService {
skip(1), skip(1),
combineLatestWith(this.configService.getFeatureFlag$(FeatureFlag.RouterFocusManagement)), combineLatestWith(this.configService.getFeatureFlag$(FeatureFlag.RouterFocusManagement)),
filter(([_navEvent, flagEnabled]) => flagEnabled), filter(([_navEvent, flagEnabled]) => flagEnabled),
map(() => { filter(() => {
const currentNavData = this.router.getCurrentNavigation()?.extras; const currentNavExtras = this.router.currentNavigation()?.extras;
const info = currentNavData?.info as { focusMainAfterNav?: boolean } | undefined; const focusMainAfterNav: boolean | undefined = currentNavExtras?.state?.focusMainAfterNav;
return info; return focusMainAfterNav !== false;
}),
filter((currentNavInfo) => {
return currentNavInfo === undefined ? true : currentNavInfo?.focusMainAfterNav !== false;
}), }),
tap(() => { tap(() => {
const mainEl = document.querySelector<HTMLElement>("main"); const mainEl = document.querySelector<HTMLElement>("main");

View File

@@ -5,7 +5,7 @@
[routerLinkActiveOptions]="routerLinkMatchOptions" [routerLinkActiveOptions]="routerLinkMatchOptions"
#rla="routerLinkActive" #rla="routerLinkActive"
[active]="rla.isActive" [active]="rla.isActive"
[info]="{ focusMainAfterNav: false }" [state]="{ focusMainAfterNav: false }"
[disabled]="disabled" [disabled]="disabled"
[attr.aria-disabled]="disabled" [attr.aria-disabled]="disabled"
ariaCurrentWhenActive="page" ariaCurrentWhenActive="page"