From ac1e5c584e8e711e47603a01d4d058dfdc24e6a6 Mon Sep 17 00:00:00 2001 From: Gergana Georgieva Date: Tue, 17 Mar 2026 15:04:26 +0200 Subject: [PATCH] fix(ui5-expandable-text): scroll toggle link into view on expansion When expanding long text with keyboard navigation, the "Show Less" link now automatically scrolls into view, ensuring it's visible to keyboard users. Fixes #13258 --- .../main/cypress/specs/ExpandableText.cy.tsx | 30 +++++++++++++++++++ packages/main/src/ExpandableText.ts | 22 ++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/packages/main/cypress/specs/ExpandableText.cy.tsx b/packages/main/cypress/specs/ExpandableText.cy.tsx index c83050b218a0..5abd96f812e7 100644 --- a/packages/main/cypress/specs/ExpandableText.cy.tsx +++ b/packages/main/cypress/specs/ExpandableText.cy.tsx @@ -173,6 +173,36 @@ describe("ExpandableText", () => { .should("exist"); }); + it("Scroll toggle link into view after expansion with long text (accessibility)", () => { + // Generate long text that will definitely push content below viewport + const longText = "This is a very long text. ".repeat(50); + const maxCharacters = 10; + + cy.mount( +
+ + +
+ ); + + cy.get("[ui5-expandable-text]").shadow().as("expTextShadow"); + cy.get("@expTextShadow").find(".ui5-exp-text-toggle").as("toggle"); + + // Focus and expand + cy.get("#before").focus(); + cy.get("#before").realPress("Tab"); + + cy.get("@toggle") + .should("be.focused") + .realPress("Enter"); + + // After expansion, the toggle link (now showing "Show Less") should still be visible + // by checking that it's within the viewport + cy.get("@toggle") + .contains(EXPANDABLE_TEXT_SHOW_LESS.defaultText) + .should("be.visible"); + }); + it("ARIA attributes", () => { const text = "This is a very long text that should be displayed"; diff --git a/packages/main/src/ExpandableText.ts b/packages/main/src/ExpandableText.ts index 543b3cacf52e..c07c51e0d8d8 100644 --- a/packages/main/src/ExpandableText.ts +++ b/packages/main/src/ExpandableText.ts @@ -96,9 +96,26 @@ class ExpandableText extends UI5Element { @property({ type: Boolean }) _expanded = false; + @property({ type: Boolean }) + _shouldScrollIntoView = false; + @i18n("@ui5/webcomponents") static i18nBundle: I18nBundle; + onAfterRendering() { + if (this._shouldScrollIntoView) { + this._shouldScrollIntoView = false; + const toggleLink = this.shadowRoot?.querySelector("[ui5-link]") as HTMLElement; + if (toggleLink) { + toggleLink.scrollIntoView({ + behavior: "smooth", + block: "nearest", + inline: "nearest", + }); + } + } + } + getFocusDomRef(): HTMLElement | undefined { if (this._usePopover) { return this.shadowRoot?.querySelector("[ui5-responsive-popover]") as HTMLElement; @@ -168,6 +185,11 @@ class ExpandableText extends UI5Element { _handleToggleClick() { this._expanded = !this._expanded; + // Scroll the toggle link into view after expanding/collapsing, especially important + // when expanded content is long and pushes the "Show Less" link out of viewport + if (!this._usePopover) { + this._shouldScrollIntoView = true; + } } _handleCloseButtonClick(e: UI5CustomEvent) {