Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions BREAKING.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ This is a comprehensive list of the breaking changes introduced in the major ver

- [Components](#components)
* [Header](#header)
* [Popover](#popover)
* [Tab Bar](#tab-bar)
* [Toast](#toast)
* [Toolbar](#toolbar)
Expand Down Expand Up @@ -42,6 +43,12 @@ ion-header.header-collapse-condense ion-toolbar:last-of-type {
}
```

#### Popover

Converted `ion-popover` to use [Shadow DOM](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM).

If you were targeting the internals of `ion-popover` in your CSS, you will need to target the `backdrop`, `arrow`, or `content` [Shadow Parts](https://ionicframework.com/docs/theming/css-shadow-parts) instead.

#### Tab Bar

The default iOS tab bar background color has been updated to better reflect the latest iOS styles. The new default value is:
Expand Down
39 changes: 39 additions & 0 deletions angular/src/directives/overlays/ion-popover.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/* eslint-disable */
/* tslint:disable */
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChild, ElementRef, EventEmitter, NgZone, TemplateRef } from "@angular/core";
import { ProxyCmp, proxyOutputs } from "../proxies-utils";
import { Components } from "@ionic/core";
export declare interface IonPopover extends Components.IonPopover {
}
@ProxyCmp({ inputs: ["animated", "backdropDismiss", "cssClass", "enterAnimation", "event", "isOpen", "keyboardClose", "leaveAnimation", "mode", "showBackdrop", "translucent"], "methods": ["present", "dismiss", "onDidDismiss", "onWillDismiss"] })
@Component({ selector: "ion-popover", changeDetection: ChangeDetectionStrategy.OnPush, template: `<ng-container [ngTemplateOutlet]="template" *ngIf="isCmpOpen"></ng-container>`, inputs: ["animated", "backdropDismiss", "component", "componentProps", "cssClass", "enterAnimation", "event", "isOpen", "keyboardClose", "leaveAnimation", "mode", "showBackdrop", "translucent"] })
export class IonPopover {
@ContentChild(TemplateRef, { static: false }) template: TemplateRef<any>;

ionPopoverDidPresent!: EventEmitter<CustomEvent>;
ionPopoverWillPresent!: EventEmitter<CustomEvent>;
ionPopoverWillDismiss!: EventEmitter<CustomEvent>;
ionPopoverDidDismiss!: EventEmitter<CustomEvent>;
didPresent!: EventEmitter<CustomEvent>;
willPresent!: EventEmitter<CustomEvent>;
willDismiss!: EventEmitter<CustomEvent>;
didDismiss!: EventEmitter<CustomEvent>;
isCmpOpen: boolean = false;

protected el: HTMLElement;
constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) {
c.detach();
this.el = r.nativeElement;

this.el.addEventListener('willPresent', () => {
this.isCmpOpen = true;
c.detectChanges();
});
this.el.addEventListener('didDismiss', () => {
this.isCmpOpen = false;
c.detectChanges();
});

proxyOutputs(this, this.el, ["ionPopoverDidPresent", "ionPopoverWillPresent", "ionPopoverWillDismiss", "ionPopoverDidDismiss", "didPresent", "willPresent", "willDismiss", "didDismiss"]);
}
}
2 changes: 2 additions & 0 deletions angular/src/ionic-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { IonRouterOutlet } from './directives/navigation/ion-router-outlet';
import { IonTabs } from './directives/navigation/ion-tabs';
import { NavDelegate } from './directives/navigation/nav-delegate';
import { RouterLinkDelegate } from './directives/navigation/router-link-delegate';
import { IonPopover } from './directives/overlays/ion-popover';
import { IonAccordion, IonAccordionGroup, IonApp, IonAvatar, IonBackButton, IonBackdrop, IonBadge, IonButton, IonButtons, IonCard, IonCardContent, IonCardHeader, IonCardSubtitle, IonCardTitle, IonCheckbox, IonChip, IonCol, IonContent, IonDatetime, IonFab, IonFabButton, IonFabList, IonFooter, IonGrid, IonHeader, IonIcon, IonImg, IonInfiniteScroll, IonInfiniteScrollContent, IonInput, IonItem, IonItemDivider, IonItemGroup, IonItemOption, IonItemOptions, IonItemSliding, IonLabel, IonList, IonListHeader, IonMenu, IonMenuButton, IonMenuToggle, IonNav, IonNavLink, IonNote, IonProgressBar, IonRadio, IonRadioGroup, IonRange, IonRefresher, IonRefresherContent, IonReorder, IonReorderGroup, IonRippleEffect, IonRow, IonSearchbar, IonSegment, IonSegmentButton, IonSelect, IonSelectOption, IonSkeletonText, IonSlide, IonSlides, IonSpinner, IonSplitPane, IonTabBar, IonTabButton, IonText, IonTextarea, IonThumbnail, IonTitle, IonToggle, IonToolbar } from './directives/proxies';
import { VirtualFooter } from './directives/virtual-scroll/virtual-footer';
import { VirtualHeader } from './directives/virtual-scroll/virtual-header';
Expand Down Expand Up @@ -70,6 +71,7 @@ const DECLARATIONS = [
IonNav,
IonNavLink,
IonNote,
IonPopover,
IonProgressBar,
IonRadio,
IonRadioGroup,
Expand Down
13 changes: 10 additions & 3 deletions core/api.txt
Original file line number Diff line number Diff line change
Expand Up @@ -823,14 +823,14 @@ ion-picker,css-prop,--min-height
ion-picker,css-prop,--min-width
ion-picker,css-prop,--width

ion-popover,scoped
ion-popover,shadow
ion-popover,prop,animated,boolean,true,false,false
ion-popover,prop,backdropDismiss,boolean,true,false,false
ion-popover,prop,component,Function | HTMLElement | null | string,undefined,true,false
ion-popover,prop,component,Function | HTMLElement | null | string | undefined,undefined,false,false
ion-popover,prop,componentProps,undefined | { [key: string]: any; },undefined,false,false
ion-popover,prop,cssClass,string | string[] | undefined,undefined,false,false
ion-popover,prop,enterAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
ion-popover,prop,event,any,undefined,false,false
ion-popover,prop,isOpen,boolean,false,false,false
ion-popover,prop,keyboardClose,boolean,true,false,false
ion-popover,prop,leaveAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
ion-popover,prop,mode,"ios" | "md",undefined,false,false
Expand All @@ -840,10 +840,14 @@ ion-popover,method,dismiss,dismiss(data?: any, role?: string | undefined) => Pro
ion-popover,method,onDidDismiss,onDidDismiss<T = any>() => Promise<OverlayEventDetail<T>>
ion-popover,method,onWillDismiss,onWillDismiss<T = any>() => Promise<OverlayEventDetail<T>>
ion-popover,method,present,present() => Promise<void>
ion-popover,event,didDismiss,OverlayEventDetail<any>,true
ion-popover,event,didPresent,void,true
ion-popover,event,ionPopoverDidDismiss,OverlayEventDetail<any>,true
ion-popover,event,ionPopoverDidPresent,void,true
ion-popover,event,ionPopoverWillDismiss,OverlayEventDetail<any>,true
ion-popover,event,ionPopoverWillPresent,void,true
ion-popover,event,willDismiss,OverlayEventDetail<any>,true
ion-popover,event,willPresent,void,true
ion-popover,css-prop,--backdrop-opacity
ion-popover,css-prop,--background
ion-popover,css-prop,--box-shadow
Expand All @@ -853,6 +857,9 @@ ion-popover,css-prop,--max-width
ion-popover,css-prop,--min-height
ion-popover,css-prop,--min-width
ion-popover,css-prop,--width
ion-popover,part,arrow
ion-popover,part,backdrop
ion-popover,part,content

ion-progress-bar,shadow
ion-progress-bar,prop,buffer,number,1,false,false
Expand Down
38 changes: 32 additions & 6 deletions core/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1658,11 +1658,11 @@ export namespace Components {
*/
"backdropDismiss": boolean;
/**
* The component to display inside of the popover.
* The component to display inside of the popover. You only need to use this if you are not using a JavaScript framework. Otherwise, you can just slot your component inside of `ion-popover`.
*/
"component": ComponentRef;
"component"?: ComponentRef;
/**
* The data to pass to the popover component.
* The data to pass to the popover component. You only need to use this if you are not using a JavaScript framework. Otherwise, you can just set the props directly on your component.
*/
"componentProps"?: ComponentProps;
/**
Expand All @@ -1684,6 +1684,11 @@ export namespace Components {
* The event to pass to the popover animation.
*/
"event": any;
"inline": boolean;
/**
* If `true`, the popover will open. If `false`, the popover will close. Use this if you need finer grained control over presentation, otherwise just use the popoverController or the `trigger` property. Note: `isOpen` will not automatically be set back to `false` when the popover dismisses. You will need to do that in your code.
*/
"isOpen": boolean;
/**
* If `true`, the keyboard will be automatically dismissed when the overlay is presented.
*/
Expand Down Expand Up @@ -4990,11 +4995,11 @@ declare namespace LocalJSX {
*/
"backdropDismiss"?: boolean;
/**
* The component to display inside of the popover.
* The component to display inside of the popover. You only need to use this if you are not using a JavaScript framework. Otherwise, you can just slot your component inside of `ion-popover`.
*/
"component": ComponentRef;
"component"?: ComponentRef;
/**
* The data to pass to the popover component.
* The data to pass to the popover component. You only need to use this if you are not using a JavaScript framework. Otherwise, you can just set the props directly on your component.
*/
"componentProps"?: ComponentProps;
/**
Expand All @@ -5010,6 +5015,11 @@ declare namespace LocalJSX {
* The event to pass to the popover animation.
*/
"event"?: any;
"inline"?: boolean;
/**
* If `true`, the popover will open. If `false`, the popover will close. Use this if you need finer grained control over presentation, otherwise just use the popoverController or the `trigger` property. Note: `isOpen` will not automatically be set back to `false` when the popover dismisses. You will need to do that in your code.
*/
"isOpen"?: boolean;
/**
* If `true`, the keyboard will be automatically dismissed when the overlay is presented.
*/
Expand All @@ -5022,6 +5032,14 @@ declare namespace LocalJSX {
* The mode determines which platform styles to use.
*/
"mode"?: "ios" | "md";
/**
* Emitted after the popover has dismissed. Shorthand for ionPopoverDidDismiss.
*/
"onDidDismiss"?: (event: CustomEvent<OverlayEventDetail>) => void;
/**
* Emitted after the popover has presented. Shorthand for ionPopoverWillDismiss.
*/
"onDidPresent"?: (event: CustomEvent<void>) => void;
/**
* Emitted after the popover has dismissed.
*/
Expand All @@ -5038,6 +5056,14 @@ declare namespace LocalJSX {
* Emitted before the popover has presented.
*/
"onIonPopoverWillPresent"?: (event: CustomEvent<void>) => void;
/**
* Emitted before the popover has dismissed. Shorthand for ionPopoverWillDismiss.
*/
"onWillDismiss"?: (event: CustomEvent<OverlayEventDetail>) => void;
/**
* Emitted before the popover has presented. Shorthand for ionPopoverWillPresent.
*/
"onWillPresent"?: (event: CustomEvent<void>) => void;
"overlayIndex": number;
/**
* If `true`, a backdrop will be displayed behind the popover.
Expand Down
11 changes: 6 additions & 5 deletions core/src/components/popover/animations/ios.enter.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Animation } from '../../../interface';
import { createAnimation } from '../../../utils/animation/animation';
import { getElementRoot } from '../../../utils/helpers';

/**
* iOS Popover Enter Animation
Expand All @@ -8,7 +9,8 @@ export const iosEnterAnimation = (baseEl: HTMLElement, ev?: Event): Animation =>
let originY = 'top';
let originX = 'left';

const contentEl = baseEl.querySelector('.popover-content') as HTMLElement;
const root = getElementRoot(baseEl);
const contentEl = root.querySelector('.popover-content') as HTMLElement;
const contentDimentions = contentEl.getBoundingClientRect();
const contentWidth = contentDimentions.width;
const contentHeight = contentDimentions.height;
Expand All @@ -24,7 +26,7 @@ export const iosEnterAnimation = (baseEl: HTMLElement, ev?: Event): Animation =>
const targetWidth = (targetDim && targetDim.width) || 0;
const targetHeight = (targetDim && targetDim.height) || 0;

const arrowEl = baseEl.querySelector('.popover-arrow') as HTMLElement;
const arrowEl = root.querySelector('.popover-arrow') as HTMLElement;

const arrowDim = arrowEl.getBoundingClientRect();
const arrowWidth = arrowDim.width;
Expand Down Expand Up @@ -103,19 +105,18 @@ export const iosEnterAnimation = (baseEl: HTMLElement, ev?: Event): Animation =>
const wrapperAnimation = createAnimation();

backdropAnimation
.addElement(baseEl.querySelector('ion-backdrop')!)
.addElement(root.querySelector('ion-backdrop')!)
.fromTo('opacity', 0.01, 'var(--backdrop-opacity)')
.beforeStyles({
'pointer-events': 'none'
})
.afterClearStyles(['pointer-events']);

wrapperAnimation
.addElement(baseEl.querySelector('.popover-wrapper')!)
.addElement(root.querySelector('.popover-wrapper')!)
.fromTo('opacity', 0.01, 1);

return baseAnimation
.addElement(baseEl)
.easing('ease')
.duration(100)
.addAnimation([backdropAnimation, wrapperAnimation]);
Expand Down
7 changes: 4 additions & 3 deletions core/src/components/popover/animations/ios.leave.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
import { Animation } from '../../../interface';
import { createAnimation } from '../../../utils/animation/animation';
import { getElementRoot } from '../../../utils/helpers';

/**
* iOS Popover Leave Animation
*/
export const iosLeaveAnimation = (baseEl: HTMLElement): Animation => {
const root = getElementRoot(baseEl);
const baseAnimation = createAnimation();
const backdropAnimation = createAnimation();
const wrapperAnimation = createAnimation();

backdropAnimation
.addElement(baseEl.querySelector('ion-backdrop')!)
.addElement(root.querySelector('ion-backdrop')!)
.fromTo('opacity', 'var(--backdrop-opacity)', 0);

wrapperAnimation
.addElement(baseEl.querySelector('.popover-wrapper')!)
.addElement(root.querySelector('.popover-wrapper')!)
.fromTo('opacity', 0.99, 0);

return baseAnimation
.addElement(baseEl)
.easing('ease')
.duration(500)
.addAnimation([backdropAnimation, wrapperAnimation]);
Expand Down
11 changes: 6 additions & 5 deletions core/src/components/popover/animations/md.enter.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Animation } from '../../../interface';
import { createAnimation } from '../../../utils/animation/animation';
import { getElementRoot } from '../../../utils/helpers';

/**
* Md Popover Enter Animation
Expand All @@ -12,7 +13,8 @@ export const mdEnterAnimation = (baseEl: HTMLElement, ev?: Event): Animation =>
let originY = 'top';
let originX = isRTL ? 'right' : 'left';

const contentEl = baseEl.querySelector('.popover-content') as HTMLElement;
const root = getElementRoot(baseEl);
const contentEl = root.querySelector('.popover-content') as HTMLElement;
const contentDimentions = contentEl.getBoundingClientRect();
const contentWidth = contentDimentions.width;
const contentHeight = contentDimentions.height;
Expand Down Expand Up @@ -85,15 +87,15 @@ export const mdEnterAnimation = (baseEl: HTMLElement, ev?: Event): Animation =>
const viewportAnimation = createAnimation();

backdropAnimation
.addElement(baseEl.querySelector('ion-backdrop')!)
.addElement(root.querySelector('ion-backdrop')!)
.fromTo('opacity', 0.01, 'var(--backdrop-opacity)')
.beforeStyles({
'pointer-events': 'none'
})
.afterClearStyles(['pointer-events']);

wrapperAnimation
.addElement(baseEl.querySelector('.popover-wrapper')!)
.addElement(root.querySelector('.popover-wrapper')!)
.fromTo('opacity', 0.01, 1);

contentAnimation
Expand All @@ -106,11 +108,10 @@ export const mdEnterAnimation = (baseEl: HTMLElement, ev?: Event): Animation =>
.fromTo('transform', 'scale(0.001)', 'scale(1)');

viewportAnimation
.addElement(baseEl.querySelector('.popover-viewport')!)
.addElement(root.querySelector('.popover-viewport')!)
.fromTo('opacity', 0.01, 1);

return baseAnimation
.addElement(baseEl)
.easing('cubic-bezier(0.36,0.66,0.04,1)')
.duration(300)
.addAnimation([backdropAnimation, wrapperAnimation, contentAnimation, viewportAnimation]);
Expand Down
7 changes: 4 additions & 3 deletions core/src/components/popover/animations/md.leave.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
import { Animation } from '../../../interface';
import { createAnimation } from '../../../utils/animation/animation';
import { getElementRoot } from '../../../utils/helpers';

/**
* Md Popover Leave Animation
*/
export const mdLeaveAnimation = (baseEl: HTMLElement): Animation => {
const root = getElementRoot(baseEl);
const baseAnimation = createAnimation();
const backdropAnimation = createAnimation();
const wrapperAnimation = createAnimation();

backdropAnimation
.addElement(baseEl.querySelector('ion-backdrop')!)
.addElement(root.querySelector('ion-backdrop')!)
.fromTo('opacity', 'var(--backdrop-opacity)', 0);

wrapperAnimation
.addElement(baseEl.querySelector('.popover-wrapper')!)
.addElement(root.querySelector('.popover-wrapper')!)
.fromTo('opacity', 0.99, 0);

return baseAnimation
.addElement(baseEl)
.easing('ease')
.duration(500)
.addAnimation([backdropAnimation, wrapperAnimation]);
Expand Down
7 changes: 7 additions & 0 deletions core/src/components/popover/popover.scss
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@
color: $popover-text-color;

z-index: $z-index-overlay;

pointer-events: none;
}

:host(.popover-interactive) .popover-content,
:host(.popover-interactive) ion-backdrop {
pointer-events: auto;
}

:host(.overlay-hidden) {
Expand Down
Loading