mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-11-08 15:51:16 +08:00
Merge remote-tracking branch 'origin/main' into chore-sync-next-with-main
This commit is contained in:
@ -50,6 +50,7 @@ export class Refresher implements ComponentInterface {
|
||||
private pointerDown = false;
|
||||
private needsCompletion = false;
|
||||
private didRefresh = false;
|
||||
private contentFullscreen = false;
|
||||
private lastVelocityY = 0;
|
||||
private elementToTransform?: HTMLElement;
|
||||
private animations: Animation[] = [];
|
||||
@ -478,6 +479,12 @@ export class Refresher implements ComponentInterface {
|
||||
* Query the background content element from the host ion-content element directly.
|
||||
*/
|
||||
this.backgroundContentEl = await contentEl.getBackgroundElement();
|
||||
/**
|
||||
* Check if the content element is fullscreen to apply the correct styles
|
||||
* when the refresher is refreshing. Otherwise, the refresher will be
|
||||
* hidden because it is positioned behind the background content element.
|
||||
*/
|
||||
this.contentFullscreen = contentEl.fullscreen;
|
||||
|
||||
if (await shouldUseNativeRefresher(this.el, getIonMode(this))) {
|
||||
this.setupNativeRefresher(contentEl);
|
||||
@ -580,6 +587,15 @@ export class Refresher implements ComponentInterface {
|
||||
this.progress = 0;
|
||||
this.state = RefresherState.Inactive;
|
||||
this.memoizeOverflowStyle();
|
||||
|
||||
/**
|
||||
* If the content is fullscreen, then we need to
|
||||
* set the offset-top style on the background content
|
||||
* element to ensure that the refresher is shown.
|
||||
*/
|
||||
if (this.contentFullscreen && this.backgroundContentEl) {
|
||||
this.backgroundContentEl.style.setProperty('--offset-top', '0px');
|
||||
}
|
||||
}
|
||||
|
||||
private onMove(detail: GestureDetail) {
|
||||
@ -737,6 +753,18 @@ export class Refresher implements ComponentInterface {
|
||||
* user can scroll again.
|
||||
*/
|
||||
this.setCss(0, '0ms', false, '', true);
|
||||
|
||||
/**
|
||||
* Reset the offset-top style on the background content
|
||||
* when the refresher is no longer refreshing and the
|
||||
* content is fullscreen.
|
||||
*
|
||||
* This ensures that the behavior of background content
|
||||
* does not change when refreshing is complete.
|
||||
*/
|
||||
if (this.contentFullscreen && this.backgroundContentEl) {
|
||||
this.backgroundContentEl?.style.removeProperty('--offset-top');
|
||||
}
|
||||
}, 600);
|
||||
|
||||
// reset the styles on the scroll element
|
||||
|
||||
103
core/src/components/refresher/test/fullscreen/index.html
Normal file
103
core/src/components/refresher/test/fullscreen/index.html
Normal file
@ -0,0 +1,103 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" dir="ltr">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Refresher - Basic</title>
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"
|
||||
/>
|
||||
<link href="../../../../../css/ionic.bundle.css" rel="stylesheet" />
|
||||
<link href="../../../../../scripts/testing/styles.css" rel="stylesheet" />
|
||||
<script src="../../../../../scripts/testing/scripts.js"></script>
|
||||
<script nomodule src="../../../../../dist/ionic/ionic.js"></script>
|
||||
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
|
||||
|
||||
<style>
|
||||
ion-toolbar {
|
||||
--opacity: 0.5;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<ion-app>
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Pull To Refresh</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content fullscreen>
|
||||
<ion-refresher id="refresher" slot="fixed">
|
||||
<ion-refresher-content
|
||||
pulling-icon="arrow-down-outline"
|
||||
pulling-text="Pull to refresh..."
|
||||
refreshing-text="Refreshing..."
|
||||
refreshing-spinner="circles"
|
||||
>
|
||||
</ion-refresher-content>
|
||||
</ion-refresher>
|
||||
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean sed tellus nec mauris auctor dignissim
|
||||
fermentum in risus. Sed nec convallis sapien, id tincidunt enim. Mauris ornare eleifend nunc id mattis. Fusce
|
||||
augue diam, sagittis nec posuere at, consectetur tempor lectus. Nulla at lectus eget mauris iaculis malesuada
|
||||
mollis sed neque. Curabitur et risus tristique, malesuada mauris finibus, elementum massa. Proin lacinia
|
||||
mauris quis ligula blandit ullamcorper. Donec ut posuere lorem. In volutpat magna vitae tellus posuere
|
||||
pulvinar. Nam varius ligula justo, nec placerat lacus pharetra ac. Aenean massa orci, tristique in nisl ut,
|
||||
aliquet consectetur libero. Etiam luctus placerat vulputate. Aliquam ipsum massa, porttitor at mollis ut,
|
||||
pretium sit amet mi. In neque mauris, placerat et neque vel, tempor interdum dolor. Suspendisse gravida
|
||||
malesuada tellus, vel dapibus nisl dignissim vel. Cras ut nulla sit amet erat malesuada euismod vel a nulla.
|
||||
</p>
|
||||
<p>
|
||||
Phasellus sit amet iaculis odio, eget feugiat erat. Etiam sit amet turpis sit amet massa viverra maximus.
|
||||
Aenean venenatis porttitor pharetra. Fusce vulputate urna purus, vel efficitur mauris auctor non. Etiam libero
|
||||
odio, sodales in velit a, faucibus venenatis erat. Ut convallis sit amet urna in ultrices. Cras neque est,
|
||||
vehicula sed lorem ac, placerat commodo elit. Praesent turpis metus, elementum eget iaculis ac, elementum in
|
||||
odio. Nunc et elit faucibus, condimentum mauris consequat, ornare dolor. Sed ac lectus a est blandit tempor.
|
||||
Etiam lobortis tristique maximus.
|
||||
</p>
|
||||
<p>
|
||||
Quisque tempus porttitor massa, vel condimentum risus finibus a. Aliquam viverra maximus odio, id ornare justo
|
||||
tristique ac. Mauris euismod arcu eget neque sagittis rutrum. Ut vehicula porta lacus nec lobortis. Vestibulum
|
||||
et elit ultrices, lacinia metus in, lobortis est. Vivamus nisi justo, venenatis sit amet arcu ac, congue
|
||||
faucibus justo. Duis volutpat posuere enim, vel sagittis elit dictum et. Sed et congue mauris. Nam venenatis
|
||||
venenatis risus, ac condimentum neque sagittis sed. In eget nulla ultricies urna sollicitudin posuere. Aenean
|
||||
sagittis congue mauris. Proin nec libero mi. In hac habitasse platea dictumst. Praesent nunc nulla, dictum id
|
||||
molestie sed, pretium vitae turpis.
|
||||
</p>
|
||||
<p>
|
||||
Pellentesque vitae dapibus lacus. Nullam suscipit ornare risus quis ullamcorper. Nullam feugiat, sapien et
|
||||
sodales fermentum, risus ligula semper risus, id efficitur ligula augue id diam. Suspendisse lobortis est sit
|
||||
amet quam facilisis, ut vestibulum nunc dignissim. Donec at vestibulum magna. Maecenas maximus pretium metus.
|
||||
Phasellus congue sapien vel odio imperdiet, nec mollis odio euismod. Sed vel eros ut sapien accumsan
|
||||
condimentum vehicula vitae lectus. Donec sed efficitur lorem. Aenean tristique mi libero, eleifend tincidunt
|
||||
libero finibus at. Mauris condimentum fermentum rutrum.
|
||||
</p>
|
||||
<p>
|
||||
Nulla tristique ultricies suscipit. Donec non ornare elit. Vivamus id pretium mauris, nec sagittis leo. Fusce
|
||||
mattis eget est id sollicitudin. Suspendisse dictum sem magna, in imperdiet metus suscipit et. Suspendisse
|
||||
enim enim, venenatis et orci eu, suscipit congue lacus. Praesent vel ligula non eros tempor interdum. Proin
|
||||
justo orci, ultricies vitae diam sed, semper consectetur ligula. Aenean finibus ante velit, nec efficitur
|
||||
libero cursus cursus. Duis mi nunc, imperdiet sed condimentum vel, porttitor ut lacus. Quisque dui ipsum,
|
||||
vehicula sed vestibulum id, semper vel libero. Suspendisse tincidunt mollis condimentum. Nulla facilisi. Etiam
|
||||
neque nisl, egestas nec iaculis sed, tristique faucibus sem. Sed mollis dui quis ligula cursus rutrum.
|
||||
</p>
|
||||
</ion-content>
|
||||
</ion-app>
|
||||
<ion-menu-controller></ion-menu-controller>
|
||||
|
||||
<script>
|
||||
const refresher = document.getElementById('refresher');
|
||||
|
||||
refresher.addEventListener('ionRefresh', () => {
|
||||
setTimeout(() => {
|
||||
refresher.complete();
|
||||
// Custom event consumed by e2e tests
|
||||
window.dispatchEvent(new CustomEvent('ionRefreshComplete'));
|
||||
}, 500);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@ -0,0 +1,84 @@
|
||||
import { expect } from '@playwright/test';
|
||||
import { configs, test } from '@utils/test/playwright';
|
||||
|
||||
import { pullToRefresh } from '../test.utils';
|
||||
|
||||
/**
|
||||
* This behavior does not vary across directions.
|
||||
*/
|
||||
configs({ directions: ['ltr'] }).forEach(({ title, config, screenshot }) => {
|
||||
test.describe(title('refresher: fullscreen content'), () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
/**
|
||||
* Do not call `complete()` from `ion-refresher` in this test.
|
||||
* This will allow the refresher to "pause" while refreshing.
|
||||
* By pausing, the test can verify that the refresher is
|
||||
* completely visible when the content is fullscreen.
|
||||
*/
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Pull To Refresh</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content fullscreen>
|
||||
<ion-refresher id="refresher" slot="fixed">
|
||||
<ion-refresher-content
|
||||
pulling-icon="arrow-down-outline"
|
||||
pulling-text="Pull to refresh..."
|
||||
refreshing-text="Refreshing..."
|
||||
refreshing-spinner="circles"
|
||||
>
|
||||
</ion-refresher-content>
|
||||
</ion-refresher>
|
||||
|
||||
<p>Pull this content down to trigger the refresh.</p>
|
||||
</ion-content>
|
||||
|
||||
<script>
|
||||
const refresher = document.getElementById('refresher');
|
||||
|
||||
refresher.addEventListener('ionRefresh', () => {
|
||||
setTimeout(() => {
|
||||
// Custom event consumed by e2e tests
|
||||
window.dispatchEvent(new CustomEvent('ionRefreshComplete'));
|
||||
}, 500);
|
||||
});
|
||||
</script>
|
||||
`,
|
||||
config
|
||||
);
|
||||
});
|
||||
|
||||
// Bug only occurs with the legacy refresher.
|
||||
test.describe('legacy refresher', () => {
|
||||
test('should display when content is fullscreen', async ({ page, browserName }) => {
|
||||
test.info().annotations.push({
|
||||
type: 'issue',
|
||||
description: 'https://github.com/ionic-team/ionic-framework/issues/18714',
|
||||
});
|
||||
|
||||
const refresher = page.locator('ion-refresher');
|
||||
|
||||
await pullToRefresh(page);
|
||||
|
||||
if (browserName === 'firefox') {
|
||||
/**
|
||||
* The drag is highlighting the text in Firefox for
|
||||
* some reason.
|
||||
*
|
||||
* Clicking the mouse will remove the highlight and
|
||||
* be more consistent with other browsers. This
|
||||
* does not happen in Firefox, just when running
|
||||
* in Playwright.
|
||||
*/
|
||||
await page.mouse.click(0, 0);
|
||||
}
|
||||
|
||||
await expect(refresher).toHaveScreenshot(screenshot('refresher-legacy-content-fullscreen'));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 2.1 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.8 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.3 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.3 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.9 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.3 KiB |
Reference in New Issue
Block a user