From f6a00ea9544aa70620b5f8f65a7702fa3bedd974 Mon Sep 17 00:00:00 2001 From: Amanda Smith <90629384+amandaesmith3@users.noreply.github.com> Date: Mon, 6 Dec 2021 10:45:37 -0600 Subject: [PATCH] fix(popover): handle scrolling in content so header can be sticky (#24294) --- core/src/components/content/content.scss | 27 ++++++++++ core/src/components/content/content.tsx | 9 +++- core/src/components/popover/popover.scss | 6 ++- core/src/components/popover/test/basic/e2e.ts | 16 ++++++ .../components/popover/test/basic/index.html | 52 +++++++++++++++++++ 5 files changed, 108 insertions(+), 2 deletions(-) diff --git a/core/src/components/content/content.scss b/core/src/components/content/content.scss index 59ce715d7a..6fee761220 100644 --- a/core/src/components/content/content.scss +++ b/core/src/components/content/content.scss @@ -140,10 +140,37 @@ } :host(.content-sizing) { + display: flex; + + flex-direction: column; + + /** + * This resolves a sizing issue in popovers where extra long content + * would overflow the popover's height, preventing scrolling. It's a + * quirk of flexbox that forces the content to shrink to fit. + * + * overflow: hidden can't be used here because it prevents the visual + * effect from showing on translucent headers. + */ + min-height: 0; + contain: none; } :host(.content-sizing) .inner-scroll { position: relative; + + /** + * Because the outer content has display: flex here (to help enable + * scrolling in a popover), offsetting via `top` (such as when using + * a translucent header) creates white space under the content. Use + * a negative margin instead to keep the bottom in place. (A similar + * thing happens with `bottom` and footers.) + */ + top: 0; + bottom: 0; + + margin-top: calc(var(--offset-top) * -1); + margin-bottom: calc(var(--offset-bottom) * -1); } .transition-effect { diff --git a/core/src/components/content/content.tsx b/core/src/components/content/content.tsx index baa0c7c3a7..07ca73bedb 100644 --- a/core/src/components/content/content.tsx +++ b/core/src/components/content/content.tsx @@ -374,10 +374,17 @@ const getPageElement = (el: HTMLElement) => { if (tabs) { return tabs; } - const page = el.closest('ion-app,ion-page,.ion-page,page-inner'); + + /** + * If we're in a popover, we need to use its wrapper so we can account for space + * between the popover and the edges of the screen. But if the popover contains + * its own page element, we should use that instead. + */ + const page = el.closest('ion-app, ion-page, .ion-page, page-inner, .popover-content'); if (page) { return page; } + return getParentElement(el); }; diff --git a/core/src/components/popover/popover.scss b/core/src/components/popover/popover.scss index f538505f35..15768d059b 100644 --- a/core/src/components/popover/popover.scss +++ b/core/src/components/popover/popover.scss @@ -75,5 +75,9 @@ --ion-safe-area-right: 0px; --ion-safe-area-bottom: 0px; --ion-safe-area-left: 0px; -} + display: flex; + flex-direction: column; + + overflow: hidden; +} diff --git a/core/src/components/popover/test/basic/e2e.ts b/core/src/components/popover/test/basic/e2e.ts index c0ec276db0..b509bbeab1 100644 --- a/core/src/components/popover/test/basic/e2e.ts +++ b/core/src/components/popover/test/basic/e2e.ts @@ -57,6 +57,14 @@ test('popover: custom class', async () => { await testPopover(DIRECTORY, '#custom-class-popover'); }); +test('popover: header', async () => { + await testPopover(DIRECTORY, '#header-popover'); +}); + +test('popover: translucent header', async () => { + await testPopover(DIRECTORY, '#translucent-header-popover'); +}); + /** * RTL Tests */ @@ -81,6 +89,14 @@ test('popover:rtl: custom class', async () => { await testPopover(DIRECTORY, '#custom-class-popover', true); }); +test('popover:rtl: header', async () => { + await testPopover(DIRECTORY, '#header-popover', true); +}); + +test('popover:rtl: translucent header', async () => { + await testPopover(DIRECTORY, '#translucent-header-popover', true); +}); + test('popover: htmlAttributes', async () => { const page = await newE2EPage({ url: '/src/components/popover/test/basic?ionic:_testing=true' }); diff --git a/core/src/components/popover/test/basic/index.html b/core/src/components/popover/test/basic/index.html index bfc989a273..50136ca5b0 100644 --- a/core/src/components/popover/test/basic/index.html +++ b/core/src/components/popover/test/basic/index.html @@ -34,6 +34,8 @@ Show Long List Popover No Event Popover Custom Class Popover + Popover With Header + Popover With Translucent Header @@ -126,6 +128,56 @@ } customElements.define('translucent-page', TranslucentPage); + + class HeaderPage extends HTMLElement { + constructor() { + super(); + } + + connectedCallback() { + this.innerHTML = ` + + + Header + + + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit.In rutrum tortor lacus, ac interdum ipsum bibendum vel.Aenean non nibh gravida, ullamcorper mi at, tempor nulla.Proin malesuada tellus ut ullamcorper accumsan.Donec semper justo vulputate neque tempus ultricies.Proin non aliquet ipsum.Praesent mauris sem, facilisis eu justo nec, euismod imperdiet tellus.Duis eget justo congue, lacinia orci sed, fermentum urna.Quisque sed massa faucibus, interdum dolor rhoncus, molestie erat.Proin suscipit ante non mauris volutpat egestas.Donec a ultrices ligula.Mauris in felis vel dui consectetur viverra.Nam vitae quam in arcu aliquam aliquam.Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.Cras non velit nisl.Donec viverra, magna quis vestibulum volutpat, metus ante tincidunt augue, non porta nisi mi sit amet neque.Proin dapibus eros vitae nibh tincidunt, blandit rhoncus est porttitor. + + `; + } + } + + customElements.define('header-page', HeaderPage); + + class TranslucentHeaderPage extends HTMLElement { + constructor() { + super(); + } + + connectedCallback() { + this.innerHTML = ` + + + Header + + + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit.In rutrum tortor lacus, ac interdum ipsum bibendum vel.Aenean non nibh gravida, ullamcorper mi at, tempor nulla.Proin malesuada tellus ut ullamcorper accumsan.Donec semper justo vulputate neque tempus ultricies.Proin non aliquet ipsum.Praesent mauris sem, facilisis eu justo nec, euismod imperdiet tellus.Duis eget justo congue, lacinia orci sed, fermentum urna.Quisque sed massa faucibus, interdum dolor rhoncus, molestie erat.Proin suscipit ante non mauris volutpat egestas.Donec a ultrices ligula.Mauris in felis vel dui consectetur viverra.Nam vitae quam in arcu aliquam aliquam.Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.Cras non velit nisl.Donec viverra, magna quis vestibulum volutpat, metus ante tincidunt augue, non porta nisi mi sit amet neque.Proin dapibus eros vitae nibh tincidunt, blandit rhoncus est porttitor. + + + + + Footer + + + `; + } + } + + customElements.define('translucent-header-page', TranslucentHeaderPage);