Skip to content

Commit c502c6b

Browse files
-improved logic with less hard coded values and redundant maintainable code
1 parent 5b28355 commit c502c6b

2 files changed

Lines changed: 119 additions & 5 deletions

File tree

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

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import Select from "../../src/Select.js";
1313
import Option from "../../src/Option.js";
1414
import CheckBox from "../../src/CheckBox.js";
1515
import Bar from "../../src/Bar.js";
16+
import Link from "../../src/Link.js";
1617

1718
function getGrowingWithScrollList(length: number, height: string = "100px") {
1819
return (
@@ -729,6 +730,98 @@ describe("List Tests", () => {
729730
cy.get("@itemClickStub").should("not.have.been.called");
730731
});
731732

733+
it("fires item-click when nested ui5-link is clicked", () => {
734+
cy.mount(
735+
<List>
736+
<ListItemCustom>
737+
<div>
738+
<span>First List Item</span>
739+
<Link id="nested-link" href="#">Details</Link>
740+
</div>
741+
</ListItemCustom>
742+
</List>
743+
);
744+
745+
cy.get("[ui5-list]").then(($list) => {
746+
$list[0].addEventListener("ui5-item-click", cy.stub().as("itemClickStub"));
747+
});
748+
749+
cy.get("#nested-link").then(($link) => {
750+
const linkClickStub = cy.stub().as("linkClickStub");
751+
$link[0].addEventListener("click", linkClickStub);
752+
});
753+
754+
cy.get("#nested-link").click();
755+
756+
cy.get("@linkClickStub").should("have.been.calledOnce");
757+
cy.get("@itemClickStub").should("have.been.calledOnce");
758+
});
759+
760+
it("does not fire item-click when nested disabled custom element is clicked", () => {
761+
cy.mount(
762+
<List>
763+
<ListItemCustom>
764+
<div>
765+
<span>First List Item</span>
766+
<div id="custom-host"></div>
767+
</div>
768+
</ListItemCustom>
769+
</List>
770+
);
771+
772+
cy.get("[ui5-list]").then(($list) => {
773+
$list[0].addEventListener("ui5-item-click", cy.stub().as("itemClickStub"));
774+
});
775+
776+
cy.get("#custom-host").then(($host) => {
777+
const customAction = document.createElement("x-action");
778+
customAction.id = "disabled-custom-action";
779+
customAction.setAttribute("aria-disabled", "true");
780+
customAction.textContent = "Disabled Action";
781+
$host[0].appendChild(customAction);
782+
783+
const customClickStub = cy.stub().as("customClickStub");
784+
customAction.addEventListener("click", customClickStub);
785+
});
786+
787+
cy.get("#disabled-custom-action").click();
788+
789+
cy.get("@customClickStub").should("have.been.calledOnce");
790+
cy.get("@itemClickStub").should("not.have.been.called");
791+
});
792+
793+
it("fires item-click when nested custom element is not disabled", () => {
794+
cy.mount(
795+
<List>
796+
<ListItemCustom>
797+
<div>
798+
<span>First List Item</span>
799+
<div id="custom-host-enabled"></div>
800+
</div>
801+
</ListItemCustom>
802+
</List>
803+
);
804+
805+
cy.get("[ui5-list]").then(($list) => {
806+
$list[0].addEventListener("ui5-item-click", cy.stub().as("itemClickStub"));
807+
});
808+
809+
cy.get("#custom-host-enabled").then(($host) => {
810+
const customAction = document.createElement("x-action");
811+
customAction.id = "enabled-custom-action";
812+
customAction.textContent = "Enabled Action";
813+
$host[0].appendChild(customAction);
814+
815+
const customClickStub = cy.stub().as("customClickStub");
816+
customAction.addEventListener("click", customClickStub);
817+
});
818+
819+
cy.get("#enabled-custom-action").click();
820+
821+
cy.get("@customClickStub").should("have.been.calledOnce");
822+
cy.get("@itemClickStub").should("have.been.calledOnce");
823+
});
824+
732825
it("selectionChange events provides previousSelection item", () => {
733826
cy.mount(
734827
<div>

packages/main/src/ListItemBase.ts

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -173,24 +173,45 @@ class ListItemBase extends UI5Element implements ITabbable {
173173

174174
_isDisabledInteractiveContentClicked(e: MouseEvent): boolean {
175175
const path = e.composedPath();
176+
const focusDomRef = this.getFocusDomRef();
176177

177178
return path.some(target => {
178179
if (!(target instanceof HTMLElement)) {
179180
return false;
180181
}
181182

182-
if (target.matches("button, input, select, textarea")) {
183-
return (target as HTMLButtonElement | HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement).disabled;
183+
if (target === this || target === focusDomRef) {
184+
return false;
184185
}
185186

186-
if (target.matches("ui5-button, ui5-input, ui5-textarea, ui5-select, ui5-combobox, ui5-multi-combobox, ui5-switch, ui5-checkbox, ui5-radio-button, ui5-date-picker, ui5-daterange-picker, ui5-time-picker, ui5-step-input")) {
187-
return !!(target as { disabled?: boolean }).disabled;
187+
if (!this._isNativeInteractiveElement(target) && !this._isCustomInteractiveElement(target)) {
188+
return false;
188189
}
189190

190-
return false;
191+
return this._isElementDisabled(target);
191192
});
192193
}
193194

195+
_isNativeInteractiveElement(target: HTMLElement): boolean {
196+
return target.matches("button, input, select, textarea");
197+
}
198+
199+
_isCustomInteractiveElement(target: HTMLElement): boolean {
200+
const targetWithDisabled = target as HTMLElement & { disabled?: boolean };
201+
202+
return target.tagName.includes("-")
203+
&& ("disabled" in targetWithDisabled || target.hasAttribute("aria-disabled"));
204+
}
205+
206+
_isElementDisabled(target: HTMLElement): boolean {
207+
const targetWithDisabled = target as HTMLElement & { disabled?: boolean };
208+
if (typeof targetWithDisabled.disabled === "boolean") {
209+
return targetWithDisabled.disabled;
210+
}
211+
212+
return target.getAttribute("aria-disabled") === "true";
213+
}
214+
194215
/**
195216
* Override from subcomponent, if needed
196217
*/

0 commit comments

Comments
 (0)