diff --git a/goldens/cdk/menu/index.api.md b/goldens/cdk/menu/index.api.md index 27be93023ab9..318e551c75c2 100644 --- a/goldens/cdk/menu/index.api.md +++ b/goldens/cdk/menu/index.api.md @@ -46,7 +46,7 @@ export class CdkContextMenuTrigger extends CdkMenuTriggerBase implements OnDestr open(coordinates: ContextMenuCoordinates): void; _openOnContextMenu(event: MouseEvent): void; // (undocumented) - static ɵdir: i0.ɵɵDirectiveDeclaration; + static ɵdir: i0.ɵɵDirectiveDeclaration; // (undocumented) static ɵfac: i0.ɵɵFactoryDeclaration; } @@ -224,7 +224,7 @@ export class CdkMenuTrigger extends CdkMenuTriggerBase implements OnChanges, OnD toggle(): void; _toggleOnKeydown(event: KeyboardEvent): void; // (undocumented) - static ɵdir: i0.ɵɵDirectiveDeclaration; + static ɵdir: i0.ɵɵDirectiveDeclaration; // (undocumented) static ɵfac: i0.ɵɵFactoryDeclaration; } @@ -250,6 +250,7 @@ export abstract class CdkMenuTriggerBase implements OnDestroy { protected overlayRef: OverlayRef | null; registerChildMenu(child: Menu): void; protected readonly stopOutsideClicksListener: rxjs.Observable; + transformOriginSelector: string | null; protected readonly viewContainerRef: ViewContainerRef; // (undocumented) static ɵdir: i0.ɵɵDirectiveDeclaration; diff --git a/src/cdk/menu/context-menu-trigger.ts b/src/cdk/menu/context-menu-trigger.ts index bf1b5a86ea67..bc6cac4f2798 100644 --- a/src/cdk/menu/context-menu-trigger.ts +++ b/src/cdk/menu/context-menu-trigger.ts @@ -62,6 +62,7 @@ export type ContextMenuCoordinates = {x: number; y: number}; {name: 'menuTemplateRef', alias: 'cdkContextMenuTriggerFor'}, {name: 'menuPosition', alias: 'cdkContextMenuPosition'}, {name: 'menuData', alias: 'cdkContextMenuTriggerData'}, + {name: 'transformOriginSelector', alias: 'cdkContextMenuTriggerTransformOriginOn'}, ], outputs: ['opened: cdkContextMenuOpened', 'closed: cdkContextMenuClosed'], providers: [ @@ -147,10 +148,16 @@ export class CdkContextMenuTrigger extends CdkMenuTriggerBase implements OnDestr private _getOverlayPositionStrategy( coordinates: ContextMenuCoordinates, ): FlexibleConnectedPositionStrategy { - return createFlexibleConnectedPositionStrategy(this._injector, coordinates) + const strategy = createFlexibleConnectedPositionStrategy(this._injector, coordinates) .withLockedPosition() .withGrowAfterOpen() .withPositions(this.menuPosition ?? CONTEXT_MENU_POSITIONS); + + if (this.transformOriginSelector) { + strategy.withTransformOriginOn(this.transformOriginSelector); + } + + return strategy; } /** Subscribe to the menu stack close events and close this menu when requested. */ diff --git a/src/cdk/menu/menu-trigger-base.ts b/src/cdk/menu/menu-trigger-base.ts index 7656603cc00a..e5addfc550d6 100644 --- a/src/cdk/menu/menu-trigger-base.ts +++ b/src/cdk/menu/menu-trigger-base.ts @@ -102,6 +102,12 @@ export abstract class CdkMenuTriggerBase implements OnDestroy { /** Context data to be passed along to the menu template */ menuData: unknown; + /** + * Selector for the element on which to set the transform origin once the menu is open. + * This makes it easier to implement animations that start from the attachment point of the menu. + */ + transformOriginSelector: string | null = null; + /** Close the opened menu. */ abstract close(): void; diff --git a/src/cdk/menu/menu-trigger.ts b/src/cdk/menu/menu-trigger.ts index d37ab81a4205..3b4d5b48dee3 100644 --- a/src/cdk/menu/menu-trigger.ts +++ b/src/cdk/menu/menu-trigger.ts @@ -69,6 +69,7 @@ import {eventDispatchesNativeClick} from './event-detection'; {name: 'menuTemplateRef', alias: 'cdkMenuTriggerFor'}, {name: 'menuPosition', alias: 'cdkMenuPosition'}, {name: 'menuData', alias: 'cdkMenuTriggerData'}, + {name: 'transformOriginSelector', alias: 'cdkMenuTriggerTransformOriginOn'}, ], outputs: ['opened: cdkMenuOpened', 'closed: cdkMenuClosed'], providers: [ @@ -281,10 +282,16 @@ export class CdkMenuTrigger extends CdkMenuTriggerBase implements OnChanges, OnD /** Build the position strategy for the overlay which specifies where to place the menu. */ private _getOverlayPositionStrategy(): FlexibleConnectedPositionStrategy { - return createFlexibleConnectedPositionStrategy(this._injector, this._elementRef) + const strategy = createFlexibleConnectedPositionStrategy(this._injector, this._elementRef) .withLockedPosition() .withFlexibleDimensions(false) .withPositions(this._getOverlayPositions()); + + if (this.transformOriginSelector) { + strategy.withTransformOriginOn(this.transformOriginSelector); + } + + return strategy; } /** Get the preferred positions for the opened menu relative to the menu item. */