diff --git a/BREAKING.md b/BREAKING.md
index 8735baa995..a7d4ee2af5 100644
--- a/BREAKING.md
+++ b/BREAKING.md
@@ -17,6 +17,7 @@ This is a comprehensive list of the breaking changes introduced in the major ver
- [Accordion Group](#version-7x-accordion-group)
- [Checkbox](#version-7x-checkbox)
- [Input](#version-7x-input)
+ - [Modal](#version-7x-modal)
- [Overlays](#version-7x-overlays)
- [Range](#version-7x-range)
- [Segment](#version-7x-segment)
@@ -71,6 +72,11 @@ This section details the desktop browser, JavaScript framework, and mobile platf
- The `debounce` property has been updated to control the timing in milliseconds to delay the event emission of the `ionInput` event after each keystroke. Previously it would delay the event emission of `ionChange`.
+
Modal
+
+- The `swipeToClose` property has been removed in favor of `canDismiss`.
+- The `canDismiss` property now defaults to `true` and can no longer be set to `undefined`.
+
Overlays
Ionic now listens on the `keydown` event instead of the `keyup` event when determining when to dismiss overlays via the "Escape" key. Any applications that were listening on `keyup` to suppress this behavior should listen on `keydown` instead.
diff --git a/angular/src/directives/overlays/modal.ts b/angular/src/directives/overlays/modal.ts
index 960b5d2242..4873bceeb0 100644
--- a/angular/src/directives/overlays/modal.ts
+++ b/angular/src/directives/overlays/modal.ts
@@ -71,7 +71,6 @@ export declare interface IonModal extends Components.IonModal {
'mode',
'presentingElement',
'showBackdrop',
- 'swipeToClose',
'translucent',
'trigger',
],
@@ -102,7 +101,6 @@ export declare interface IonModal extends Components.IonModal {
'mode',
'presentingElement',
'showBackdrop',
- 'swipeToClose',
'translucent',
'trigger',
],
diff --git a/core/api.txt b/core/api.txt
index b4ccf42d1a..0979694afe 100644
--- a/core/api.txt
+++ b/core/api.txt
@@ -778,7 +778,7 @@ ion-modal,prop,animated,boolean,true,false,false
ion-modal,prop,backdropBreakpoint,number,0,false,false
ion-modal,prop,backdropDismiss,boolean,true,false,false
ion-modal,prop,breakpoints,number[] | undefined,undefined,false,false
-ion-modal,prop,canDismiss,(() => Promise) | boolean | undefined,undefined,false,false
+ion-modal,prop,canDismiss,(() => Promise) | boolean,true,false,false
ion-modal,prop,enterAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
ion-modal,prop,handle,boolean | undefined,undefined,false,false
ion-modal,prop,handleBehavior,"cycle" | "none" | undefined,'none',false,false
@@ -791,7 +791,6 @@ ion-modal,prop,leaveAnimation,((baseEl: any, opts?: any) => Animation) | undefin
ion-modal,prop,mode,"ios" | "md",undefined,false,false
ion-modal,prop,presentingElement,HTMLElement | undefined,undefined,false,false
ion-modal,prop,showBackdrop,boolean,true,false,false
-ion-modal,prop,swipeToClose,boolean,false,false,false
ion-modal,prop,trigger,string | undefined,undefined,false,false
ion-modal,method,dismiss,dismiss(data?: any, role?: string | undefined) => Promise
ion-modal,method,getCurrentBreakpoint,getCurrentBreakpoint() => Promise
diff --git a/core/src/components.d.ts b/core/src/components.d.ts
index 78a4cbbe05..b49f14998e 100644
--- a/core/src/components.d.ts
+++ b/core/src/components.d.ts
@@ -1547,7 +1547,7 @@ export namespace Components {
/**
* Determines whether or not a modal can dismiss when calling the `dismiss` method. If the value is `true` or the value's function returns `true`, the modal will close when trying to dismiss. If the value is `false` or the value's function returns `false`, the modal will not close when trying to dismiss.
*/
- "canDismiss"?: undefined | boolean | (() => Promise);
+ "canDismiss": boolean | (() => Promise);
/**
* The component to display inside of the modal.
*/
@@ -1637,11 +1637,6 @@ export namespace Components {
* If `true`, a backdrop will be displayed behind the modal. This property controls whether or not the backdrop darkens the screen when the modal is presented. It does not control whether or not the backdrop is active or present in the DOM.
*/
"showBackdrop": boolean;
- /**
- * If `true`, the modal can be swiped to dismiss. Only applies in iOS mode.
- * @deprecated - To prevent modals from dismissing, use canDismiss instead.
- */
- "swipeToClose": boolean;
/**
* An ID corresponding to the trigger element that causes the modal to open when clicked.
*/
@@ -5332,7 +5327,7 @@ declare namespace LocalJSX {
/**
* Determines whether or not a modal can dismiss when calling the `dismiss` method. If the value is `true` or the value's function returns `true`, the modal will close when trying to dismiss. If the value is `false` or the value's function returns `false`, the modal will not close when trying to dismiss.
*/
- "canDismiss"?: undefined | boolean | (() => Promise);
+ "canDismiss"?: boolean | (() => Promise);
/**
* The component to display inside of the modal.
*/
@@ -5432,11 +5427,6 @@ declare namespace LocalJSX {
* If `true`, a backdrop will be displayed behind the modal. This property controls whether or not the backdrop darkens the screen when the modal is presented. It does not control whether or not the backdrop is active or present in the DOM.
*/
"showBackdrop"?: boolean;
- /**
- * If `true`, the modal can be swiped to dismiss. Only applies in iOS mode.
- * @deprecated - To prevent modals from dismissing, use canDismiss instead.
- */
- "swipeToClose"?: boolean;
/**
* An ID corresponding to the trigger element that causes the modal to open when clicked.
*/
diff --git a/core/src/components/modal/modal-interface.ts b/core/src/components/modal/modal-interface.ts
index cbfe9a045a..354e41680a 100644
--- a/core/src/components/modal/modal-interface.ts
+++ b/core/src/components/modal/modal-interface.ts
@@ -9,11 +9,6 @@ export interface ModalOptions {
cssClass?: string | string[];
delegate?: FrameworkDelegate;
animated?: boolean;
- /**
- * If `true`, the modal can be swiped to dismiss. Only applies in iOS mode.
- * @deprecated - To prevent modals from dismissing, use canDismiss instead.
- */
- swipeToClose?: boolean;
canDismiss?: boolean | (() => Promise);
mode?: Mode;
diff --git a/core/src/components/modal/modal.tsx b/core/src/components/modal/modal.tsx
index c718441a43..96b9a9a1b4 100644
--- a/core/src/components/modal/modal.tsx
+++ b/core/src/components/modal/modal.tsx
@@ -193,12 +193,6 @@ export class Modal implements ComponentInterface, OverlayInterface {
*/
@Prop() animated = true;
- /**
- * If `true`, the modal can be swiped to dismiss. Only applies in iOS mode.
- * @deprecated - To prevent modals from dismissing, use canDismiss instead.
- */
- @Prop() swipeToClose = false;
-
/**
* The element that presented the modal. This is used for card presentation effects
* and for stacking multiple modals on top of each other. Only applies in iOS mode.
@@ -250,14 +244,6 @@ export class Modal implements ComponentInterface, OverlayInterface {
*/
@Prop() keepContentsMounted = false;
- /**
- * TODO (FW-937)
- * This needs to default to true in the next
- * major release. We default it to undefined
- * so we can force the card modal to be swipeable
- * when using canDismiss.
- */
-
/**
* Determines whether or not a modal can dismiss
* when calling the `dismiss` method.
@@ -265,7 +251,7 @@ export class Modal implements ComponentInterface, OverlayInterface {
* If the value is `true` or the value's function returns `true`, the modal will close when trying to dismiss.
* If the value is `false` or the value's function returns `false`, the modal will not close when trying to dismiss.
*/
- @Prop() canDismiss?: undefined | boolean | (() => Promise);
+ @Prop() canDismiss: boolean | (() => Promise) = true;
/**
* Emitted after the modal has presented.
@@ -316,15 +302,6 @@ export class Modal implements ComponentInterface, OverlayInterface {
*/
@Event({ eventName: 'didDismiss' }) didDismissShorthand!: EventEmitter;
- @Watch('swipeToClose')
- async swipeToCloseChanged(enable: boolean) {
- if (this.gesture) {
- this.gesture.enable(enable);
- } else if (enable) {
- await this.initSwipeToClose();
- }
- }
-
breakpointsChanged(breakpoints: number[] | undefined) {
if (breakpoints !== undefined) {
this.sortedBreakpoints = breakpoints.sort((a, b) => a - b);
@@ -336,7 +313,7 @@ export class Modal implements ComponentInterface, OverlayInterface {
}
componentWillLoad() {
- const { breakpoints, initialBreakpoint, swipeToClose, el } = this;
+ const { breakpoints, initialBreakpoint, el } = this;
this.inheritedAttributes = inheritAttributes(el, ['role']);
@@ -354,12 +331,6 @@ export class Modal implements ComponentInterface, OverlayInterface {
if (breakpoints !== undefined && initialBreakpoint !== undefined && !breakpoints.includes(initialBreakpoint)) {
printIonWarning('Your breakpoints array must include the initialBreakpoint value.');
}
-
- if (swipeToClose) {
- printIonWarning(
- 'swipeToClose has been deprecated in favor of canDismiss.\n\nIf you want a card modal to be swipeable, set canDismiss to `true`. In the next major release of Ionic, swipeToClose will be removed, and all card modals will be swipeable by default.'
- );
- }
}
componentDidLoad() {
@@ -441,14 +412,6 @@ export class Modal implements ComponentInterface, OverlayInterface {
private async checkCanDismiss() {
const { canDismiss } = this;
- /**
- * TODO (FW-937) - Remove the following check in
- * the next major release of Ionic.
- */
- if (canDismiss === undefined) {
- return true;
- }
-
if (typeof canDismiss === 'function') {
return canDismiss();
}
@@ -465,6 +428,8 @@ export class Modal implements ComponentInterface, OverlayInterface {
return;
}
+ const { presentingElement } = this;
+
/**
* When using an inline modal
* and dismissing a modal it is possible to
@@ -496,21 +461,12 @@ export class Modal implements ComponentInterface, OverlayInterface {
writeTask(() => this.el.classList.add('show-modal'));
this.currentTransition = present(this, 'modalEnter', iosEnterAnimation, mdEnterAnimation, {
- presentingEl: this.presentingElement,
+ presentingEl: presentingElement,
currentBreakpoint: this.initialBreakpoint,
backdropBreakpoint: this.backdropBreakpoint,
});
- /**
- * TODO (FW-937) - In the next major release of Ionic, all card modals
- * will be swipeable by default. canDismiss will be used to determine if the
- * modal can be dismissed. This check should change to check the presence of
- * presentingElement instead.
- *
- * If we did not do this check, then not using swipeToClose would mean you could
- * not run canDismiss on swipe as there would be no swipe gesture created.
- */
- const hasCardModal = this.swipeToClose || (this.canDismiss !== undefined && this.presentingElement !== undefined);
+ const hasCardModal = presentingElement !== undefined;
/**
* We need to change the status bar at the
@@ -676,13 +632,14 @@ export class Modal implements ComponentInterface, OverlayInterface {
return false;
}
+ const { presentingElement } = this;
+
/**
* We need to start the status bar change
* before the animation so that the change
* finishes when the dismiss animation does.
- * TODO (FW-937)
*/
- const hasCardModal = this.swipeToClose || (this.canDismiss !== undefined && this.presentingElement !== undefined);
+ const hasCardModal = presentingElement !== undefined;
if (hasCardModal && getIonMode(this) === 'ios') {
setCardStatusBarDefault();
}
@@ -707,7 +664,7 @@ export class Modal implements ComponentInterface, OverlayInterface {
const enteringAnimation = activeAnimations.get(this) || [];
this.currentTransition = dismiss(this, data, role, 'modalLeave', iosLeaveAnimation, mdLeaveAnimation, {
- presentingEl: this.presentingElement,
+ presentingEl: presentingElement,
currentBreakpoint: this.currentBreakpoint || this.initialBreakpoint,
backdropBreakpoint: this.backdropBreakpoint,
});
diff --git a/core/src/components/modal/test/card-refresher/index.html b/core/src/components/modal/test/card-refresher/index.html
index 3b387b2c58..8ac3d90078 100644
--- a/core/src/components/modal/test/card-refresher/index.html
+++ b/core/src/components/modal/test/card-refresher/index.html
@@ -96,7 +96,6 @@
const modalElement = await modalController.create({
presentingElement: presentingEl,
component: element,
- swipeToClose: true,
...opts,
});
return modalElement;
diff --git a/core/src/components/modal/test/card-scroll-target/index.html b/core/src/components/modal/test/card-scroll-target/index.html
index 50fe1e7b1a..f6f66a52f3 100644
--- a/core/src/components/modal/test/card-scroll-target/index.html
+++ b/core/src/components/modal/test/card-scroll-target/index.html
@@ -119,7 +119,6 @@
const modalElement = await modalController.create({
presentingElement: presentingEl,
component: element,
- swipeToClose: true,
...opts,
});
return modalElement;
diff --git a/core/src/components/modal/test/card/index.html b/core/src/components/modal/test/card/index.html
index 68425b8df5..e70327a86a 100644
--- a/core/src/components/modal/test/card/index.html
+++ b/core/src/components/modal/test/card/index.html
@@ -151,7 +151,6 @@
const modalElement = await modalController.create({
presentingElement: presentingEl,
component: element,
- swipeToClose: true,
...opts,
});
return modalElement;
diff --git a/core/src/components/modal/test/spec/index.html b/core/src/components/modal/test/spec/index.html
index 88533310cb..d97fdd1de4 100644
--- a/core/src/components/modal/test/spec/index.html
+++ b/core/src/components/modal/test/spec/index.html
@@ -515,7 +515,6 @@
const modalElement = await modalController.create({
presentingElement: presentingEl,
component: element,
- swipeToClose: true,
enterAnimation: toggle.checked ? enterAnimation : undefined,
leaveAnimation: toggle.checked ? leaveAnimation : undefined,
});
diff --git a/core/src/themes/test/css-variables/index.html b/core/src/themes/test/css-variables/index.html
index a881966b88..09deb1b058 100644
--- a/core/src/themes/test/css-variables/index.html
+++ b/core/src/themes/test/css-variables/index.html
@@ -1059,7 +1059,6 @@
// present the modal
const modalElement = Object.assign(document.createElement('ion-modal'), {
component: element,
- swipeToClose: true,
presentingElement: document.querySelector('ion-tabs'),
});
diff --git a/packages/vue/src/components/Overlays.ts b/packages/vue/src/components/Overlays.ts
index 1f02542841..c2646bfd72 100644
--- a/packages/vue/src/components/Overlays.ts
+++ b/packages/vue/src/components/Overlays.ts
@@ -29,7 +29,7 @@ export const IonPicker = /*@__PURE__*/ defineOverlayContainer('io
export const IonToast = /*@__PURE__*/ defineOverlayContainer('ion-toast', defineIonToastCustomElement, ['animated', 'buttons', 'color', 'cssClass', 'duration', 'enterAnimation', 'header', 'htmlAttributes', 'icon', 'keyboardClose', 'leaveAnimation', 'message', 'mode', 'position', 'translucent'], toastController);
-export const IonModal = /*@__PURE__*/ defineOverlayContainer('ion-modal', defineIonModalCustomElement, ['animated', 'backdropBreakpoint', 'backdropDismiss', 'breakpoints', 'canDismiss', 'enterAnimation', 'handle', 'handleBehavior', 'htmlAttributes', 'initialBreakpoint', 'isOpen', 'keepContentsMounted', 'keyboardClose', 'leaveAnimation', 'mode', 'presentingElement', 'showBackdrop', 'swipeToClose', 'trigger']);
+export const IonModal = /*@__PURE__*/ defineOverlayContainer('ion-modal', defineIonModalCustomElement, ['animated', 'backdropBreakpoint', 'backdropDismiss', 'breakpoints', 'canDismiss', 'enterAnimation', 'handle', 'handleBehavior', 'htmlAttributes', 'initialBreakpoint', 'isOpen', 'keepContentsMounted', 'keyboardClose', 'leaveAnimation', 'mode', 'presentingElement', 'showBackdrop', 'trigger']);
export const IonPopover = /*@__PURE__*/ defineOverlayContainer('ion-popover', defineIonPopoverCustomElement, ['alignment', 'animated', 'arrow', 'backdropDismiss', 'component', 'componentProps', 'dismissOnSelect', 'enterAnimation', 'event', 'htmlAttributes', 'isOpen', 'keepContentsMounted', 'keyboardClose', 'leaveAnimation', 'mode', 'reference', 'showBackdrop', 'side', 'size', 'translucent', 'trigger', 'triggerAction']);