diff --git a/src/aria/menu/menu.ts b/src/aria/menu/menu.ts index c169e01b73e4..86c736b02df0 100644 --- a/src/aria/menu/menu.ts +++ b/src/aria/menu/menu.ts @@ -252,6 +252,11 @@ export class Menu { }); } + /** Opens the menu. */ + open() { + this._pattern.open(); + } + /** Closes the menu. */ close() { this._pattern.close(); diff --git a/src/aria/private/menu/menu.ts b/src/aria/private/menu/menu.ts index d61e9ffbae9b..fb8247369710 100644 --- a/src/aria/private/menu/menu.ts +++ b/src/aria/private/menu/menu.ts @@ -80,7 +80,9 @@ export class MenuPattern { disabled = () => this.inputs.disabled(); /** Whether the menu is visible. */ - isVisible = computed(() => (this.inputs.parent() ? !!this.inputs.parent()?.expanded() : true)); + isVisible = computed(() => + this.inputs.parent() ? !!this.inputs.parent()?.expanded() : this._visible(), + ); /** Controls list behavior for the menu items. */ listBehavior: List, V>; @@ -91,6 +93,8 @@ export class MenuPattern { /** Whether the menu has received focus. */ hasBeenFocused = signal(false); + _visible = signal(false); + /** Timeout used to open sub-menus on hover. */ _openTimeout: any; @@ -402,9 +406,24 @@ export class MenuPattern { } } + /** Opens the menu. */ + open() { + if (this.inputs.parent()) { + this.inputs.parent()!.close(); + } else { + this._visible.set(true); + + this.first(); + } + } + /** Closes the menu. */ close() { - this.inputs.parent()?.close(); + if (this.inputs.parent()) { + this.inputs.parent()!.close(); + } else { + this._visible.set(false); + } } /** Closes the menu and all parent menus. */ diff --git a/src/components-examples/aria/menu/menu-context/menu-context-example.ts b/src/components-examples/aria/menu/menu-context/menu-context-example.ts index a484b5f3f5da..d9ed909fbcd0 100644 --- a/src/components-examples/aria/menu/menu-context/menu-context-example.ts +++ b/src/components-examples/aria/menu/menu-context/menu-context-example.ts @@ -30,23 +30,20 @@ export class MenuContextExample { const relatedTarget = event.relatedTarget as HTMLElement | null; if (menu && !menu.element.contains(relatedTarget)) { - menu.close(); - menu.element.style.visibility = 'hidden'; + menu!.close(); } } open(event: MouseEvent) { const menu = this.menu(); - menu?._pattern.closeAll(); if (menu) { event.preventDefault(); - menu.element.style.visibility = 'visible'; menu.element.style.top = `${event.clientY}px`; menu.element.style.left = `${event.clientX}px`; - setTimeout(() => menu._pattern.first()); + menu.open(); } } } diff --git a/src/components-examples/aria/menu/menu-example.css b/src/components-examples/aria/menu/menu-example.css index 6aaf76c9d91a..40bae3a74671 100644 --- a/src/components-examples/aria/menu/menu-example.css +++ b/src/components-examples/aria/menu/menu-example.css @@ -128,5 +128,4 @@ .example-context-menu { position: absolute; - visibility: hidden; }