diff --git a/packages/mdc-menu-surface/adapter.ts b/packages/mdc-menu-surface/adapter.ts index 86a15acf4dd..cd3b4bf2ed1 100644 --- a/packages/mdc-menu-surface/adapter.ts +++ b/packages/mdc-menu-surface/adapter.ts @@ -64,4 +64,7 @@ export interface MDCMenuSurfaceAdapter { /** Emits an event when the menu surface is opened. */ notifyOpen(): void; + + /** Emits an event when the menu surface is opening. */ + notifyOpening(): void; } diff --git a/packages/mdc-menu-surface/component.ts b/packages/mdc-menu-surface/component.ts index 6cbb06a2cf7..7e8ee0ec0bd 100644 --- a/packages/mdc-menu-surface/component.ts +++ b/packages/mdc-menu-surface/component.ts @@ -160,6 +160,8 @@ export class MDCMenuSurface extends MDCComponent { }, notifyOpen: () => this.emit(MDCMenuSurfaceFoundation.strings.OPENED_EVENT, {}), + notifyOpening: () => + this.emit(MDCMenuSurfaceFoundation.strings.OPENING_EVENT, {}), isElementInContainer: (el) => this.root.contains(el), isRtl: () => getComputedStyle(this.root).getPropertyValue('direction') === 'rtl', diff --git a/packages/mdc-menu-surface/constants.ts b/packages/mdc-menu-surface/constants.ts index 7f457e90512..96a03ceda66 100644 --- a/packages/mdc-menu-surface/constants.ts +++ b/packages/mdc-menu-surface/constants.ts @@ -36,6 +36,7 @@ const strings = { CLOSED_EVENT: 'MDCMenuSurface:closed', CLOSING_EVENT: 'MDCMenuSurface:closing', OPENED_EVENT: 'MDCMenuSurface:opened', + OPENING_EVENT: 'MDCMenuSurface:opening', FOCUSABLE_ELEMENTS: [ 'button:not(:disabled)', '[href]:not([aria-disabled="true"])', diff --git a/packages/mdc-menu-surface/foundation.ts b/packages/mdc-menu-surface/foundation.ts index 25a7478a05a..d78b61fa95f 100644 --- a/packages/mdc-menu-surface/foundation.ts +++ b/packages/mdc-menu-surface/foundation.ts @@ -82,8 +82,9 @@ export class MDCMenuSurfaceFoundation extends restoreFocus: () => undefined, notifyClose: () => undefined, - notifyOpen: () => undefined, notifyClosing: () => undefined, + notifyOpen: () => undefined, + notifyOpening: () => undefined, }; // tslint:enable:object-literal-sort-keys } @@ -238,6 +239,7 @@ export class MDCMenuSurfaceFoundation extends return; } + this.adapter.notifyOpening(); this.adapter.saveFocus(); if (this.isQuickOpen) { diff --git a/packages/mdc-menu-surface/test/component.test.ts b/packages/mdc-menu-surface/test/component.test.ts index 04b288985a5..f7dddea2d72 100644 --- a/packages/mdc-menu-surface/test/component.test.ts +++ b/packages/mdc-menu-surface/test/component.test.ts @@ -316,6 +316,15 @@ describe('MDCMenuSurface', () => { expect(handler).toHaveBeenCalled(); }); + it(`adapter#notifyOpening fires an ${strings.OPENING_EVENT} custom event`, + () => { + const {root, component} = setupTest(); + const handler = jasmine.createSpy('notifyOpening handler'); + root.addEventListener(strings.OPENING_EVENT, handler); + (component.getDefaultFoundation() as any).adapter.notifyOpening(); + expect(handler).toHaveBeenCalled(); + }); + it('adapter#restoreFocus restores focus saved by adapter#saveFocus', () => { const {root, component} = setupTest({open: true}); const button = document.createElement('button'); diff --git a/packages/mdc-menu-surface/test/foundation.test.ts b/packages/mdc-menu-surface/test/foundation.test.ts index cc459492642..e6dbb6765e1 100644 --- a/packages/mdc-menu-surface/test/foundation.test.ts +++ b/packages/mdc-menu-surface/test/foundation.test.ts @@ -196,6 +196,7 @@ describe('MDCMenuSurfaceFoundation', () => { 'notifyClose', 'notifyClosing', 'notifyOpen', + 'notifyOpening', 'isElementInContainer', 'isRtl', 'setTransformOrigin', @@ -264,6 +265,13 @@ describe('MDCMenuSurfaceFoundation', () => { .toHaveBeenCalledWith(cssClasses.ANIMATING_OPEN); }); + testFoundation( + '#open emits the opening event at the beginning of the animation', + ({foundation, mockAdapter}) => { + foundation.open(); + expect(mockAdapter.notifyOpening).toHaveBeenCalled(); + }); + testFoundation( '#open emits the open event at the end of the animation', ({foundation, mockAdapter}) => {