mirror of
https://github.com/bitwarden/browser
synced 2025-12-15 15:53:27 +00:00
[SM-43] create product-switcher (#4189)
* rebase to master * use bit-menu in product switcher; add focusStrategy to bit-menu * recommit locales after rebase * add light style to iconButton, use in product-switcher * move out of component library * add buttonType input * gate behind sm flag * update aria-label * add role input to bit-menu * style changes * simplify partition logic * split into two components for Storybook * update focus styles; update grid sizing to relative * fix underline on hover * update attribute binding * move to layouts dir * add bitLink; update grid gap * reorder loose components * move orgs mock * move a11y module * fix aria role bug; add aria label to menu * update colors * update ring color * simplify colors * remove duplicate link module
This commit is contained in:
@@ -19,7 +19,9 @@ import { MenuComponent } from "./menu.component";
|
||||
})
|
||||
export class MenuTriggerForDirective implements OnDestroy {
|
||||
@HostBinding("attr.aria-expanded") isOpen = false;
|
||||
@HostBinding("attr.aria-haspopup") hasPopup = "menu";
|
||||
@HostBinding("attr.aria-haspopup") get hasPopup(): "menu" | "dialog" {
|
||||
return this.menu?.ariaRole || "menu";
|
||||
}
|
||||
@HostBinding("attr.role") role = "button";
|
||||
|
||||
@Input("bitMenuTriggerFor") menu: MenuComponent;
|
||||
@@ -86,9 +88,11 @@ export class MenuTriggerForDirective implements OnDestroy {
|
||||
}
|
||||
this.destroyMenu();
|
||||
});
|
||||
this.keyDownEventsSub = this.overlayRef
|
||||
.keydownEvents()
|
||||
.subscribe((event: KeyboardEvent) => this.menu.keyManager.onKeydown(event));
|
||||
this.keyDownEventsSub =
|
||||
this.menu.keyManager &&
|
||||
this.overlayRef
|
||||
.keydownEvents()
|
||||
.subscribe((event: KeyboardEvent) => this.menu.keyManager.onKeydown(event));
|
||||
}
|
||||
|
||||
private destroyMenu() {
|
||||
@@ -102,9 +106,12 @@ export class MenuTriggerForDirective implements OnDestroy {
|
||||
|
||||
private getClosedEvents(): Observable<any> {
|
||||
const detachments = this.overlayRef.detachments();
|
||||
const escKey = this.overlayRef
|
||||
.keydownEvents()
|
||||
.pipe(filter((event: KeyboardEvent) => event.key === "Escape" || event.key === "Tab"));
|
||||
const escKey = this.overlayRef.keydownEvents().pipe(
|
||||
filter((event: KeyboardEvent) => {
|
||||
const keys = this.menu.ariaRole === "menu" ? ["Escape", "Tab"] : ["Escape"];
|
||||
return keys.includes(event.key);
|
||||
})
|
||||
);
|
||||
const backdrop = this.overlayRef.backdropClick();
|
||||
const menuClosed = this.menu.closed;
|
||||
|
||||
|
||||
@@ -2,7 +2,10 @@
|
||||
<div
|
||||
(click)="closed.emit()"
|
||||
class="tw-flex tw-shrink-0 tw-flex-col tw-rounded tw-border tw-border-solid tw-border-secondary-500 tw-bg-background tw-bg-clip-padding tw-py-2"
|
||||
role="menu"
|
||||
[attr.role]="ariaRole"
|
||||
[attr.aria-label]="ariaLabel"
|
||||
cdkTrapFocus
|
||||
[cdkTrapFocusAutoCapture]="true"
|
||||
>
|
||||
<ng-content></ng-content>
|
||||
</div>
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
ContentChildren,
|
||||
QueryList,
|
||||
AfterContentInit,
|
||||
Input,
|
||||
} from "@angular/core";
|
||||
|
||||
import { MenuItemDirective } from "./menu-item.directive";
|
||||
@@ -22,9 +23,15 @@ export class MenuComponent implements AfterContentInit {
|
||||
@Output() closed = new EventEmitter<void>();
|
||||
@ContentChildren(MenuItemDirective, { descendants: true })
|
||||
menuItems: QueryList<MenuItemDirective>;
|
||||
keyManager: FocusKeyManager<MenuItemDirective>;
|
||||
keyManager?: FocusKeyManager<MenuItemDirective>;
|
||||
|
||||
@Input() ariaRole: "menu" | "dialog" = "menu";
|
||||
|
||||
@Input() ariaLabel: string;
|
||||
|
||||
ngAfterContentInit() {
|
||||
this.keyManager = new FocusKeyManager(this.menuItems).withWrap();
|
||||
if (this.ariaRole === "menu") {
|
||||
this.keyManager = new FocusKeyManager(this.menuItems).withWrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { A11yModule } from "@angular/cdk/a11y";
|
||||
import { OverlayModule } from "@angular/cdk/overlay";
|
||||
import { CommonModule } from "@angular/common";
|
||||
import { NgModule } from "@angular/core";
|
||||
@@ -8,7 +9,7 @@ import { MenuTriggerForDirective } from "./menu-trigger-for.directive";
|
||||
import { MenuComponent } from "./menu.component";
|
||||
|
||||
@NgModule({
|
||||
imports: [CommonModule, OverlayModule],
|
||||
imports: [A11yModule, CommonModule, OverlayModule],
|
||||
declarations: [MenuComponent, MenuTriggerForDirective, MenuItemDirective, MenuDividerComponent],
|
||||
exports: [MenuComponent, MenuTriggerForDirective, MenuItemDirective, MenuDividerComponent],
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user