From e345b56344bdecc4856b71f47c16f21586f5f4f3 Mon Sep 17 00:00:00 2001 From: Diana Pazheva Date: Tue, 9 Dec 2025 22:03:51 +0200 Subject: [PATCH 1/5] feat(ui5-list): add sticky header property --- packages/main/cypress/specs/List.cy.tsx | 74 +++++++++++++++++++ packages/main/src/List.ts | 11 +++ packages/main/src/ListTemplate.tsx | 59 +++++++-------- packages/main/src/themes/List.css | 10 ++- packages/main/test/pages/List.html | 42 +++++++++++ packages/main/test/pages/styles/List.css | 4 + .../docs/_components_pages/main/List/List.mdx | 6 ++ .../main/List/StickyHeader/StickyHeader.md | 4 + .../_samples/main/List/StickyHeader/main.js | 4 + .../main/List/StickyHeader/sample.html | 32 ++++++++ 10 files changed, 216 insertions(+), 30 deletions(-) create mode 100644 packages/website/docs/_samples/main/List/StickyHeader/StickyHeader.md create mode 100644 packages/website/docs/_samples/main/List/StickyHeader/main.js create mode 100644 packages/website/docs/_samples/main/List/StickyHeader/sample.html diff --git a/packages/main/cypress/specs/List.cy.tsx b/packages/main/cypress/specs/List.cy.tsx index 46e608d738eb..0775f3d7bb89 100644 --- a/packages/main/cypress/specs/List.cy.tsx +++ b/packages/main/cypress/specs/List.cy.tsx @@ -12,6 +12,7 @@ import ResponsivePopover from "../../src/ResponsivePopover.js"; import Select from "../../src/Select.js"; import Option from "../../src/Option.js"; import CheckBox from "../../src/CheckBox.js"; +import Bar from "../../src/Bar.js"; function getGrowingWithScrollList(length: number, height: string = "100px") { return ( @@ -2516,4 +2517,77 @@ describe("List keyboard drag and drop tests", () => { cy.get("#item9").prev().should("have.id", "item4"); }); +}); + +describe("List sticky header", () => { + it("sticks default header", () => { + cy.mount( +
+ + Item 1 + Item 2 + Item 3 + +
+
+ ); + + cy.get("#scrollContainer") + .as("container"); + + cy.get("[ui5-list]") + .shadow() + .find(".ui5-list-header") + .as("header"); + + cy.get("@header") + .then(($headerBefore) => { + const headerTopBefore = $headerBefore[0].getBoundingClientRect().top; + + cy.get("@container") + .scrollTo(0, 50); + + cy.get("@header") + .should(($headerAfter) => { + const headerTopAfter = $headerAfter[0].getBoundingClientRect().top; + expect(headerTopAfter).to.eq(headerTopBefore); + }); + }); + }); + + it("sticks custom header", () => { + cy.mount( +
+ + + Sticky Header Bar + + Item 1 + Item 2 + Item 3 + +
+
+ ); + + cy.get("#scrollContainer") + .as("container"); + + cy.get("[ui5-bar]") + .as("header"); + + cy.get("@header") + .then(($headerBefore) => { + const headerTopBefore = $headerBefore[0].getBoundingClientRect().top; + + cy.get("@container") + .scrollTo(0, 50); + + cy.get("@header") + .should(($headerAfter) => { + const headerTopAfter = $headerAfter[0].getBoundingClientRect().top; + expect(headerTopAfter).to.eq(headerTopBefore); + }); + }); + }); }); \ No newline at end of file diff --git a/packages/main/src/List.ts b/packages/main/src/List.ts index 92e881c7cf2a..61e86cb021ce 100644 --- a/packages/main/src/List.ts +++ b/packages/main/src/List.ts @@ -396,6 +396,17 @@ class List extends UI5Element { @property({ type: Number }) loadingDelay = 1000; + /** + * Indicates whether the List header is sticky or not. + * If stickyHeader is set to true, then whenever you scroll the content or + * the application, the header of the list will be always visible. + * @default false + * @public + * @since 2.18.0 + */ + @property({ type: Boolean }) + stickyHeader = false; + /** * Defines the accessible name of the component. * @default undefined diff --git a/packages/main/src/ListTemplate.tsx b/packages/main/src/ListTemplate.tsx index ff00c185bc94..913f21783e63 100644 --- a/packages/main/src/ListTemplate.tsx +++ b/packages/main/src/ListTemplate.tsx @@ -29,8 +29,7 @@ export default function ListTemplate(this: List) { active={this.showBusyIndicatorOverlay} class="ui5-list-busy-indicator" > - -
+
{this.header.length > 0 && } @@ -41,40 +40,42 @@ export default function ListTemplate(this: List) { } - {this.hasData && -
- } +
- {this.ariaLabelModeText} + {this.hasData && +
+ } -
    - + {this.ariaLabelModeText} - {this.showNoDataText && -
  • -
    - {this.noDataText} -
    -
  • - } -
+
    + - { this.growsWithButton && moreRow.call(this) } + {this.showNoDataText && +
  • +
    + {this.noDataText} +
    +
  • + } +
- {this.footerText && -
{this.footerText}
- } + { this.growsWithButton && moreRow.call(this) } - {this.hasData && -
- } + {this.footerText && +
{this.footerText}
+ } + {this.hasData && +
+ } +
diff --git a/packages/main/src/themes/List.css b/packages/main/src/themes/List.css index 748e613f614e..734229e88053 100644 --- a/packages/main/src/themes/List.css +++ b/packages/main/src/themes/List.css @@ -17,7 +17,8 @@ } .ui5-list-root, -.ui5-list-busy-indicator { +.ui5-list-busy-indicator, +.ui5-list-container { width: 100%; height: 100%; position: relative; @@ -111,4 +112,11 @@ :host([growing="Scroll"]) .ui5-list-end-marker { /* Ensure the list-end-marker has a block property to always be stretched and "visible" on the screen */ display: inline-block; +} + +:host([sticky-header]) ::slotted([slot="header"]), +:host([sticky-header]) .ui5-list-header { + position: sticky; + top: 0; + z-index: 100; } \ No newline at end of file diff --git a/packages/main/test/pages/List.html b/packages/main/test/pages/List.html index 2e7b7f36176e..896e1e58bd40 100644 --- a/packages/main/test/pages/List.html +++ b/packages/main/test/pages/List.html @@ -89,6 +89,46 @@

