Skip to content

Commit 4a165bc

Browse files
committed
fix(modal): correct safe-area handling for MD mode and edge detection
1 parent 9c404a6 commit 4a165bc

File tree

1 file changed

+29
-11
lines changed

1 file changed

+29
-11
lines changed

core/src/components/modal/modal.tsx

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -875,8 +875,10 @@ export class Modal implements ComponentInterface, OverlayInterface {
875875
*/
876876
private setInitialSafeAreaOverrides(presentingElement: HTMLElement | undefined) {
877877
const style = this.el.style;
878+
const mode = getIonMode(this);
878879
const isSheetModal = this.breakpoints !== undefined && this.initialBreakpoint !== undefined;
879-
const isCardModal = presentingElement !== undefined;
880+
// Card modals only exist in iOS mode - in MD mode, presentingElement is ignored
881+
const isCardModal = presentingElement !== undefined && mode === 'ios';
880882
const isTablet = window.innerWidth >= 768;
881883

882884
// Sheet modals always touch bottom edge, never top/left/right
@@ -949,9 +951,23 @@ export class Modal implements ComponentInterface, OverlayInterface {
949951
style.setProperty('--ion-safe-area-right', '0px');
950952
}
951953

954+
/**
955+
* Gets the root safe-area values from the document element.
956+
* These represent the actual device safe areas before any overlay overrides.
957+
*/
958+
private getRootSafeAreaValues(): { top: number; bottom: number; left: number; right: number } {
959+
const rootStyle = getComputedStyle(document.documentElement);
960+
return {
961+
top: parseFloat(rootStyle.getPropertyValue('--ion-safe-area-top')) || 0,
962+
bottom: parseFloat(rootStyle.getPropertyValue('--ion-safe-area-bottom')) || 0,
963+
left: parseFloat(rootStyle.getPropertyValue('--ion-safe-area-left')) || 0,
964+
right: parseFloat(rootStyle.getPropertyValue('--ion-safe-area-right')) || 0,
965+
};
966+
}
967+
952968
/**
953969
* Updates safe-area CSS variable overrides based on whether the modal
954-
* is touching each edge of the viewport. Called after animation
970+
* extends into each safe-area region. Called after animation
955971
* and during gestures to handle dynamic position changes.
956972
*/
957973
private updateSafeAreaOverrides() {
@@ -965,20 +981,22 @@ export class Modal implements ComponentInterface, OverlayInterface {
965981
}
966982

967983
const rect = wrapper.getBoundingClientRect();
968-
const threshold = 2;
984+
const safeAreas = this.getRootSafeAreaValues();
969985

970-
const touchingTop = rect.top <= threshold;
971-
const touchingBottom = rect.bottom >= window.innerHeight - threshold;
972-
const touchingLeft = rect.left <= threshold;
973-
const touchingRight = rect.right >= window.innerWidth - threshold;
986+
const extendsIntoTop = rect.top < safeAreas.top;
987+
const extendsIntoBottom = rect.bottom > window.innerHeight - safeAreas.bottom;
988+
const extendsIntoLeft = rect.left < safeAreas.left;
989+
const extendsIntoRight = rect.right > window.innerWidth - safeAreas.right;
974990

975991
const style = this.el.style;
976-
touchingTop ? style.removeProperty('--ion-safe-area-top') : style.setProperty('--ion-safe-area-top', '0px');
977-
touchingBottom
992+
extendsIntoTop ? style.removeProperty('--ion-safe-area-top') : style.setProperty('--ion-safe-area-top', '0px');
993+
extendsIntoBottom
978994
? style.removeProperty('--ion-safe-area-bottom')
979995
: style.setProperty('--ion-safe-area-bottom', '0px');
980-
touchingLeft ? style.removeProperty('--ion-safe-area-left') : style.setProperty('--ion-safe-area-left', '0px');
981-
touchingRight ? style.removeProperty('--ion-safe-area-right') : style.setProperty('--ion-safe-area-right', '0px');
996+
extendsIntoLeft ? style.removeProperty('--ion-safe-area-left') : style.setProperty('--ion-safe-area-left', '0px');
997+
extendsIntoRight
998+
? style.removeProperty('--ion-safe-area-right')
999+
: style.setProperty('--ion-safe-area-right', '0px');
9821000
}
9831001

9841002
private sheetOnDismiss() {

0 commit comments

Comments
 (0)