fix(overlay): centered flexible positioning not working in some browsers (#10701)

Currently using centering with the `FlexibleConnectedPositionStrategy` in flexible mode doesn't work in browsers that haven't implemented [the new absolute position behavior inside a flex container](https://developers.google.com/web/updates/2016/06/absolute-positioned-children) (e.g. iOS Safari), which means that the position will be thrown off completely. These changes rework the position strategy to use `position: static` and `justify-content`/`align-items`, rather than `position: absolute`, to push the overlay pane to the proper edge of the bounding box in flexible mode. As a result, support for having flexible dimensions in only one direction has been removed.
This commit is contained in:
Kristiyan Kostadinov
2018-04-10 19:57:36 +02:00
committed by tinayuangao
parent b472330659
commit dfc3b026e7
10 changed files with 150 additions and 159 deletions
+6 -3
View File
@@ -51,8 +51,9 @@ $backdrop-animation-timing-function: cubic-bezier(0.25, 0.8, 0.25, 1) !default;
// A single overlay pane.
.cdk-overlay-pane {
// Note: it's important for this one to start off `absolute`,
// in order for us to be able to measure it correctly.
position: absolute;
pointer-events: auto;
box-sizing: border-box;
z-index: $cdk-z-index-overlay;
@@ -113,8 +114,10 @@ $backdrop-animation-timing-function: cubic-bezier(0.25, 0.8, 0.25, 1) !default;
// When *not* centering, a top/left/bottom/right will be set which overrides the normal
// flex layout.
display: flex;
justify-content: center;
align-items: center;
// We use the `column` direction here to avoid some flexbox issues in Edge
// when using the "grow after open" options.
flex-direction: column;
// Add some dimensions so the element has an `innerText` which some people depend on in tests.
min-width: 1px;
+1 -2
View File
@@ -289,8 +289,7 @@ export class CdkConnectedOverlay implements OnDestroy, OnChanges {
// the same way as the old ConnectedPositionStrategy and to avoid breaking changes.
// TODO(crisbeto): make these on by default and add inputs for them
// next time we do breaking changes.
.withFlexibleHeight(false)
.withFlexibleWidth(false)
.withFlexibleDimensions(false)
.withPush(false)
.withGrowAfterOpen(false)
.withLockedPosition(this.lockPosition);
@@ -70,8 +70,7 @@ export class ConnectedPositionStrategy implements PositionStrategy {
// proxy all of the API calls.
this._positionStrategy =
new FlexibleConnectedPositionStrategy(connectedTo, viewportRuler, document)
.withFlexibleHeight(false)
.withFlexibleWidth(false)
.withFlexibleDimensions(false)
.withPush(false)
.withViewportMargin(0);
@@ -120,8 +120,7 @@ describe('FlexibleConnectedPositionStrategy', () => {
document.body.appendChild(originElement);
positionStrategy = overlay.position()
.flexibleConnectedTo(new ElementRef(originElement))
.withFlexibleHeight(false)
.withFlexibleWidth(false)
.withFlexibleDimensions(false)
.withPush(false);
});
@@ -865,8 +864,7 @@ describe('FlexibleConnectedPositionStrategy', () => {
document.body.appendChild(originElement);
positionStrategy = overlay.position()
.flexibleConnectedTo(new ElementRef(originElement))
.withFlexibleHeight(false)
.withFlexibleWidth(false)
.withFlexibleDimensions(false)
.withPush();
});
@@ -1003,8 +1001,8 @@ describe('FlexibleConnectedPositionStrategy', () => {
it('should align the overlay to `flex-start` when the content is flowing to the right', () => {
positionStrategy
.withFlexibleWidth()
.withFlexibleHeight()
.withFlexibleDimensions()
.withPush(false)
.withPositions([{
overlayY: 'top',
overlayX: 'start',
@@ -1014,13 +1012,13 @@ describe('FlexibleConnectedPositionStrategy', () => {
attachOverlay({positionStrategy});
expect(overlayRef.overlayElement.style.justifyContent).toBe('flex-start');
expect(overlayRef.hostElement.style.alignItems).toBe('flex-start');
});
it('should align the overlay to `flex-end` when the content is flowing to the left', () => {
positionStrategy
.withFlexibleWidth()
.withFlexibleHeight()
.withFlexibleDimensions()
.withPush(false)
.withPositions([{
overlayY: 'top',
overlayX: 'end',
@@ -1030,13 +1028,13 @@ describe('FlexibleConnectedPositionStrategy', () => {
attachOverlay({positionStrategy});
expect(overlayRef.overlayElement.style.justifyContent).toBe('flex-end');
expect(overlayRef.hostElement.style.alignItems).toBe('flex-end');
});
it('should align the overlay to `center` when the content is centered', () => {
positionStrategy
.withFlexibleWidth()
.withFlexibleHeight()
.withFlexibleDimensions()
.withPush(false)
.withPositions([{
overlayY: 'top',
overlayX: 'center',
@@ -1046,48 +1044,48 @@ describe('FlexibleConnectedPositionStrategy', () => {
attachOverlay({positionStrategy});
expect(overlayRef.overlayElement.style.justifyContent).toBe('center');
expect(overlayRef.hostElement.style.alignItems).toBe('center');
});
// TODO(crisbeto): investigate failure in older Safari
// it('should support offsets when centering', () => {
// originElement.style.top = '200px';
// originElement.style.left = '200px';
it('should support offsets when centering', () => {
originElement.style.top = '200px';
originElement.style.left = '200px';
// positionStrategy
// .withFlexibleWidth()
// .withFlexibleHeight()
// .withPositions([{
// overlayY: 'center',
// overlayX: 'center',
// originY: 'center',
// originX: 'center',
// offsetY: 20,
// offsetX: -15
// }]);
positionStrategy
.withFlexibleDimensions()
.withPush(false)
.withPositions([{
overlayY: 'center',
overlayX: 'center',
originY: 'center',
originX: 'center',
offsetY: 20,
offsetX: -15
}]);
// attachOverlay({positionStrategy});
attachOverlay({positionStrategy});
// const originRect = originElement.getBoundingClientRect();
// const originCenterY = originRect.top + (ORIGIN_HEIGHT / 2);
// const originCenterX = originRect.left + (ORIGIN_WIDTH / 2);
const originRect = originElement.getBoundingClientRect();
const originCenterX = originRect.left + (DEFAULT_WIDTH / 2);
const originCenterY = originRect.top + (DEFAULT_HEIGHT / 2);
// const overlayRect = overlayRef.overlayElement.getBoundingClientRect();
// const overlayCenterY = overlayRect.top + (OVERLAY_HEIGHT / 2);
// const overlayCenterX = overlayRect.left + (OVERLAY_WIDTH / 2);
const overlayRect = overlayRef.overlayElement.getBoundingClientRect();
const overlayCenterY = overlayRect.top + (OVERLAY_HEIGHT / 2);
const overlayCenterX = overlayRect.left + (OVERLAY_WIDTH / 2);
// expect(overlayRef.overlayElement.style.transform)
// .toBe('translateX(-15px) translateY(20px)');
// expect(Math.floor(overlayCenterY)).toBe(Math.floor(originCenterY) + 20);
// expect(Math.floor(overlayCenterX)).toBe(Math.floor(originCenterX) - 15);
// });
expect(overlayRef.overlayElement.style.transform)
.toBe('translateX(-15px) translateY(20px)');
expect(Math.floor(overlayCenterY)).toBe(Math.floor(originCenterY) + 20);
expect(Math.floor(overlayCenterX)).toBe(Math.floor(originCenterX) - 15);
});
it('should become scrollable when it hits the viewport edge with a flexible height', () => {
originElement.style.left = '200px';
originElement.style.bottom = `${OVERLAY_HEIGHT - 10}px`;
positionStrategy
.withFlexibleHeight()
.withFlexibleDimensions()
.withPush(false)
.withPositions([{
overlayY: 'top',
overlayX: 'start',
@@ -1107,7 +1105,8 @@ describe('FlexibleConnectedPositionStrategy', () => {
originElement.style.right = '-20px';
positionStrategy
.withFlexibleWidth()
.withFlexibleDimensions()
.withPush(false)
.withPositions([{
overlayY: 'top',
overlayX: 'start',
@@ -1127,7 +1126,7 @@ describe('FlexibleConnectedPositionStrategy', () => {
originElement.style.bottom = `${OVERLAY_HEIGHT - 10}px`;
positionStrategy
.withFlexibleHeight()
.withFlexibleDimensions()
.withPositions([{
overlayY: 'top',
overlayX: 'start',
@@ -1149,7 +1148,7 @@ describe('FlexibleConnectedPositionStrategy', () => {
originElement.style.right = '-20px';
positionStrategy
.withFlexibleWidth()
.withFlexibleDimensions()
.withPositions([{
overlayY: 'top',
overlayX: 'start',
@@ -1171,7 +1170,8 @@ describe('FlexibleConnectedPositionStrategy', () => {
originElement.style.right = '25px';
positionStrategy
.withFlexibleWidth()
.withFlexibleDimensions()
.withPush(false)
.withPositions([
{
originX: 'end',
@@ -1202,7 +1202,8 @@ describe('FlexibleConnectedPositionStrategy', () => {
originElement.style.bottom = `${OVERLAY_HEIGHT - 10}px`;
positionStrategy
.withFlexibleHeight()
.withFlexibleDimensions()
.withPush(false)
.withGrowAfterOpen()
.withPositions([{
overlayY: 'top',
@@ -1239,7 +1240,8 @@ describe('FlexibleConnectedPositionStrategy', () => {
window.scroll(0, 50);
positionStrategy
.withFlexibleHeight()
.withFlexibleDimensions()
.withPush(false)
.withPositions([{
overlayY: 'bottom',
overlayX: 'start',
@@ -1257,14 +1259,15 @@ describe('FlexibleConnectedPositionStrategy', () => {
window.scroll(0, 0);
document.body.removeChild(veryLargeElement);
});
it('should set the proper styles when the `bottom` value is exactly zero', () => {
originElement.style.position = 'fixed';
originElement.style.bottom = '0';
originElement.style.left = '200px';
positionStrategy
.withFlexibleWidth()
.withFlexibleHeight()
.withFlexibleDimensions()
.withPush(false)
.withPositions([{
overlayY: 'bottom',
overlayX: 'start',
@@ -1289,8 +1292,8 @@ describe('FlexibleConnectedPositionStrategy', () => {
originElement.style.left = '200px';
positionStrategy
.withFlexibleWidth()
.withFlexibleHeight()
.withFlexibleDimensions()
.withPush(false)
.withPositions([{
overlayY: 'top',
overlayX: 'start',
@@ -1315,8 +1318,8 @@ describe('FlexibleConnectedPositionStrategy', () => {
originElement.style.top = '200px';
positionStrategy
.withFlexibleWidth()
.withFlexibleHeight()
.withFlexibleDimensions()
.withPush(false)
.withPositions([{
overlayY: 'top',
overlayX: 'start',
@@ -1341,8 +1344,8 @@ describe('FlexibleConnectedPositionStrategy', () => {
originElement.style.top = '200px';
positionStrategy
.withFlexibleWidth()
.withFlexibleHeight()
.withFlexibleDimensions()
.withPush(false)
.withPositions([{
overlayY: 'top',
overlayX: 'end',
@@ -1368,7 +1371,8 @@ describe('FlexibleConnectedPositionStrategy', () => {
originElement.style.right = '200px';
positionStrategy
.withFlexibleHeight()
.withFlexibleDimensions()
.withPush(false)
.withViewportMargin(viewportMargin)
.withPositions([
{
@@ -1408,6 +1412,7 @@ describe('FlexibleConnectedPositionStrategy', () => {
// Create a strategy with knowledge of the scrollable container
const strategy = overlay.position()
.flexibleConnectedTo(new ElementRef(originElement))
.withPush(false)
.withPositions([{
originX: 'start',
originY: 'bottom',
@@ -1503,8 +1508,8 @@ describe('FlexibleConnectedPositionStrategy', () => {
attachOverlay({positionStrategy});
expect(overlayRef.overlayElement.style.left).toBeTruthy();
expect(overlayRef.overlayElement.style.right).toBeFalsy();
expect(overlayRef.hostElement.style.left).toBeTruthy();
expect(overlayRef.hostElement.style.right).toBeFalsy();
});
it('should use `right` when positioning an element at the end', () => {
@@ -1517,8 +1522,8 @@ describe('FlexibleConnectedPositionStrategy', () => {
attachOverlay({positionStrategy});
expect(overlayRef.overlayElement.style.right).toBeTruthy();
expect(overlayRef.overlayElement.style.left).toBeFalsy();
expect(overlayRef.hostElement.style.right).toBeTruthy();
expect(overlayRef.hostElement.style.left).toBeFalsy();
});
});
@@ -1537,8 +1542,8 @@ describe('FlexibleConnectedPositionStrategy', () => {
direction: 'rtl'
});
expect(overlayRef.overlayElement.style.right).toBeTruthy();
expect(overlayRef.overlayElement.style.left).toBeFalsy();
expect(overlayRef.hostElement.style.right).toBeTruthy();
expect(overlayRef.hostElement.style.left).toBeFalsy();
});
it('should use `left` when positioning an element at the end', () => {
@@ -1551,8 +1556,8 @@ describe('FlexibleConnectedPositionStrategy', () => {
attachOverlay({positionStrategy, direction: 'rtl'});
expect(overlayRef.overlayElement.style.left).toBeTruthy();
expect(overlayRef.overlayElement.style.right).toBeFalsy();
expect(overlayRef.hostElement.style.left).toBeTruthy();
expect(overlayRef.hostElement.style.right).toBeFalsy();
});
});
@@ -1567,8 +1572,8 @@ describe('FlexibleConnectedPositionStrategy', () => {
attachOverlay({positionStrategy});
expect(overlayRef.overlayElement.style.top).toBeTruthy();
expect(overlayRef.overlayElement.style.bottom).toBeFalsy();
expect(overlayRef.hostElement.style.top).toBeTruthy();
expect(overlayRef.hostElement.style.bottom).toBeFalsy();
});
it('should use `bottom` when positioning at element along the bottom', () => {
@@ -1581,8 +1586,8 @@ describe('FlexibleConnectedPositionStrategy', () => {
attachOverlay({positionStrategy});
expect(overlayRef.overlayElement.style.bottom).toBeTruthy();
expect(overlayRef.overlayElement.style.top).toBeFalsy();
expect(overlayRef.hostElement.style.bottom).toBeTruthy();
expect(overlayRef.hostElement.style.top).toBeFalsy();
});
});
@@ -51,11 +51,8 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
/** Whether the overlay can grow via flexible width/height after the initial open. */
private _growAfterOpen = false;
/** Whether the overlay's height can be constrained to fit within the viewport. */
private _hasFlexibleHeight = true;
/** Whether the overlay's width can be constrained to fit within the viewport. */
private _hasFlexibleWidth = true;
/** Whether the overlay's width and height can be constrained to fit within the viewport. */
private _hasFlexibleDimensions = true;
/** Whether the overlay position is locked. */
private _positionLocked = false;
@@ -167,6 +164,7 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
return;
}
this._resetOverlayElementStyles();
this._resetBoundingBoxStyles();
// We need the bounding rects for the origin and the overlay to determine how to position
@@ -329,15 +327,9 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
return this;
}
/** Sets whether the overlay's height can be constrained to fit within the viewport. */
withFlexibleHeight(flexibleHeight = true): this {
this._hasFlexibleHeight = flexibleHeight;
return this;
}
/** Sets whether the overlay's width can be constrained to fit within the viewport. */
withFlexibleWidth(flexibleWidth = true): this {
this._hasFlexibleWidth = flexibleWidth;
/** Sets whether the overlay's width and height can be constrained to fit within the viewport. */
withFlexibleDimensions(flexibleDimensions = true): this {
this._hasFlexibleDimensions = flexibleDimensions;
return this;
}
@@ -494,16 +486,16 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
* @param viewport The geometry of the viewport.
*/
private _canFitWithFlexibleDimensions(fit: OverlayFit, point: Point, viewport: ClientRect) {
if (this._hasFlexibleWidth || this._hasFlexibleWidth) {
if (this._hasFlexibleDimensions) {
const availableHeight = viewport.bottom - point.y;
const availableWidth = viewport.right - point.x;
const minHeight = this._overlayRef.getConfig().minHeight || 0;
const minWidth = this._overlayRef.getConfig().minWidth || 0;
const minHeight = this._overlayRef.getConfig().minHeight;
const minWidth = this._overlayRef.getConfig().minWidth;
const verticalFit = fit.fitsInViewportVertically ||
(this._hasFlexibleHeight && minHeight <= availableHeight);
(minHeight != null && minHeight <= availableHeight);
const horizontalFit = fit.fitsInViewportHorizontally ||
(this._hasFlexibleWidth && minWidth <= availableWidth);
(minWidth != null && minWidth <= availableWidth);
return verticalFit && horizontalFit;
}
@@ -664,34 +656,43 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
const styles = {} as CSSStyleDeclaration;
if (!this._hasFlexibleHeight || this._isPushed) {
styles.top = '0';
styles.bottom = '';
styles.height = '100%';
if (this._hasExactPosition()) {
styles.top = styles.left = '0';
styles.bottom = styles.right = '';
styles.width = styles.height = '100%';
} else {
const maxHeight = this._overlayRef.getConfig().maxHeight;
const maxWidth = this._overlayRef.getConfig().maxWidth;
styles.height = coerceCssPixelValue(boundingBoxRect.height);
styles.top = coerceCssPixelValue(boundingBoxRect.top);
styles.bottom = coerceCssPixelValue(boundingBoxRect.bottom);
styles.height = coerceCssPixelValue(boundingBoxRect.height);
}
if (!this._hasFlexibleWidth || this._isPushed) {
styles.left = '0';
styles.right = '';
styles.width = '100%';
} else {
styles.width = coerceCssPixelValue(boundingBoxRect.width);
styles.left = coerceCssPixelValue(boundingBoxRect.left);
styles.right = coerceCssPixelValue(boundingBoxRect.right);
styles.width = coerceCssPixelValue(boundingBoxRect.width);
}
const maxHeight = this._overlayRef.getConfig().maxHeight;
if (maxHeight && this._hasFlexibleHeight) {
styles.maxHeight = coerceCssPixelValue(maxHeight);
}
// Push the pane content towards the proper direction.
if (position.overlayX === 'center') {
styles.alignItems = 'center';
} else if (this._isRtl()) {
styles.alignItems = position.overlayX === 'end' ? 'flex-start' : 'flex-end';
} else {
styles.alignItems = position.overlayX === 'end' ? 'flex-end' : 'flex-start';
}
const maxWidth = this._overlayRef.getConfig().maxWidth;
if (maxWidth && this._hasFlexibleWidth) {
styles.maxWidth = coerceCssPixelValue(maxWidth);
if (position.overlayY === 'center') {
styles.justifyContent = 'center';
} else {
styles.justifyContent = position.overlayY === 'bottom' ? 'flex-end' : 'flex-start';
}
if (maxHeight) {
styles.maxHeight = coerceCssPixelValue(maxHeight);
}
if (maxWidth) {
styles.maxWidth = coerceCssPixelValue(maxWidth);
}
}
this._lastBoundingBoxSize = boundingBoxRect;
@@ -713,36 +714,26 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
} as CSSStyleDeclaration);
}
/** Sets positioning styles to the overlay element. */
private _setOverlayElementStyles(originPoint: Point, position: ConnectedPosition): void {
// Reset styles from any previous positioning.
const styles = {
/** Resets the styles for the overlay pane so that a new positioning can be computed. */
private _resetOverlayElementStyles() {
extendStyles(this._pane.style, {
top: '',
left: '',
bottom: '',
right: '',
} as CSSStyleDeclaration;
position: '',
} as CSSStyleDeclaration);
}
// Align the overlay panel to the appropriate edge of the
// size-constraining container unless using a 'center' position.
if (this._hasFlexibleWidth && position.overlayX !== 'center' && !this._isPushed) {
if (this._isRtl()) {
styles[position.overlayX === 'end' ? 'left' : 'right'] = '0';
} else {
styles[position.overlayX === 'end' ? 'right' : 'left'] = '0';
}
}
/** Sets positioning styles to the overlay element. */
private _setOverlayElementStyles(originPoint: Point, position: ConnectedPosition): void {
const styles = {} as CSSStyleDeclaration;
if (this._hasFlexibleHeight && position.overlayY !== 'center' && !this._isPushed) {
styles[position.overlayY === 'bottom' ? 'bottom' : 'top'] = '0';
}
if (!this._hasFlexibleHeight || this._isPushed) {
if (this._hasExactPosition()) {
extendStyles(styles, this._getExactOverlayY(position, originPoint));
}
if (!this._hasFlexibleWidth || this._isPushed) {
extendStyles(styles, this._getExactOverlayX(position, originPoint));
} else {
styles.position = 'static';
}
// Use a transform to apply the offsets. We do this because the `center` positions rely on
@@ -750,12 +741,12 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
// off the position. We also can't use margins, because they won't have an effect in some
// cases where the element doesn't have anything to "push off of". Finally, this works
// better both with flexible and non-flexible positioning.
let transformString = ' ';
let transformString = '';
let offsetX = this._getOffset(position, 'x');
let offsetY = this._getOffset(position, 'y');
if (offsetX) {
transformString += `translateX(${offsetX}px)`;
transformString += `translateX(${offsetX}px) `;
}
if (offsetY) {
@@ -767,21 +758,14 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
// If a maxWidth or maxHeight is specified on the overlay, we remove them. We do this because
// we need these values to both be set to "100%" for the automatic flexible sizing to work.
// The maxHeight and maxWidth are set on the boundingBox in order to enforce the constraint.
if (this._hasFlexibleHeight && this._overlayRef.getConfig().maxHeight) {
if (this._hasFlexibleDimensions && this._overlayRef.getConfig().maxHeight) {
styles.maxHeight = '';
}
if (this._hasFlexibleWidth && this._overlayRef.getConfig().maxWidth) {
if (this._hasFlexibleDimensions && this._overlayRef.getConfig().maxWidth) {
styles.maxWidth = '';
}
// Push the pane content towards the proper direction.
if (position.overlayX === 'center') {
styles.justifyContent = 'center';
} else {
styles.justifyContent = position.overlayX === 'end' ? 'flex-end' : 'flex-start';
}
extendStyles(this._pane.style, styles);
}
@@ -902,6 +886,11 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
return this._overlayRef.getConfig().direction === 'rtl';
}
/** Determines whether the overlay uses exact or flexible positioning. */
private _hasExactPosition() {
return !this._hasFlexibleDimensions || this._isPushed;
}
/** Retrieves the offset of a position along the x or y axis. */
private _getOffset(position: ConnectedPosition, axis: 'x' | 'y') {
if (axis === 'x') {
@@ -49,8 +49,7 @@ export class ConnectedOverlayDemo {
openWithConfig() {
const positionStrategy = this.overlay.position()
.flexibleConnectedTo(this._overlayOrigin.elementRef)
.withFlexibleHeight(this.isFlexible)
.withFlexibleWidth(this.isFlexible)
.withFlexibleDimensions(this.isFlexible)
.withPush(this.canPush)
.withViewportMargin(10)
.withGrowAfterOpen(true)
+1 -2
View File
@@ -531,8 +531,7 @@ export class MatAutocompleteTrigger implements ControlValueAccessor, OnDestroy {
private _getOverlayPosition(): PositionStrategy {
this._positionStrategy = this._overlay.position()
.flexibleConnectedTo(this._getConnectedElement())
.withFlexibleHeight(false)
.withFlexibleWidth(false)
.withFlexibleDimensions(false)
.withPush(false)
.withPositions([
{originX: 'start', originY: 'bottom', overlayX: 'start', overlayY: 'top'},
+1 -2
View File
@@ -484,8 +484,7 @@ export class MatDatepicker<D> implements OnDestroy, CanColor {
private _createPopupPositionStrategy(): PositionStrategy {
return this._overlay.position()
.flexibleConnectedTo(this._datepickerInput.getPopupConnectionElementRef())
.withFlexibleHeight(false)
.withFlexibleWidth(false)
.withFlexibleDimensions(false)
.withViewportMargin(8)
.withPush(false)
.withPositions([
+3 -3
View File
@@ -482,7 +482,7 @@ describe('MatMenu', () => {
// Push trigger to the right side of viewport, so it doesn't have space to open
// in its default "after" position on the right side.
trigger.style.position = 'fixed';
trigger.style.right = '-50px';
trigger.style.right = '0';
trigger.style.top = '200px';
fixture.componentInstance.trigger.openMenu();
@@ -541,8 +541,8 @@ describe('MatMenu', () => {
// push trigger to the bottom, right part of viewport, so it doesn't have space to open
// in its default "after below" position.
trigger.style.position = 'fixed';
trigger.style.right = '-50px';
trigger.style.bottom = '65px';
trigger.style.right = '0';
trigger.style.bottom = '0';
fixture.componentInstance.trigger.openMenu();
fixture.detectChanges();
+1 -2
View File
@@ -309,8 +309,7 @@ export class MatTooltip implements OnDestroy {
// Create connected position strategy that listens for scroll events to reposition.
const strategy = this._overlay.position()
.flexibleConnectedTo(this._elementRef)
.withFlexibleHeight(false)
.withFlexibleWidth(false)
.withFlexibleDimensions(false)
.withViewportMargin(8)
.withPositions([
{...origin.main, ...overlay.main},