+

List with sticky header

+ + + Sticky Header Bar + Action + + Item 1 + Item 2 + Item 3 + Item 4 + Item 5 + Item 6 + Item 7 + Item 8 + Item 9 + Item 10 + Item 11 + Item 12 + Item 13 + Item 14 + Item 15 + + + + Item 1 + Item 2 + Item 3 + Item 4 + Item 5 + Item 6 + Item 7 + Item 8 + Item 9 + Item 10 + Item 11 + Item 12 + Item 13 + Item 14 + Item 15 +

List growing="Button" and growing-button-text property used

@@ -688,6 +728,8 @@

With accessible description

+ + + + + + From 97d23ffad7a737cca59fca6a1e0e6bb0abaa042b Mon Sep 17 00:00:00 2001 From: Diana Pazheva Date: Mon, 15 Dec 2025 11:54:27 +0200 Subject: [PATCH 2/5] feat(ui5-list): update sample --- .../_samples/main/List/StickyHeader/main.js | 2 +- .../main/List/StickyHeader/sample.html | 32 ++++++++++++------- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/packages/website/docs/_samples/main/List/StickyHeader/main.js b/packages/website/docs/_samples/main/List/StickyHeader/main.js index d64eb151d6a0..4cbcf2b9899a 100644 --- a/packages/website/docs/_samples/main/List/StickyHeader/main.js +++ b/packages/website/docs/_samples/main/List/StickyHeader/main.js @@ -1,4 +1,4 @@ import "@ui5/webcomponents/dist/List.js"; import "@ui5/webcomponents/dist/ListItemStandard.js"; -import "@ui5/webcomponents-icons/dist/product.js"; \ No newline at end of file +import "@ui5/webcomponents-icons/dist/nutrition-activity.js"; \ No newline at end of file diff --git a/packages/website/docs/_samples/main/List/StickyHeader/sample.html b/packages/website/docs/_samples/main/List/StickyHeader/sample.html index caab0014c9df..97a90786b916 100644 --- a/packages/website/docs/_samples/main/List/StickyHeader/sample.html +++ b/packages/website/docs/_samples/main/List/StickyHeader/sample.html @@ -5,23 +5,33 @@ - Sample + Sticky Header Sample - Item #1 - Item #2 - Item #3 - Item #4 - Item #5 - Item #6 - Item #7 - Item #8 - Item #9 - Item #10 + Pineapple + Orange + Blueberry + Mango + Apple + Banana + Strawberry + Grape + Papaya + Kiwi From d6f49756b18be77703c41bd7f25abc7af17c30ed Mon Sep 17 00:00:00 2001 From: Diana Pazheva Date: Mon, 15 Dec 2025 12:20:28 +0200 Subject: [PATCH 3/5] feat(ui5-list): update sample --- .../_samples/main/List/StickyHeader/main.css | 8 ++++ .../main/List/StickyHeader/sample.html | 48 ++++++++++--------- 2 files changed, 34 insertions(+), 22 deletions(-) create mode 100644 packages/website/docs/_samples/main/List/StickyHeader/main.css diff --git a/packages/website/docs/_samples/main/List/StickyHeader/main.css b/packages/website/docs/_samples/main/List/StickyHeader/main.css new file mode 100644 index 000000000000..82d3ee089e97 --- /dev/null +++ b/packages/website/docs/_samples/main/List/StickyHeader/main.css @@ -0,0 +1,8 @@ +.scrollContainer { + height: 300px; + overflow: auto; +} + +.heading { + margin: 2rem 0 2rem 1rem; +} \ No newline at end of file diff --git a/packages/website/docs/_samples/main/List/StickyHeader/sample.html b/packages/website/docs/_samples/main/List/StickyHeader/sample.html index 97a90786b916..a1fa55e10d4b 100644 --- a/packages/website/docs/_samples/main/List/StickyHeader/sample.html +++ b/packages/website/docs/_samples/main/List/StickyHeader/sample.html @@ -6,33 +6,37 @@ Sticky Header Sample + - - Pineapple - Orange - Blueberry - Mango - Apple - Banana - Strawberry - Grape - Papaya - Kiwi - +
+ Scroll down to see the sticky header in action + + Pineapple + Orange + Blueberry + Mango + Apple + Banana + Strawberry + Grape + Papaya + Kiwi + +
From d035aeaa7558d9a63888e06f51c1568aa82358ef Mon Sep 17 00:00:00 2001 From: Diana Pazheva Date: Mon, 15 Dec 2025 14:45:29 +0200 Subject: [PATCH 4/5] feat(ui5-list): correct start-end markers of scroll container --- packages/main/src/ListTemplate.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/main/src/ListTemplate.tsx b/packages/main/src/ListTemplate.tsx index 913f21783e63..c3c0809a1459 100644 --- a/packages/main/src/ListTemplate.tsx +++ b/packages/main/src/ListTemplate.tsx @@ -30,7 +30,6 @@ export default function ListTemplate(this: List) { class="ui5-list-busy-indicator" >
- {this.header.length > 0 && } @@ -41,6 +40,7 @@ export default function ListTemplate(this: List) { }
+ {this.hasData &&
@@ -75,8 +75,8 @@ export default function ListTemplate(this: List) { {this.hasData &&
} +
-
From 553f0d2389523d731f3b26b5d2a7daf043ba547e Mon Sep 17 00:00:00 2001 From: Diana Pazheva Date: Mon, 15 Dec 2025 15:08:26 +0200 Subject: [PATCH 5/5] feat(ui5-list): remove redundant newlined --- packages/main/test/pages/List.html | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/main/test/pages/List.html b/packages/main/test/pages/List.html index 896e1e58bd40..631f663e4395 100644 --- a/packages/main/test/pages/List.html +++ b/packages/main/test/pages/List.html @@ -728,8 +728,6 @@

With accessible description

- -