diff --git a/packages/fiori/cypress/specs/Search.cy.tsx b/packages/fiori/cypress/specs/Search.cy.tsx
index 9182c3c65390..0d7616a79cec 100644
--- a/packages/fiori/cypress/specs/Search.cy.tsx
+++ b/packages/fiori/cypress/specs/Search.cy.tsx
@@ -891,6 +891,122 @@ describe("Events", () => {
.should("not.exist")
});
+ it("delete event is fired on clicking the delete button of a search item", () => {
+ cy.mount(
+
+
+
+ );
+
+ cy.get("[ui5-search]")
+ .shadow()
+ .find("input")
+ .realClick();
+
+ cy.get("[ui5-search]")
+ .realPress("I");
+
+ cy.get("[ui5-search]")
+ .realPress("ArrowDown");
+
+ cy.get("[ui5-search-item]").eq(0)
+ .as("firstSearchItem");
+
+ cy.get("@firstSearchItem")
+ .shadow()
+ .find("[ui5-button]")
+ .realClick();
+
+ cy.get("@deleteSpy").should("have.been.calledOnce");
+ });
+
+ it("Fast navigation with F2 key press", () => {
+ cy.mount(
+
+
+
+ );
+
+ cy.get("[ui5-search]")
+ .shadow()
+ .find("input")
+ .realClick();
+
+ cy.get("[ui5-search]")
+ .realPress("I");
+
+ cy.get("[ui5-search]")
+ .realPress("ArrowDown");
+
+ cy.get("[ui5-search-item]").eq(0)
+ .as("firstSearchItem");
+
+ cy.get("@firstSearchItem")
+ .should("be.focused");
+
+ cy.realPress("F2");
+
+ cy.get("@firstSearchItem")
+ .shadow()
+ .find("[ui5-button]")
+ .should("be.focused");
+
+ cy.realPress("F2");
+
+ cy.get("@firstSearchItem")
+ .should("be.focused");
+ });
+
+ it("delete event is fired on pressing SPACE on the focused delete button of a search item", () => {
+ cy.mount(
+
+
+
+ );
+
+ cy.get("[ui5-search]")
+ .shadow()
+ .find("input")
+ .realClick();
+
+ cy.get("[ui5-search]")
+ .realPress("I");
+
+ cy.get("[ui5-search]")
+ .realPress("ArrowDown");
+
+ cy.realPress("F2");
+
+ cy.realPress("Space");
+
+ cy.get("@deleteSpy").should("have.been.calledOnce");
+ });
+
+ it("delete event is fired on pressing ENTER on the focused delete button of a search item", () => {
+ cy.mount(
+
+
+
+ );
+
+ cy.get("[ui5-search]")
+ .shadow()
+ .find("input")
+ .realClick();
+
+ cy.get("[ui5-search]")
+ .realPress("I");
+
+ cy.get("[ui5-search]")
+ .realPress("ArrowDown");
+
+ cy.realPress("F2");
+
+ cy.realPress("Enter");
+
+ cy.get("@deleteSpy").should("have.been.calledOnce");
+ });
+
it("should deselect items when backspace or delete key is pressed", () => {
cy.mount(
diff --git a/packages/fiori/src/SearchItem.ts b/packages/fiori/src/SearchItem.ts
index a60617910aa1..5ae95c6afa5c 100644
--- a/packages/fiori/src/SearchItem.ts
+++ b/packages/fiori/src/SearchItem.ts
@@ -8,6 +8,9 @@ import generateHighlightedMarkup from "@ui5/webcomponents-base/dist/util/generat
import jsxRenderer from "@ui5/webcomponents-base/dist/renderer/JsxRenderer.js";
import event from "@ui5/webcomponents-base/dist/decorators/event-strict.js";
import { SEARCH_ITEM_DELETE_BUTTON } from "./generated/i18n/i18n-defaults.js";
+import getActiveElement from "@ui5/webcomponents-base/dist/util/getActiveElement.js";
+import { getFirstFocusableElement } from "@ui5/webcomponents-base/dist/util/FocusableElements.js";
+import { isSpace, isEnter, isF2 } from "@ui5/webcomponents-base/dist/Keys.js";
import { i18n } from "@ui5/webcomponents-base/dist/decorators.js";
import type I18nBundle from "@ui5/webcomponents-base/dist/i18nBundle.js";
// @ts-expect-error
@@ -129,10 +132,44 @@ class SearchItem extends ListItemBase {
this.selected = false;
}
+ async _onkeydown(e: KeyboardEvent) {
+ super._onkeydown(e);
+
+ if (this.getFocusDomRef()!.matches(":has(:focus-within)")) {
+ if (isSpace(e) || isEnter(e)) {
+ e.preventDefault();
+ return;
+ }
+ }
+
+ if (isF2(e)) {
+ e.stopImmediatePropagation();
+ const activeElement = getActiveElement();
+ const focusDomRef = this.getFocusDomRef();
+
+ if (!focusDomRef) {
+ return;
+ }
+
+ if (activeElement === focusDomRef) {
+ const firstFocusable = await getFirstFocusableElement(focusDomRef);
+ firstFocusable?.focus();
+ } else {
+ focusDomRef.focus();
+ }
+ }
+ }
+
_onDeleteButtonClick() {
this.fireDecoratorEvent("delete");
}
+ _onDeleteButtonKeyDown(e: KeyboardEvent) {
+ if (isSpace(e) || isEnter(e)) {
+ this.fireDecoratorEvent("delete");
+ }
+ }
+
onBeforeRendering(): void {
super.onBeforeRendering();
diff --git a/packages/fiori/src/SearchItemTemplate.tsx b/packages/fiori/src/SearchItemTemplate.tsx
index 963120818e45..489a516e069d 100644
--- a/packages/fiori/src/SearchItemTemplate.tsx
+++ b/packages/fiori/src/SearchItemTemplate.tsx
@@ -45,7 +45,12 @@ export default function SearchFieldTemplate(this: SearchItem) {
{this.deletable &&
-
+
}
diff --git a/packages/fiori/test/pages/Search.html b/packages/fiori/test/pages/Search.html
index dee7fba812d8..4a857726067c 100644
--- a/packages/fiori/test/pages/Search.html
+++ b/packages/fiori/test/pages/Search.html
@@ -255,15 +255,6 @@
{ name: 'Tomato', category: 'Vegetable' },
];
- function createItems(parent, data) {
- data.forEach(item => {
- const searchItem = document.createElement('ui5-search-item');
- searchItem.text = item.name;
- searchItem.icon = 'search';
- parent.appendChild(searchItem);
- });
- }
-
const filtering = document.getElementById('filtering');
createItems(filtering, data);
filtering.addEventListener('ui5-input', (event) => {
@@ -370,10 +361,11 @@
const searchDelete = document.getElementById('delete-search');
- function onDelete(event) {
+ function onDelete(event, parent) {
const item = event.target;
if (item) {
item.remove();
+ parent.focus();
}
}
@@ -392,7 +384,7 @@
searchItem.text = item.name;
searchItem.icon = 'search';
searchItem.deletable = true;
- searchItem.addEventListener('ui5-delete', onDelete);
+ searchItem.addEventListener('ui5-delete', (e) => onDelete(e, parent));
parent.appendChild(searchItem);
});
}