diff --git a/packages/fiori/src/DynamicPage.ts b/packages/fiori/src/DynamicPage.ts index 5e1865b65d69..62ba63ec38d4 100644 --- a/packages/fiori/src/DynamicPage.ts +++ b/packages/fiori/src/DynamicPage.ts @@ -5,6 +5,7 @@ import slot from "@ui5/webcomponents-base/dist/decorators/slot.js"; import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js"; import { getI18nBundle } from "@ui5/webcomponents-base/dist/i18nBundle.js"; import type I18nBundle from "@ui5/webcomponents-base/dist/i18nBundle.js"; +import type { Timeout } from "@ui5/webcomponents-base/dist/types.js"; // Template import DynamicPageTemplate from "./generated/templates/DynamicPageTemplate.lit.js"; @@ -16,6 +17,8 @@ import DynamicPageHeader from "./DynamicPageHeader.js"; import DynamicPageTitle from "./DynamicPageTitle.js"; import DynamicPageHeaderActions from "./DynamicPageHeaderActions.js"; +const SCROLL_DEBOUNCE_RATE = 0; // ms + /** * @class * @@ -35,6 +38,7 @@ import DynamicPageHeaderActions from "./DynamicPageHeaderActions.js"; template: DynamicPageTemplate, dependencies: [DynamicPageHeader, DynamicPageTitle, DynamicPageHeaderActions], }) + class DynamicPage extends UI5Element { static i18nBundle: I18nBundle; @@ -63,6 +67,14 @@ class DynamicPage extends UI5Element { @slot({ type: HTMLElement }) footer!: HTMLElement[]; + isExpanding = false; + iPreviousScrollAmount = 0; + _debounceInterval?: Timeout | null; + + onAfterRendering() { + this.addEventListener("scroll", this.snapOnScroll.bind(this)); + } + get classes() { return { root: { @@ -80,20 +92,61 @@ class DynamicPage extends UI5Element { }; } - get dynamicPageTitle() { + get dynamicPageTitle(): DynamicPageTitle | null { return this.querySelector("[ui5-dynamic-page-title]"); } + get dynamicPageHeader(): DynamicPageHeader | null { + return this.querySelector("[ui5-dynamic-page-header]"); + } + + snapOnScroll() { + this._debounce(() => { + if (!this.dynamicPageTitle || !this.dynamicPageHeader) { + return; + } + + if (this.iPreviousScrollAmount === this.scrollTop || this.headerPinned) { + return; + } + + this.iPreviousScrollAmount = this.scrollTop; + + if (this.isExpanding) { + this.isExpanding = false; + return; + } + + if (this.scrollTop > this.dynamicPageHeader.getBoundingClientRect().height) { + this.headerSnapped = true; + } else { + this.headerSnapped = false; + } + this.dynamicPageTitle.snapped = this.headerSnapped; + }, SCROLL_DEBOUNCE_RATE); + } + onExpandClick() { this.headerSnapped = !this.headerSnapped; if (this.dynamicPageTitle) { this.dynamicPageTitle.snapped = this.headerSnapped; } + this.isExpanding = true; } onPinClick() { this.headerPinned = !this.headerPinned; } + + /// + + _debounce(fn: () => void, delay: number) { + clearTimeout(this._debounceInterval!); + this._debounceInterval = setTimeout(() => { + this._debounceInterval = null; + fn(); + }, delay); + } } DynamicPage.define(); diff --git a/packages/fiori/src/themes/DynamicPage.css b/packages/fiori/src/themes/DynamicPage.css index 090385fad96b..af3b349b5ad5 100644 --- a/packages/fiori/src/themes/DynamicPage.css +++ b/packages/fiori/src/themes/DynamicPage.css @@ -14,6 +14,12 @@ z-index: 1; } +:host { + display: block; + overflow-y: scroll; + height: 100%; +} + ::slotted([slot="footer"]) { /* TODO css vars? */ border: 1px solid; diff --git a/packages/fiori/test/pages/DynamicPage.html b/packages/fiori/test/pages/DynamicPage.html index 781bdf64224c..26e6eb8883f4 100644 --- a/packages/fiori/test/pages/DynamicPage.html +++ b/packages/fiori/test/pages/DynamicPage.html @@ -7,7 +7,7 @@ /> - Flexible Column Layout + Dynamic page - + + diff --git a/packages/fiori/test/pages/styles/DynamicPage.css b/packages/fiori/test/pages/styles/DynamicPage.css new file mode 100644 index 000000000000..c3d6751ac79a --- /dev/null +++ b/packages/fiori/test/pages/styles/DynamicPage.css @@ -0,0 +1,3 @@ +html, body { + height: 100%; +} \ No newline at end of file