Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(ui5-dynamic-page): improve scrolling smoothness #10093

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 22 additions & 8 deletions packages/fiori/src/DynamicPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ class DynamicPage extends UI5Element {
}

get headerInContent(): boolean {
return !this.showHeaderInStickArea && !this.headerInTitle;
return !this.showHeaderInStickArea && !this.headerInTitle && !this.hasSnappedTitleOnMobile;
}

get _headerLabel() {
Expand Down Expand Up @@ -307,26 +307,40 @@ class DynamicPage extends UI5Element {
return;
}

const scrollTop = this.scrollContainer!.scrollTop;
const lastHeaderSnapped = this._headerSnapped;

if (this.skipSnapOnScroll) {
this.skipSnapOnScroll = false;
return;
}

if (scrollTop > this.dynamicPageHeader.getBoundingClientRect().height) {
const scrollTop = this.scrollContainer!.scrollTop;
const headerHeight = this.dynamicPageHeader.getBoundingClientRect().height;
const lastHeaderSnapped = this._headerSnapped;

const shouldSnap = !this._headerSnapped && scrollTop > headerHeight + SCROLL_THRESHOLD;
const shouldUnsnap = this._headerSnapped
&& (scrollTop < headerHeight - SCROLL_THRESHOLD
|| (!scrollTop && !headerHeight));

if (shouldSnap) {
this.showHeaderInStickArea = false;
this._headerSnapped = true;
} else {

//* snappedTitleOnMobile
// If the header is snapped and the scroll is at the top, scroll down a bit
// to avoid ending in an endless loop of snapping and unsnapping
requestAnimationFrame(() => {
if (this.scrollContainer!.scrollTop === 0) {
this.scrollContainer!.scrollTop = SCROLL_THRESHOLD;
}
});
} else if (shouldUnsnap) {
this._headerSnapped = false;
}

// Fire event if snapped state changed
if (lastHeaderSnapped !== this._headerSnapped) {
this.fireDecoratorEvent("title-toggle");
}

this.dynamicPageTitle.snapped = this._headerSnapped;
}

async onExpandClick() {
Expand Down
7 changes: 0 additions & 7 deletions packages/fiori/src/themes/DynamicPage.css
Original file line number Diff line number Diff line change
Expand Up @@ -126,11 +126,4 @@

:host([media-range="XL"]) ::slotted([slot="headerArea"]) {
padding: var(--_ui5_dynamic_page_header_padding_XL);
}

/* snappedTitleOnMobile */
:host([_header-snapped]) ::slotted([slot="headerArea"]) {
height: 0;
padding: 0;
visibility: hidden;
}
38 changes: 38 additions & 0 deletions packages/fiori/test/specs/DynamicPage.mobile.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,44 @@ describe("DynamicPage Mobile Behaviour", () => {
);
});

it("the header content should not be rendered when snappedTitleOnMobile content is present", async () => {
const dynamicPage = await browser.$("#page");
const headerAreaSlot = await dynamicPage.shadow$("slot[name=headerArea]");
const scrollContainer = await dynamicPage.shadow$(".ui5-dynamic-page-scroll-container");

const initialScrollTop = await scrollContainer.getProperty("scrollTop");

// Scroll the content to snap the header
await browser.execute((container) => {
container.scrollTop = 340;
}, scrollContainer);

// Wait until the scroll position has changed
await browser.waitUntil(
async () => (await scrollContainer.getProperty("scrollTop")) > initialScrollTop,
{
timeout: 2000,
timeoutMsg: "The scroll handler must be called.",
}
);

// Assert that the header is snapped
const isHeaderSnapped = await dynamicPage.getProperty("headerSnapped");
assert.strictEqual(
isHeaderSnapped,
true,
"Header should be snapped when the content is scrolled."
);

// Assert that the header content is not rendered
const isHeaderContentRendered = await headerAreaSlot.isExisting();
assert.strictEqual(
isHeaderContentRendered,
false,
"Header content should not be rendered when snappedTitleOnMobile slot has content."
);
});

it("should not display snapped title on mobile when snappedTitleOnMobile slot is empty", async () => {
const dynamicPage = await browser.$("#page");
const title = await browser.$("#page ui5-dynamic-page-title");
Expand Down