Skip to content

Commit 6bc4f0a

Browse files
authored
feat(ui5-link): add default text slot (#12781)
The problem was that the `ui5-link` component was missing a `@slot` decorator for its default text slot. Without this decorator: - The component didnt invalidate when slot content changed - The effectiveTabIndex getter (which checks this.textContent?.length) wasn't re-evaluated after text was added - The initial tabindex of -1 (set during first render when there was no text) remained unchanged So we add the `@slot` decorator to the default text slot, following the same pattern used in the`ui5-button` component: This ensures that: - When text content is added, removed, or changed in the slot, the component is **invalidated** - The component re-renders and recalculates `effectiveTabIndex` - The `tabindex` attribute in the shadow DOM is updated correctly
1 parent 1884137 commit 6bc4f0a

2 files changed

Lines changed: 71 additions & 0 deletions

File tree

packages/main/cypress/specs/Link.cy.tsx

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,4 +260,65 @@ describe("General API", () => {
260260
cy.get("@signInDialog")
261261
.should("be.visible");
262262
});
263+
264+
it("tabindex should update when text content is added after mount", () => {
265+
// Mount link without text content
266+
cy.mount(<Link id="dynamic-link"></Link>);
267+
268+
// Initially, tabindex should be -1 because there's no text content
269+
cy.get("#dynamic-link")
270+
.shadow()
271+
.find(".ui5-link-root")
272+
.should("have.attr", "tabindex", "-1");
273+
274+
// Add text content dynamically
275+
cy.get("#dynamic-link")
276+
.then($link => {
277+
$link[0].textContent = "Click me";
278+
});
279+
280+
// After text is added, tabindex should become 0
281+
cy.get("#dynamic-link")
282+
.shadow()
283+
.find(".ui5-link-root")
284+
.should("have.attr", "tabindex", "0");
285+
});
286+
287+
it("tabindex should remain 0 when text content changes", () => {
288+
cy.mount(<Link id="text-change-link">Initial Text</Link>);
289+
290+
cy.get("#text-change-link")
291+
.shadow()
292+
.find(".ui5-link-root")
293+
.should("have.attr", "tabindex", "0");
294+
295+
cy.get("#text-change-link")
296+
.then($link => {
297+
$link[0].textContent = "Updated Text";
298+
});
299+
300+
cy.get("#text-change-link")
301+
.shadow()
302+
.find(".ui5-link-root")
303+
.should("have.attr", "tabindex", "0");
304+
});
305+
306+
it("tabindex should be -1 when text content is removed", () => {
307+
cy.mount(<Link id="remove-text-link">Some text</Link>);
308+
309+
cy.get("#remove-text-link")
310+
.shadow()
311+
.find(".ui5-link-root")
312+
.should("have.attr", "tabindex", "0");
313+
314+
cy.get("#remove-text-link")
315+
.then($link => {
316+
$link[0].textContent = "";
317+
});
318+
319+
cy.get("#remove-text-link")
320+
.shadow()
321+
.find(".ui5-link-root")
322+
.should("have.attr", "tabindex", "-1");
323+
});
263324
});

packages/main/src/Link.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js";
22
import customElement from "@ui5/webcomponents-base/dist/decorators/customElement.js";
33
import event from "@ui5/webcomponents-base/dist/decorators/event-strict.js";
44
import property from "@ui5/webcomponents-base/dist/decorators/property.js";
5+
import slot from "@ui5/webcomponents-base/dist/decorators/slot.js";
56
import jsxRenderer from "@ui5/webcomponents-base/dist/renderer/JsxRenderer.js";
67
import type { AccessibilityAttributes } from "@ui5/webcomponents-base/dist/types.js";
78
import { isSpace, isEnter } from "@ui5/webcomponents-base/dist/Keys.js";
@@ -268,6 +269,15 @@ class Link extends UI5Element implements ITabbable {
268269
@property()
269270
endIcon?: string;
270271

272+
/**
273+
* Defines the text of the component.
274+
*
275+
* **Note:** Although this slot accepts HTML Elements, it is strongly recommended that you only use text in order to preserve the intended design.
276+
* @public
277+
*/
278+
@slot({ type: Node, "default": true })
279+
text!: Array<Node>;
280+
271281
@property({ noAttribute: true })
272282
_rel: string | undefined;
273283

0 commit comments

Comments
 (0)