mirror of
https://github.com/bitwarden/browser
synced 2026-02-17 09:59:41 +00:00
[CL-724] Vault list item keyboard nav dialog (#15591)
* add focus-visible-within util * wip: add grid a11y dialog to vault * add story and i18n
This commit is contained in:
@@ -200,3 +200,7 @@ export const VAULT_BROWSER_INTRO_CAROUSEL = new StateDefinition(
|
||||
"vaultBrowserIntroCarousel",
|
||||
"disk",
|
||||
);
|
||||
export const VAULT_ITEM_GROUP_NAVIGATION_DIALOG = new StateDefinition(
|
||||
"vaultItemGroupNavigationDialog",
|
||||
"disk",
|
||||
);
|
||||
|
||||
@@ -1 +1,4 @@
|
||||
export * from "./a11y-cell.directive";
|
||||
export * from "./a11y-grid.directive";
|
||||
export * from "./a11y-row.directive";
|
||||
export * from "./a11y-title.directive";
|
||||
|
||||
47
libs/components/src/utils/focus-visible-within.ts
Normal file
47
libs/components/src/utils/focus-visible-within.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import { Directive, ElementRef, inject, input, output } from "@angular/core";
|
||||
import { takeUntilDestroyed, toObservable } from "@angular/core/rxjs-interop";
|
||||
import { filter, fromEvent, map, switchMap } from "rxjs";
|
||||
|
||||
@Directive({
|
||||
selector: "[bitFocusVisibleWithin]",
|
||||
})
|
||||
export class FocusVisibleWithinDirective {
|
||||
private elementRef = inject(ElementRef) as ElementRef<HTMLElement>;
|
||||
|
||||
/**
|
||||
* Emits when the host element has a child with `:focus-visible`.
|
||||
*
|
||||
* The target selector can be narrowed with the `selector` input.
|
||||
**/
|
||||
bitFocusVisibleWithin = output<void>();
|
||||
|
||||
/**
|
||||
* The child selector to watch.
|
||||
*
|
||||
* Defaults to `:focus-visble`, but sometimes it may be useful to be more specific, e.g. `foo-bar:focus-visible`.
|
||||
**/
|
||||
selector = input<`${string}:focus-visible`>(":focus-visible");
|
||||
|
||||
constructor() {
|
||||
toObservable(this.selector)
|
||||
.pipe(
|
||||
switchMap((selector) =>
|
||||
fromEvent(this.elementRef.nativeElement, "focusin").pipe(
|
||||
map(() => {
|
||||
const activeEl = document.activeElement;
|
||||
return (
|
||||
!!activeEl &&
|
||||
this.elementRef.nativeElement.contains(activeEl) &&
|
||||
activeEl.matches(selector)
|
||||
);
|
||||
}),
|
||||
),
|
||||
),
|
||||
filter((hasFocusVisibleWithin) => hasFocusVisibleWithin),
|
||||
takeUntilDestroyed(),
|
||||
)
|
||||
.subscribe(() => {
|
||||
this.bitFocusVisibleWithin.emit();
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,2 +1,3 @@
|
||||
export * from "./focus-visible-within";
|
||||
export * from "./function-to-observable";
|
||||
export * from "./i18n-mock.service";
|
||||
|
||||
Reference in New Issue
Block a user