From 692653842b43b5e36c51163f8261fde3b5bea40d Mon Sep 17 00:00:00 2001 From: Liam DeBeasi Date: Thu, 9 Jun 2022 16:58:53 -0400 Subject: [PATCH] fix(popover): ensure popover does not go offscreen when adjusting top position (#25350) resolves #25349 --- .../popover/test/adjustment/index.html | 59 +++++++++++++++++++ .../popover/test/adjustment/popover.e2e.ts | 32 ++++++++++ core/src/components/popover/utils.ts | 12 +++- 3 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 core/src/components/popover/test/adjustment/index.html create mode 100644 core/src/components/popover/test/adjustment/popover.e2e.ts diff --git a/core/src/components/popover/test/adjustment/index.html b/core/src/components/popover/test/adjustment/index.html new file mode 100644 index 0000000000..78d8dc105a --- /dev/null +++ b/core/src/components/popover/test/adjustment/index.html @@ -0,0 +1,59 @@ + + + + + Popover - Adjustment + + + + + + + + + + + +

Click everywhere to open the popover.

+
+
+ + + + diff --git a/core/src/components/popover/test/adjustment/popover.e2e.ts b/core/src/components/popover/test/adjustment/popover.e2e.ts new file mode 100644 index 0000000000..77a0386cb3 --- /dev/null +++ b/core/src/components/popover/test/adjustment/popover.e2e.ts @@ -0,0 +1,32 @@ +import { expect } from '@playwright/test'; +import { test } from '@utils/test/playwright'; + +test.describe('popover: adjustment', async () => { + test('should not render the popover offscreen', async ({ page }) => { + await page.goto('/src/components/popover/test/adjustment'); + + /** + * We need to click in an area where + * there is not enough room to show the popover + * below the click coordinates but not enough + * room above the click coordinates that we + * can just move the popover to without it going + * offscreen. + */ + await page.setViewportSize({ + width: 500, + height: 400, + }); + + const ionPopoverDidPresent = await page.spyOnEvent('ionPopoverDidPresent'); + + await page.mouse.click(300, 300); + + await ionPopoverDidPresent.next(); + + const popoverContent = page.locator('ion-popover .popover-content'); + const box = (await popoverContent.boundingBox())!; + + expect(box.y > 0).toBe(true); + }); +}); diff --git a/core/src/components/popover/utils.ts b/core/src/components/popover/utils.ts index 3457379591..363db25c52 100644 --- a/core/src/components/popover/utils.ts +++ b/core/src/components/popover/utils.ts @@ -863,7 +863,17 @@ export const calculateWindowAdjustment = ( */ if (triggerTop + triggerHeight + contentHeight > bodyHeight && (side === 'top' || side === 'bottom')) { if (triggerTop - contentHeight > 0) { - top = triggerTop - contentHeight - triggerHeight - (arrowHeight - 1); + /** + * While we strive to align the popover with the trigger + * on smaller screens this is not always possible. As a result, + * we adjust the popover up so that it does not hang + * off the bottom of the screen. However, we do not want to move + * the popover up so much that it goes off the top of the screen. + * + * We chose 12 here so that the popover position looks a bit nicer as + * it is not right up against the edge of the screen. + */ + top = Math.max(12, triggerTop - contentHeight - triggerHeight - (arrowHeight - 1)); arrowTop = top + contentHeight; originY = 'bottom'; addPopoverBottomClass = true;