Skip to content

Commit fd2213c

Browse files
committed
fix(cdk/menu): allow user to pass selector for transform origin (#32462)
Adds an input that allows users to specify which element the CDK overlay will set the transform origin on. This is useful when animating the menus. Fixes #32439. (cherry picked from commit 789274f)
1 parent 49f1bc8 commit fd2213c

File tree

4 files changed

+25
-4
lines changed

4 files changed

+25
-4
lines changed

goldens/cdk/menu/index.api.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ export class CdkContextMenuTrigger extends CdkMenuTriggerBase implements OnDestr
4646
open(coordinates: ContextMenuCoordinates): void;
4747
_openOnContextMenu(event: MouseEvent): void;
4848
// (undocumented)
49-
static ɵdir: i0.ɵɵDirectiveDeclaration<CdkContextMenuTrigger, "[cdkContextMenuTriggerFor]", ["cdkContextMenuTriggerFor"], { "menuTemplateRef": { "alias": "cdkContextMenuTriggerFor"; "required": false; }; "menuPosition": { "alias": "cdkContextMenuPosition"; "required": false; }; "menuData": { "alias": "cdkContextMenuTriggerData"; "required": false; }; "disabled": { "alias": "cdkContextMenuDisabled"; "required": false; }; }, { "opened": "cdkContextMenuOpened"; "closed": "cdkContextMenuClosed"; }, never, never, true, never>;
49+
static ɵdir: i0.ɵɵDirectiveDeclaration<CdkContextMenuTrigger, "[cdkContextMenuTriggerFor]", ["cdkContextMenuTriggerFor"], { "menuTemplateRef": { "alias": "cdkContextMenuTriggerFor"; "required": false; }; "menuPosition": { "alias": "cdkContextMenuPosition"; "required": false; }; "menuData": { "alias": "cdkContextMenuTriggerData"; "required": false; }; "transformOriginSelector": { "alias": "cdkContextMenuTriggerTransformOriginOn"; "required": false; }; "disabled": { "alias": "cdkContextMenuDisabled"; "required": false; }; }, { "opened": "cdkContextMenuOpened"; "closed": "cdkContextMenuClosed"; }, never, never, true, never>;
5050
// (undocumented)
5151
static ɵfac: i0.ɵɵFactoryDeclaration<CdkContextMenuTrigger, never>;
5252
}
@@ -224,7 +224,7 @@ export class CdkMenuTrigger extends CdkMenuTriggerBase implements OnChanges, OnD
224224
toggle(): void;
225225
_toggleOnKeydown(event: KeyboardEvent): void;
226226
// (undocumented)
227-
static ɵdir: i0.ɵɵDirectiveDeclaration<CdkMenuTrigger, "[cdkMenuTriggerFor]", ["cdkMenuTriggerFor"], { "menuTemplateRef": { "alias": "cdkMenuTriggerFor"; "required": false; }; "menuPosition": { "alias": "cdkMenuPosition"; "required": false; }; "menuData": { "alias": "cdkMenuTriggerData"; "required": false; }; }, { "opened": "cdkMenuOpened"; "closed": "cdkMenuClosed"; }, never, never, true, never>;
227+
static ɵdir: i0.ɵɵDirectiveDeclaration<CdkMenuTrigger, "[cdkMenuTriggerFor]", ["cdkMenuTriggerFor"], { "menuTemplateRef": { "alias": "cdkMenuTriggerFor"; "required": false; }; "menuPosition": { "alias": "cdkMenuPosition"; "required": false; }; "menuData": { "alias": "cdkMenuTriggerData"; "required": false; }; "transformOriginSelector": { "alias": "cdkMenuTriggerTransformOriginOn"; "required": false; }; }, { "opened": "cdkMenuOpened"; "closed": "cdkMenuClosed"; }, never, never, true, never>;
228228
// (undocumented)
229229
static ɵfac: i0.ɵɵFactoryDeclaration<CdkMenuTrigger, never>;
230230
}
@@ -250,6 +250,7 @@ export abstract class CdkMenuTriggerBase implements OnDestroy {
250250
protected overlayRef: OverlayRef | null;
251251
registerChildMenu(child: Menu): void;
252252
protected readonly stopOutsideClicksListener: rxjs.Observable<void>;
253+
transformOriginSelector: string | null;
253254
protected readonly viewContainerRef: ViewContainerRef;
254255
// (undocumented)
255256
static ɵdir: i0.ɵɵDirectiveDeclaration<CdkMenuTriggerBase, never, never, {}, {}, never, never, true, never>;

src/cdk/menu/context-menu-trigger.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ export type ContextMenuCoordinates = {x: number; y: number};
6262
{name: 'menuTemplateRef', alias: 'cdkContextMenuTriggerFor'},
6363
{name: 'menuPosition', alias: 'cdkContextMenuPosition'},
6464
{name: 'menuData', alias: 'cdkContextMenuTriggerData'},
65+
{name: 'transformOriginSelector', alias: 'cdkContextMenuTriggerTransformOriginOn'},
6566
],
6667
outputs: ['opened: cdkContextMenuOpened', 'closed: cdkContextMenuClosed'],
6768
providers: [
@@ -147,10 +148,16 @@ export class CdkContextMenuTrigger extends CdkMenuTriggerBase implements OnDestr
147148
private _getOverlayPositionStrategy(
148149
coordinates: ContextMenuCoordinates,
149150
): FlexibleConnectedPositionStrategy {
150-
return createFlexibleConnectedPositionStrategy(this._injector, coordinates)
151+
const strategy = createFlexibleConnectedPositionStrategy(this._injector, coordinates)
151152
.withLockedPosition()
152153
.withGrowAfterOpen()
153154
.withPositions(this.menuPosition ?? CONTEXT_MENU_POSITIONS);
155+
156+
if (this.transformOriginSelector) {
157+
strategy.withTransformOriginOn(this.transformOriginSelector);
158+
}
159+
160+
return strategy;
154161
}
155162

156163
/** Subscribe to the menu stack close events and close this menu when requested. */

src/cdk/menu/menu-trigger-base.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,12 @@ export abstract class CdkMenuTriggerBase implements OnDestroy {
102102
/** Context data to be passed along to the menu template */
103103
menuData: unknown;
104104

105+
/**
106+
* Selector for the element on which to set the transform origin once the menu is open.
107+
* This makes it easier to implement animations that start from the attachment point of the menu.
108+
*/
109+
transformOriginSelector: string | null = null;
110+
105111
/** Close the opened menu. */
106112
abstract close(): void;
107113

src/cdk/menu/menu-trigger.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ import {eventDispatchesNativeClick} from './event-detection';
6969
{name: 'menuTemplateRef', alias: 'cdkMenuTriggerFor'},
7070
{name: 'menuPosition', alias: 'cdkMenuPosition'},
7171
{name: 'menuData', alias: 'cdkMenuTriggerData'},
72+
{name: 'transformOriginSelector', alias: 'cdkMenuTriggerTransformOriginOn'},
7273
],
7374
outputs: ['opened: cdkMenuOpened', 'closed: cdkMenuClosed'],
7475
providers: [
@@ -281,10 +282,16 @@ export class CdkMenuTrigger extends CdkMenuTriggerBase implements OnChanges, OnD
281282

282283
/** Build the position strategy for the overlay which specifies where to place the menu. */
283284
private _getOverlayPositionStrategy(): FlexibleConnectedPositionStrategy {
284-
return createFlexibleConnectedPositionStrategy(this._injector, this._elementRef)
285+
const strategy = createFlexibleConnectedPositionStrategy(this._injector, this._elementRef)
285286
.withLockedPosition()
286287
.withFlexibleDimensions(false)
287288
.withPositions(this._getOverlayPositions());
289+
290+
if (this.transformOriginSelector) {
291+
strategy.withTransformOriginOn(this.transformOriginSelector);
292+
}
293+
294+
return strategy;
288295
}
289296

290297
/** Get the preferred positions for the opened menu relative to the menu item. */

0 commit comments

Comments
 (0)