diff --git a/core/src/components/modal/gestures/sheet.ts b/core/src/components/modal/gestures/sheet.ts
index afac8f3d3ed..a9f7855e4d4 100644
--- a/core/src/components/modal/gestures/sheet.ts
+++ b/core/src/components/modal/gestures/sheet.ts
@@ -52,7 +52,8 @@ export const createSheetGesture = (
expandToScroll: boolean,
getCurrentBreakpoint: () => number,
onDismiss: () => void,
- onBreakpointChange: (breakpoint: number) => void
+ onBreakpointChange: (breakpoint: number) => void,
+ onGestureMove?: () => void
) => {
// Defaults for the sheet swipe animation
const defaultBackdrop = [
@@ -423,6 +424,9 @@ export const createSheetGesture = (
offset = clamp(0.0001, processedStep, maxStep);
animation.progressStep(offset);
+
+ // Notify modal of position change for safe-area updates
+ onGestureMove?.();
};
const onEnd = (detail: GestureDetail) => {
diff --git a/core/src/components/modal/gestures/swipe-to-close.ts b/core/src/components/modal/gestures/swipe-to-close.ts
index 17ec454ff15..c81a6a6ba21 100644
--- a/core/src/components/modal/gestures/swipe-to-close.ts
+++ b/core/src/components/modal/gestures/swipe-to-close.ts
@@ -20,7 +20,8 @@ export const createSwipeToCloseGesture = (
el: HTMLIonModalElement,
animation: Animation,
statusBarStyle: StatusBarStyle,
- onDismiss: () => void
+ onDismiss: () => void,
+ onGestureMove?: () => void
) => {
/**
* The step value at which a card modal
@@ -199,6 +200,9 @@ export const createSwipeToCloseGesture = (
animation.progressStep(clampedStep);
+ // Notify modal of position change for safe-area updates
+ onGestureMove?.();
+
/**
* When swiping down half way, the status bar style
* should be reset to its default value.
diff --git a/core/src/components/modal/modal.scss b/core/src/components/modal/modal.scss
index 7c5ec7916fe..ac4cb533b48 100644
--- a/core/src/components/modal/modal.scss
+++ b/core/src/components/modal/modal.scss
@@ -94,10 +94,6 @@ ion-backdrop {
:host {
--width: #{$modal-inset-width};
--height: #{$modal-inset-height-small};
- --ion-safe-area-top: 0px;
- --ion-safe-area-bottom: 0px;
- --ion-safe-area-right: 0px;
- --ion-safe-area-left: 0px;
}
}
diff --git a/core/src/components/modal/modal.tsx b/core/src/components/modal/modal.tsx
index 174ac2f9d8a..73639da0588 100644
--- a/core/src/components/modal/modal.tsx
+++ b/core/src/components/modal/modal.tsx
@@ -276,7 +276,10 @@ export class Modal implements ComponentInterface, OverlayInterface {
@Listen('resize', { target: 'window' })
onWindowResize() {
- // Only handle resize for iOS card modals when no custom animations are provided
+ // Update safe-area overrides for all modal types on resize
+ this.updateSafeAreaOverrides();
+
+ // Only handle view transition for iOS card modals when no custom animations are provided
if (getIonMode(this) !== 'ios' || !this.presentingElement || this.enterAnimation || this.leaveAnimation) {
return;
}
@@ -592,6 +595,9 @@ export class Modal implements ComponentInterface, OverlayInterface {
await waitForMount();
}
+ // Predict safe-area needs based on modal configuration to avoid visual snap
+ this.setInitialSafeAreaOverrides(presentingElement);
+
writeTask(() => this.el.classList.add('show-modal'));
const hasCardModal = presentingElement !== undefined;
@@ -659,6 +665,9 @@ export class Modal implements ComponentInterface, OverlayInterface {
this.initSwipeToClose();
}
+ // Now that animation is complete, update safe-area based on actual position
+ this.updateSafeAreaOverrides();
+
// Initialize view transition listener for iOS card modals
this.initViewTransitionListener();
@@ -692,33 +701,39 @@ export class Modal implements ComponentInterface, OverlayInterface {
const statusBarStyle = this.statusBarStyle ?? StatusBarStyle.Default;
- this.gesture = createSwipeToCloseGesture(el, ani, statusBarStyle, () => {
- /**
- * While the gesture animation is finishing
- * it is possible for a user to tap the backdrop.
- * This would result in the dismiss animation
- * being played again. Typically this is avoided
- * by setting `presented = false` on the overlay
- * component; however, we cannot do that here as
- * that would prevent the element from being
- * removed from the DOM.
- */
- this.gestureAnimationDismissing = true;
-
- /**
- * Reset the status bar style as the dismiss animation
- * starts otherwise the status bar will be the wrong
- * color for the duration of the dismiss animation.
- * The dismiss method does this as well, but
- * in this case it's only called once the animation
- * has finished.
- */
- setCardStatusBarDefault(this.statusBarStyle);
- this.animation!.onFinish(async () => {
- await this.dismiss(undefined, GESTURE);
- this.gestureAnimationDismissing = false;
- });
- });
+ this.gesture = createSwipeToCloseGesture(
+ el,
+ ani,
+ statusBarStyle,
+ () => {
+ /**
+ * While the gesture animation is finishing
+ * it is possible for a user to tap the backdrop.
+ * This would result in the dismiss animation
+ * being played again. Typically this is avoided
+ * by setting `presented = false` on the overlay
+ * component; however, we cannot do that here as
+ * that would prevent the element from being
+ * removed from the DOM.
+ */
+ this.gestureAnimationDismissing = true;
+
+ /**
+ * Reset the status bar style as the dismiss animation
+ * starts otherwise the status bar will be the wrong
+ * color for the duration of the dismiss animation.
+ * The dismiss method does this as well, but
+ * in this case it's only called once the animation
+ * has finished.
+ */
+ setCardStatusBarDefault(this.statusBarStyle);
+ this.animation!.onFinish(async () => {
+ await this.dismiss(undefined, GESTURE);
+ this.gestureAnimationDismissing = false;
+ });
+ },
+ () => this.updateSafeAreaOverrides()
+ );
this.gesture.enable(true);
}
@@ -755,7 +770,9 @@ export class Modal implements ComponentInterface, OverlayInterface {
this.currentBreakpoint = breakpoint;
this.ionBreakpointDidChange.emit({ breakpoint });
}
- }
+ this.updateSafeAreaOverrides();
+ },
+ () => this.updateSafeAreaOverrides()
);
this.gesture = gesture;
@@ -849,6 +866,86 @@ export class Modal implements ComponentInterface, OverlayInterface {
this.cachedPageParent = undefined;
}
+ /**
+ * Sets initial safe-area overrides based on modal configuration before
+ * the modal becomes visible. This predicts whether the modal will touch
+ * screen edges to avoid a visual snap after animation completes.
+ */
+ private setInitialSafeAreaOverrides(presentingElement: HTMLElement | undefined) {
+ const style = this.el.style;
+ const isSheetModal = this.breakpoints !== undefined && this.initialBreakpoint !== undefined;
+ const isCardModal = presentingElement !== undefined;
+ const isTablet = window.innerWidth >= 768;
+
+ // Sheet modals: always touch bottom, top depends on breakpoint
+ if (isSheetModal) {
+ style.setProperty('--ion-safe-area-top', '0px');
+ // Don't override bottom - sheet always touches bottom
+ style.setProperty('--ion-safe-area-left', '0px');
+ style.setProperty('--ion-safe-area-right', '0px');
+ return;
+ }
+
+ // Card modals are inset from edges (rounded corners), no safe areas needed
+ if (isCardModal) {
+ style.setProperty('--ion-safe-area-top', '0px');
+ style.setProperty('--ion-safe-area-bottom', '0px');
+ style.setProperty('--ion-safe-area-left', '0px');
+ style.setProperty('--ion-safe-area-right', '0px');
+ return;
+ }
+
+ // Phone modals are fullscreen, need all safe areas
+ if (!isTablet) {
+ // Don't set any overrides - inherit from :root
+ return;
+ }
+
+ // Default tablet modal: centered dialog, no safe areas needed
+ // Check for fullscreen override via CSS custom properties
+ const computedStyle = getComputedStyle(this.el);
+ const width = computedStyle.getPropertyValue('--width').trim();
+ const height = computedStyle.getPropertyValue('--height').trim();
+
+ if (width === '100%' && height === '100%') {
+ // Fullscreen modal - need safe areas, don't override
+ return;
+ }
+
+ // Centered dialog - zero out all safe areas
+ style.setProperty('--ion-safe-area-top', '0px');
+ style.setProperty('--ion-safe-area-bottom', '0px');
+ style.setProperty('--ion-safe-area-left', '0px');
+ style.setProperty('--ion-safe-area-right', '0px');
+ }
+
+ /**
+ * Updates safe-area CSS variable overrides based on whether the modal
+ * is touching each edge of the viewport. This is called after animation
+ * and during gestures to handle dynamic position changes.
+ */
+ private updateSafeAreaOverrides() {
+ const wrapper = this.wrapperEl;
+ if (!wrapper) return;
+
+ const rect = wrapper.getBoundingClientRect();
+ const threshold = 2; // Account for subpixel rendering
+
+ const touchingTop = rect.top <= threshold;
+ const touchingBottom = rect.bottom >= window.innerHeight - threshold;
+ const touchingLeft = rect.left <= threshold;
+ const touchingRight = rect.right >= window.innerWidth - threshold;
+
+ // Remove override when touching edge (allow inheritance), set to 0 when not touching
+ const style = this.el.style;
+ touchingTop ? style.removeProperty('--ion-safe-area-top') : style.setProperty('--ion-safe-area-top', '0px');
+ touchingBottom
+ ? style.removeProperty('--ion-safe-area-bottom')
+ : style.setProperty('--ion-safe-area-bottom', '0px');
+ touchingLeft ? style.removeProperty('--ion-safe-area-left') : style.setProperty('--ion-safe-area-left', '0px');
+ touchingRight ? style.removeProperty('--ion-safe-area-right') : style.setProperty('--ion-safe-area-right', '0px');
+ }
+
private sheetOnDismiss() {
/**
* While the gesture animation is finishing
diff --git a/core/src/components/modal/test/safe-area/index.html b/core/src/components/modal/test/safe-area/index.html
new file mode 100644
index 00000000000..a1e2490dee4
--- /dev/null
+++ b/core/src/components/modal/test/safe-area/index.html
@@ -0,0 +1,175 @@
+
+
+
+
+ Modal - Safe Area
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Modal - Safe Area
+
+
+
+
+
Test safe-area handling in modals on tablet-sized screens.
+
+
+
+
+
Default Modal
+
Centered dialog on tablet - should NOT have safe-area padding
+
+ Present
+
+
+
+
+
Fullscreen Modal
+
Full screen on tablet - should have safe-area padding
+
+ Present
+
+
+
+
+
Sheet Modal (Partial)
+
At 0.5 breakpoint - should have bottom safe-area only
+
+ Present
+
+
+
+
+
Sheet Modal (Full)
+
At 1.0 breakpoint - should have bottom safe-area (handle creates top gap)
+
+ Present
+
+
+
+
+
Card Modal (iOS)
+
Card presentation - inset from edges, no safe-area padding
+
+ Present
+
+
+
+
+
+
+
+
+
diff --git a/core/src/components/modal/test/safe-area/modal.e2e.ts b/core/src/components/modal/test/safe-area/modal.e2e.ts
new file mode 100644
index 00000000000..54308da3679
--- /dev/null
+++ b/core/src/components/modal/test/safe-area/modal.e2e.ts
@@ -0,0 +1,106 @@
+import { expect } from '@playwright/test';
+import { configs, test, Viewports } from '@utils/test/playwright';
+
+/**
+ * Safe-area tests verify that modals correctly handle safe-area insets
+ * based on whether they're touching the screen edges.
+ */
+
+configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
+ test.describe(title('modal: safe-area - tablet'), () => {
+ test.beforeEach(async ({ page }) => {
+ await page.setViewportSize(Viewports.tablet.portrait);
+ await page.goto('/src/components/modal/test/safe-area', config);
+ });
+
+ test('default modal should not have safe-area padding on tablet', async ({ page }) => {
+ const ionModalDidPresent = await page.spyOnEvent('ionModalDidPresent');
+
+ await page.click('#default-modal');
+ await ionModalDidPresent.next();
+
+ await expect(page).toHaveScreenshot(screenshot(`modal-safe-area-default-tablet`));
+ });
+
+ test('fullscreen modal should have safe-area padding on tablet', async ({ page }) => {
+ const ionModalDidPresent = await page.spyOnEvent('ionModalDidPresent');
+
+ await page.click('#fullscreen-modal');
+ await ionModalDidPresent.next();
+
+ await expect(page).toHaveScreenshot(screenshot(`modal-safe-area-fullscreen-tablet`));
+ });
+
+ test('sheet modal at partial breakpoint should have bottom safe-area only', async ({ page }) => {
+ const ionModalDidPresent = await page.spyOnEvent('ionModalDidPresent');
+
+ await page.click('#sheet-modal-partial');
+ await ionModalDidPresent.next();
+
+ await expect(page).toHaveScreenshot(screenshot(`modal-safe-area-sheet-partial-tablet`));
+ });
+
+ test('sheet modal at full breakpoint should have bottom safe-area', async ({ page }) => {
+ const ionModalDidPresent = await page.spyOnEvent('ionModalDidPresent');
+
+ await page.click('#sheet-modal-full');
+ await ionModalDidPresent.next();
+
+ await expect(page).toHaveScreenshot(screenshot(`modal-safe-area-sheet-full-tablet`));
+ });
+ });
+});
+
+configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
+ test.describe(title('modal: safe-area - card modal'), () => {
+ test.beforeEach(async ({ page }) => {
+ await page.setViewportSize(Viewports.tablet.portrait);
+ await page.goto('/src/components/modal/test/safe-area', config);
+ });
+
+ test('card modal should not have safe-area padding', async ({ page }) => {
+ const ionModalDidPresent = await page.spyOnEvent('ionModalDidPresent');
+
+ await page.click('#card-modal');
+ await ionModalDidPresent.next();
+
+ await expect(page).toHaveScreenshot(screenshot(`modal-safe-area-card-tablet`));
+ });
+ });
+});
+
+configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
+ test.describe(title('modal: safe-area - tablet (MD mode)'), () => {
+ test.beforeEach(async ({ page }) => {
+ await page.setViewportSize(Viewports.tablet.portrait);
+ await page.goto('/src/components/modal/test/safe-area', config);
+ });
+
+ test('default modal should not have safe-area padding on tablet', async ({ page }) => {
+ const ionModalDidPresent = await page.spyOnEvent('ionModalDidPresent');
+
+ await page.click('#default-modal');
+ await ionModalDidPresent.next();
+
+ await expect(page).toHaveScreenshot(screenshot(`modal-safe-area-default-tablet`));
+ });
+
+ test('fullscreen modal should have safe-area padding on tablet', async ({ page }) => {
+ const ionModalDidPresent = await page.spyOnEvent('ionModalDidPresent');
+
+ await page.click('#fullscreen-modal');
+ await ionModalDidPresent.next();
+
+ await expect(page).toHaveScreenshot(screenshot(`modal-safe-area-fullscreen-tablet`));
+ });
+
+ test('sheet modal at full breakpoint should have bottom safe-area', async ({ page }) => {
+ const ionModalDidPresent = await page.spyOnEvent('ionModalDidPresent');
+
+ await page.click('#sheet-modal-full');
+ await ionModalDidPresent.next();
+
+ await expect(page).toHaveScreenshot(screenshot(`modal-safe-area-sheet-full-tablet`));
+ });
+ });
+});
diff --git a/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-card-tablet-ios-ltr-Mobile-Chrome-linux.png b/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-card-tablet-ios-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 00000000000..3b3d61f0cc0
Binary files /dev/null and b/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-card-tablet-ios-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-card-tablet-ios-ltr-Mobile-Firefox-linux.png b/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-card-tablet-ios-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 00000000000..d4382fd040d
Binary files /dev/null and b/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-card-tablet-ios-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-card-tablet-ios-ltr-Mobile-Safari-linux.png b/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-card-tablet-ios-ltr-Mobile-Safari-linux.png
new file mode 100644
index 00000000000..baa00f0341b
Binary files /dev/null and b/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-card-tablet-ios-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-default-tablet-ios-ltr-Mobile-Chrome-linux.png b/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-default-tablet-ios-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 00000000000..b2fecbb0fdc
Binary files /dev/null and b/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-default-tablet-ios-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-default-tablet-ios-ltr-Mobile-Firefox-linux.png b/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-default-tablet-ios-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 00000000000..db891951d8b
Binary files /dev/null and b/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-default-tablet-ios-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-default-tablet-ios-ltr-Mobile-Safari-linux.png b/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-default-tablet-ios-ltr-Mobile-Safari-linux.png
new file mode 100644
index 00000000000..49f5b0864b3
Binary files /dev/null and b/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-default-tablet-ios-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-default-tablet-md-ltr-Mobile-Chrome-linux.png b/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-default-tablet-md-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 00000000000..ea089882f87
Binary files /dev/null and b/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-default-tablet-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-default-tablet-md-ltr-Mobile-Firefox-linux.png b/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-default-tablet-md-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 00000000000..0df0d931480
Binary files /dev/null and b/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-default-tablet-md-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-default-tablet-md-ltr-Mobile-Safari-linux.png b/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-default-tablet-md-ltr-Mobile-Safari-linux.png
new file mode 100644
index 00000000000..9e9a3c19098
Binary files /dev/null and b/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-default-tablet-md-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-fullscreen-tablet-ios-ltr-Mobile-Chrome-linux.png b/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-fullscreen-tablet-ios-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 00000000000..74ec7dc3a38
Binary files /dev/null and b/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-fullscreen-tablet-ios-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-fullscreen-tablet-ios-ltr-Mobile-Firefox-linux.png b/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-fullscreen-tablet-ios-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 00000000000..65ab9784735
Binary files /dev/null and b/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-fullscreen-tablet-ios-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-fullscreen-tablet-ios-ltr-Mobile-Safari-linux.png b/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-fullscreen-tablet-ios-ltr-Mobile-Safari-linux.png
new file mode 100644
index 00000000000..d464ee43d2d
Binary files /dev/null and b/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-fullscreen-tablet-ios-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-fullscreen-tablet-md-ltr-Mobile-Chrome-linux.png b/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-fullscreen-tablet-md-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 00000000000..a7ce9d2acc1
Binary files /dev/null and b/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-fullscreen-tablet-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-fullscreen-tablet-md-ltr-Mobile-Firefox-linux.png b/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-fullscreen-tablet-md-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 00000000000..cc8506bce00
Binary files /dev/null and b/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-fullscreen-tablet-md-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-fullscreen-tablet-md-ltr-Mobile-Safari-linux.png b/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-fullscreen-tablet-md-ltr-Mobile-Safari-linux.png
new file mode 100644
index 00000000000..75671eee08f
Binary files /dev/null and b/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-fullscreen-tablet-md-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-sheet-full-tablet-ios-ltr-Mobile-Chrome-linux.png b/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-sheet-full-tablet-ios-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 00000000000..413829550ad
Binary files /dev/null and b/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-sheet-full-tablet-ios-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-sheet-full-tablet-ios-ltr-Mobile-Firefox-linux.png b/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-sheet-full-tablet-ios-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 00000000000..56e510de598
Binary files /dev/null and b/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-sheet-full-tablet-ios-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-sheet-full-tablet-ios-ltr-Mobile-Safari-linux.png b/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-sheet-full-tablet-ios-ltr-Mobile-Safari-linux.png
new file mode 100644
index 00000000000..c02d6c45629
Binary files /dev/null and b/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-sheet-full-tablet-ios-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-sheet-full-tablet-md-ltr-Mobile-Chrome-linux.png b/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-sheet-full-tablet-md-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 00000000000..61bc3e8821b
Binary files /dev/null and b/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-sheet-full-tablet-md-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-sheet-full-tablet-md-ltr-Mobile-Firefox-linux.png b/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-sheet-full-tablet-md-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 00000000000..257d82b40ec
Binary files /dev/null and b/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-sheet-full-tablet-md-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-sheet-full-tablet-md-ltr-Mobile-Safari-linux.png b/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-sheet-full-tablet-md-ltr-Mobile-Safari-linux.png
new file mode 100644
index 00000000000..252eb46d25a
Binary files /dev/null and b/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-sheet-full-tablet-md-ltr-Mobile-Safari-linux.png differ
diff --git a/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-sheet-partial-tablet-ios-ltr-Mobile-Chrome-linux.png b/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-sheet-partial-tablet-ios-ltr-Mobile-Chrome-linux.png
new file mode 100644
index 00000000000..413829550ad
Binary files /dev/null and b/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-sheet-partial-tablet-ios-ltr-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-sheet-partial-tablet-ios-ltr-Mobile-Firefox-linux.png b/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-sheet-partial-tablet-ios-ltr-Mobile-Firefox-linux.png
new file mode 100644
index 00000000000..56e510de598
Binary files /dev/null and b/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-sheet-partial-tablet-ios-ltr-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-sheet-partial-tablet-ios-ltr-Mobile-Safari-linux.png b/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-sheet-partial-tablet-ios-ltr-Mobile-Safari-linux.png
new file mode 100644
index 00000000000..c02d6c45629
Binary files /dev/null and b/core/src/components/modal/test/safe-area/modal.e2e.ts-snapshots/modal-safe-area-sheet-partial-tablet-ios-ltr-Mobile-Safari-linux.png differ