Skip to content

Commit

Permalink
fix(popover): inline popover positioning with fit-content or auto wid…
Browse files Browse the repository at this point in the history
…th (#26230)

Resolves #24716
  • Loading branch information
sean-perkins committed Nov 10, 2022
1 parent 2080ddc commit 0a8a958
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 2 deletions.
2 changes: 1 addition & 1 deletion angular/src/directives/overlays/popover.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ export class IonPopover {
constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) {
this.el = r.nativeElement;

this.el.addEventListener('willPresent', () => {
this.el.addEventListener('ionMount', () => {
this.isCmpOpen = true;
c.detectChanges();
});
Expand Down
4 changes: 4 additions & 0 deletions core/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5907,6 +5907,10 @@ declare namespace LocalJSX {
* Emitted after the popover has presented. Shorthand for ionPopoverWillDismiss.
*/
"onDidPresent"?: (event: IonPopoverCustomEvent<void>) => void;
/**
* Emitted before the popover has presented, but after the component has been mounted in the DOM. This event exists for ion-popover to resolve an issue with the popover and the lazy build, that the transition is unable to get the correct dimensions of the popover with auto sizing. This is not required for other overlays, since the existing overlay transitions are not effected by auto sizing content.
*/
"onIonMount"?: (event: IonPopoverCustomEvent<void>) => void;
/**
* Emitted after the popover has dismissed.
*/
Expand Down
34 changes: 33 additions & 1 deletion core/src/components/popover/popover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,12 @@ import { iosEnterAnimation } from './animations/ios.enter';
import { iosLeaveAnimation } from './animations/ios.leave';
import { mdEnterAnimation } from './animations/md.enter';
import { mdLeaveAnimation } from './animations/md.leave';
import { configureDismissInteraction, configureKeyboardInteraction, configureTriggerInteraction } from './utils';
import {
configureDismissInteraction,
configureKeyboardInteraction,
configureTriggerInteraction,
waitOneFrame,
} from './utils';

/**
* @virtualProp {"ios" | "md"} mode - The mode determines which platform styles to use.
Expand Down Expand Up @@ -310,6 +315,19 @@ export class Popover implements ComponentInterface, PopoverInterface {
*/
@Event({ eventName: 'didDismiss' }) didDismissShorthand!: EventEmitter<OverlayEventDetail>;

/**
* Emitted before the popover has presented, but after the component
* has been mounted in the DOM.
* This event exists for ion-popover to resolve an issue with the
* popover and the lazy build, that the transition is unable to get
* the correct dimensions of the popover with auto sizing.
* This is not required for other overlays, since the existing
* overlay transitions are not effected by auto sizing content.
*
* @internal
*/
@Event() ionMount!: EventEmitter<void>;

connectedCallback() {
const { configureTriggerInteraction, el } = this;

Expand Down Expand Up @@ -446,6 +464,20 @@ export class Popover implements ComponentInterface, PopoverInterface {
}
this.configureDismissInteraction();

// TODO: FW-2773: Apply this to only the lazy build.
if (inline === true) {
/**
* ionMount only needs to be emitted if the popover is inline.
*/
this.ionMount.emit();
/**
* Wait one raf before presenting the popover.
* This allows the lazy build enough time to
* calculate the popover dimensions for the animation.
*/
await waitOneFrame();
}

this.currentTransition = present(this, 'popoverEnter', iosEnterAnimation, mdEnterAnimation, {
event: event || this.event,
size: this.size,
Expand Down
4 changes: 4 additions & 0 deletions core/src/components/popover/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -928,3 +928,7 @@ export const shouldShowArrow = (side: PositionSide, didAdjustBounds = false, ev?

return true;
};

export const waitOneFrame = () => {
return new Promise<void>((resolve) => raf(() => resolve()));
};

0 comments on commit 0a8a958

Please sign in to comment.