mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-16 18:17:31 +08:00
fix(popover): handle scrolling in content so header can be sticky (#24294)
This commit is contained in:
@ -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 {
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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' });
|
||||
|
||||
|
@ -34,6 +34,8 @@
|
||||
<ion-button id="long-list-popover" expand="block" color="secondary" onclick="presentPopover({ component: 'list-page', event: event })">Show Long List Popover</ion-button>
|
||||
<ion-button id="no-event-popover" expand="block" color="danger" onclick="presentPopover({ component: 'profile-page' })">No Event Popover</ion-button>
|
||||
<ion-button id="custom-class-popover" expand="block" color="tertiary" onclick="presentPopover({ component: 'translucent-page', event: event, cssClass: 'my-custom-class' })">Custom Class Popover</ion-button>
|
||||
<ion-button id="header-popover" expand="block" onclick="presentPopover({ component: 'header-page' })">Popover With Header</ion-button>
|
||||
<ion-button id="translucent-header-popover" expand="block" onclick="presentPopover({ component: 'translucent-header-page' })">Popover With Translucent Header</ion-button>
|
||||
</ion-content>
|
||||
|
||||
<ion-footer>
|
||||
@ -126,6 +128,56 @@
|
||||
}
|
||||
|
||||
customElements.define('translucent-page', TranslucentPage);
|
||||
|
||||
class HeaderPage extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
this.innerHTML = `
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Header</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content class="ion-padding" color="primary">
|
||||
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.
|
||||
</ion-content>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('header-page', HeaderPage);
|
||||
|
||||
class TranslucentHeaderPage extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
this.innerHTML = `
|
||||
<ion-header translucent>
|
||||
<ion-toolbar>
|
||||
<ion-title>Header</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content class="ion-padding" fullscreen color="primary">
|
||||
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.
|
||||
</ion-content>
|
||||
|
||||
<ion-footer translucent>
|
||||
<ion-toolbar>
|
||||
<ion-title>Footer</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-footer>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('translucent-header-page', TranslucentHeaderPage);
|
||||
</script>
|
||||
</body>
|
||||
|
||||
|
Reference in New Issue
Block a user