diff --git a/packages/main/cypress/specs/Icon.cy.tsx b/packages/main/cypress/specs/Icon.cy.tsx index 1acf9e87530c..3256add32a05 100644 --- a/packages/main/cypress/specs/Icon.cy.tsx +++ b/packages/main/cypress/specs/Icon.cy.tsx @@ -109,24 +109,28 @@ describe("Icon general interaction", () => { }); }); + // Mouse click fires both native click and ui5-click for interactive icons cy.get("@interactiveIcon").click(); cy.get("[ui5-input]").eq(0).should("have.prop", "value", "1"); - cy.get("[ui5-input]").eq(1).should("have.prop", "value", "0"); + cy.get("[ui5-input]").eq(1).should("have.prop", "value", "1"); + // Enter key fires both native click and ui5-click for interactive icons cy.get("@interactiveIcon").realPress("Enter"); cy.get("[ui5-input]").eq(0).should("have.prop", "value", "2"); - cy.get("[ui5-input]").eq(1).should("have.prop", "value", "1"); + cy.get("[ui5-input]").eq(1).should("have.prop", "value", "2"); + // Space key fires both native click and ui5-click for interactive icons cy.get("@interactiveIcon").realPress("Space"); cy.get("[ui5-input]").eq(0).should("have.prop", "value", "3"); - cy.get("[ui5-input]").eq(1).should("have.prop", "value", "2"); + cy.get("[ui5-input]").eq(1).should("have.prop", "value", "3"); + // Non-interactive icon: mouse click fires native click but NOT ui5-click cy.get("@nonInteractiveIcon").click(); cy.get("[ui5-input]").eq(2).should("have.prop", "value", "1"); cy.get("[ui5-input]").eq(3).should("have.prop", "value", "0"); cy.get("@interactiveClickStub").should("have.been.calledThrice"); - cy.get("@interactiveUI5ClickStub").should("have.been.calledTwice"); + cy.get("@interactiveUI5ClickStub").should("have.been.calledThrice"); cy.get("@nonInteractiveClickStub").should("have.been.calledOnce"); cy.get("@nonInteractiveUI5ClickStub").should("not.have.been.called"); diff --git a/packages/main/src/Icon.ts b/packages/main/src/Icon.ts index 9c997af0e1ee..ec1b43aa342f 100644 --- a/packages/main/src/Icon.ts +++ b/packages/main/src/Icon.ts @@ -89,7 +89,6 @@ const ICON_NOT_FOUND = "ICON_NOT_FOUND"; * ### Keyboard Handling * * - [Space] / [Enter] or [Return] - Fires the `click` event if the `mode` property is set to `Interactive`. - * - [Shift] - If [Space] / [Enter] or [Return] is pressed, pressing [Shift] releases the ui5-icon without triggering the click event. * * ### ES6 Module Import * @@ -109,9 +108,10 @@ const ICON_NOT_FOUND = "ICON_NOT_FOUND"; styles: iconCss, }) /** - * Fired on mouseup, `SPACE` and `ENTER`. - * - on mouse click, the icon fires native `click` event - * - on `SPACE` and `ENTER`, the icon fires custom `click` event + * Fired when the component is activated by mouse/touch, keyboard (Enter or Space), + * or screen reader virtual cursor activation. + * + * **Note:** The event will not be fired if the `mode` property is set to `Decorative` or `Image`. * @public * @since 2.11.0 */ @@ -224,6 +224,17 @@ class Icon extends UI5Element implements IIcon { customTemplate?: object; customTemplateAsString?: string; + _onclick(e: MouseEvent) { + if (this.mode !== IconMode.Interactive) { + return; + } + + // prevents the native browser "click" event from firing + e.stopImmediatePropagation(); + + this.fireDecoratorEvent("click"); + } + _onkeydown(e: KeyboardEvent) { if (this.mode !== IconMode.Interactive) { return; diff --git a/packages/main/src/IconTemplate.tsx b/packages/main/src/IconTemplate.tsx index 8c0ab0355765..380161620a01 100644 --- a/packages/main/src/IconTemplate.tsx +++ b/packages/main/src/IconTemplate.tsx @@ -16,6 +16,7 @@ export default function IconTemplate(this: Icon) { xmlns="http://www.w3.org/2000/svg" onKeyDown={this._onkeydown} onKeyUp={this._onkeyup} + onClick={this._onclick} > { this.hasIconTooltip && {this.effectiveAccessibleName}