diff --git a/packages/fiori/cypress/specs/SideNavigation.cy.tsx b/packages/fiori/cypress/specs/SideNavigation.cy.tsx
index 4c660108600c..bb313950936d 100644
--- a/packages/fiori/cypress/specs/SideNavigation.cy.tsx
+++ b/packages/fiori/cypress/specs/SideNavigation.cy.tsx
@@ -6,6 +6,7 @@ import group from "@ui5/webcomponents-icons/dist/group.js";
import { NAVIGATION_MENU_POPOVER_HIDDEN_TEXT } from "../../src/generated/i18n/i18n-defaults.js";
import Title from "@ui5/webcomponents/dist/Title.js";
import Label from "@ui5/webcomponents/dist/Label.js";
+import ResponsivePopover from "@ui5/webcomponents/dist/ResponsivePopover.js";
describe("Side Navigation Rendering", () => {
it("Tests rendering in collapsed mode", () => {
@@ -222,6 +223,269 @@ describe("Side Navigation interaction", () => {
cy.get("#unselectableItem").should("be.focused").and("not.have.attr", "expanded");
});
+ it("Tests expanding of items with ArrowRight", () => {
+ cy.mount(
+
+
+
+
+
+
+ );
+
+ cy.get("#focusStart").realClick();
+ cy.realPress("ArrowDown");
+ cy.realPress("ArrowRight");
+
+ cy.get("#unselectableItem").should("have.attr", "expanded");
+ });
+
+ it("Tests collapsing of items with ArrowLeft", () => {
+ cy.mount(
+
+
+
+
+
+
+ );
+ cy.get("#focusStart").realClick();
+ cy.realPress("ArrowDown");
+ cy.realPress("ArrowLeft");
+
+ cy.get("#unselectableItem").should("not.have.attr", "expanded");
+
+ });
+
+ it("Tests expanding of items with ArrowRight on collapsed sn", () => {
+ cy.mount(
+
+
+
+
+
+
+ );
+
+ cy.get("#unselectableItem").realClick();
+
+ cy.get("#sn")
+ .shadow()
+ .find(`[ui5-side-navigation-item][text="1"]`)
+ .should('be.focused');
+
+ cy.realPress("ArrowLeft");
+ cy.get("#unselectableItem").should('be.focused');
+
+ cy.realPress("ArrowRight");
+ cy.get("#sn")
+ .shadow()
+ .find(`[ui5-side-navigation-item][text="1"]`)
+ .should('be.focused');
+
+ cy.get("#sn")
+ .shadow()
+ .find("[ui5-responsive-popover]")
+ .ui5ResponsivePopoverOpened();
+ });
+
+ it("Tests collapsing of items with ArrowLeft on collapsed sn", () => {
+ cy.mount(
+
+
+
+
+
+
+ );
+
+ cy.get("#unselectableItem").realClick();
+
+ cy.get("#sn")
+ .shadow()
+ .find(`[ui5-side-navigation-item][text="1"]`)
+ .should('be.focused'); // Фокуса на правилното място ли е след, като съм отворил popover?
+
+ cy.realPress("ArrowLeft"); // Ако фокуса е на правилното място, натисни ArrowLeft
+
+ cy.get("#unselectableItem").should('be.focused'); // След като съм натиснал ArrowLeft, провери дали фокуса е на правилното място
+
+ cy.get("#sn")
+ .shadow()
+ .find("[ui5-responsive-popover]")
+ .ui5ResponsivePopoverClosed(); // Ако фокуса е на правилното място провери дали popover-a е затворен, защото така очаквам
+ });
+
+ it("Tests expanding of items with ArrowLeft for rtl", () => {
+ cy.mount(
+
+
+
+
+
+
+
+
+ );
+
+ cy.get("#focusStart").realClick();
+ cy.realPress("ArrowDown");
+ cy.realPress("ArrowLeft");
+
+ cy.get("#unselectableItem").should("have.attr", "expanded");
+ });
+
+ it("Tests collapsing of items with ArrowRight for rtl", () => {
+ cy.mount(
+
+
+
+
+
+
+
+
+ );
+
+ cy.get("#unselectableItem").realClick();
+ cy.get("#unselectableItem").realPress("ArrowRight");
+
+ cy.get("#unselectableItem").should("not.have.attr", "expanded");
+
+ });
+
+ it("Tests expanding of items with ArrowLeft on collapsed sn for rtl", () => {
+ cy.mount(
+
+
+
+
+
+
+
+
+ );
+
+ cy.get("#unselectableItem").realClick();
+
+ cy.get("#sn")
+ .shadow()
+ .find(`[ui5-side-navigation-item][text="1"]`)
+ .should('be.focused');
+
+ cy.realPress("ArrowRight");
+
+ cy.get("#unselectableItem").should('be.focused');
+
+ cy.realPress("ArrowLeft");
+ cy.get("#sn")
+ .shadow()
+ .find(`[ui5-side-navigation-item][text="1"]`)
+ .should('be.focused');
+
+ cy.get("#sn")
+ .shadow()
+ .find("[ui5-responsive-popover]")
+ .ui5ResponsivePopoverOpened();
+ });
+
+ it("Tests collapsing of items with ArrowRight on collapsed sn for rtl", () => {
+ cy.mount(
+
+
+
+
+
+
+
+
+ );
+
+ cy.get("#unselectableItem").realClick();
+ cy.get("#sn")
+ .shadow()
+ .find(`[ui5-side-navigation-item][text="1"]`)
+ .should('be.focused');
+
+ cy.realPress("ArrowRight");
+
+ cy.get("#sn")
+ .shadow()
+ .find("[ui5-responsive-popover]")
+ .ui5ResponsivePopoverClosed();
+ });
+
+ it("Tests expanding of items with Plus", () => {
+ cy.mount(
+
+
+
+
+
+
+ );
+
+ cy.get("#focusStart").realClick();
+ cy.realPress("ArrowDown");
+ cy.realPress("+");
+
+ cy.get("#unselectableItem").should("have.attr", "expanded");
+
+ });
+
+ it("Tests collapsing of items with Minus", () => {
+ cy.mount(
+
+
+
+
+
+
+ );
+
+ cy.get("#unselectableItem").realClick();
+ cy.realPress("-");
+
+ cy.get("#unselectableItem").should("not.have.attr", "expanded");
+
+ });
+
+ it("Tests expanding of items with Plus for rtl", () => {
+ cy.mount(
+
+
+
+
+
+
+
+
+ );
+
+ cy.get("#focusStart").realClick();
+ cy.realPress("ArrowDown");
+ cy.realPress("+");
+
+ cy.get("#unselectableItem").should("have.attr", "expanded");
+ });
+
+ it("Tests collapsing of items with Minus for rtl", () => {
+ cy.mount(
+
+
+
+
+
+
+
+
+ );
+ cy.get("#unselectableItem").realClick();
+ cy.realPress("-");
+
+ cy.get("#unselectableItem").should("not.have.attr", "expanded");
+ });
+
it("Tests expanding and collapsing of unselectable parent item when SideNavigation is collapsed", () => {
cy.mount(
diff --git a/packages/fiori/cypress/specs/SideNavigationWithGroups.cy.tsx b/packages/fiori/cypress/specs/SideNavigationWithGroups.cy.tsx
index b99495c9912a..2dcfab827d90 100644
--- a/packages/fiori/cypress/specs/SideNavigationWithGroups.cy.tsx
+++ b/packages/fiori/cypress/specs/SideNavigationWithGroups.cy.tsx
@@ -94,35 +94,177 @@ describe("Component Behavior", () => {
.find(".ui5-sn-item")
.realClick();
cy.get("#group1").should("have.prop", "expanded", true);
+ });
+
+ it("Tests expanding of groups with ArrowRight", () => {
+ cy.mount(
+
+
+
+
+
+
+ );
- cy.get("#group2")
- .shadow()
- .find(".ui5-sn-item")
- .realClick();
- cy.get("#group2").should("have.prop", "expanded", false);
+ cy.get("#focusStart").realClick();
+ cy.realPress("ArrowDown");
+ cy.realPress("ArrowRight");
+
+ cy.get("#group1").should("have.attr", "expanded");
});
- it("disabled", () => {
+ it("Tests collapsing of groups with ArrowLeft", () => {
cy.mount(
-
-
-
-
-
+
+
+
+
- );
+
+ );
+
+ cy.get("#focusStart").realClick();
+ cy.realPress("ArrowDown");
+ cy.realPress("ArrowLeft");
+
+ cy.get("#group1").should("not.have.attr", "expanded");
+ });
+
+ it("Tests expanding of groups with ArrowLeft for rtl", () => {
+ cy.mount(
+
+
+
+
+
+
+
+
+ );
+
+ cy.get("#focusStart").realClick();
+ cy.realPress("ArrowDown");
+ cy.realPress("ArrowLeft");
+
+ cy.get("#group1").should("have.attr", "expanded");
+ });
+
+ it("Tests expanding of groups with ArrowRight for rtl", () => {
+ cy.mount(
+
+
+
+
+
+
+
+
+ );
+
+ cy.get("#focusStart").realClick();
+ cy.realPress("ArrowDown");
+ cy.realPress("ArrowRight");
+
+ cy.get("#group1").should("not.have.attr", "expanded");
+
+ });
+
+ it("Tests expanding of groups with Plus", () => {
+ cy.mount(
+
+
+
+
+
+
+ );
+
+ cy.get("#focusStart").realClick();
+ cy.realPress("ArrowDown");
+ cy.realPress("+");
+
+ cy.get("#group1").should("have.attr", "expanded");
+ });
+
+ it("Tests collapsing of groups with Minus", () => {
+ cy.mount(
+
+
+
+
+
+
+ );
+
+ cy.get("#focusStart").realClick();
+ cy.realPress("ArrowDown");
+ cy.realPress("-");
+
+ cy.get("#group1").should("not.have.attr", "expanded");
+ });
+
+ it("Tests expanding of groups with Plus for rtl", () => {
+ cy.mount(
+
+
+
+
+
+
+
+
+ );
+
+ cy.get("#focusStart").realClick();
+ cy.realPress("ArrowDown");
+ cy.realPress("+");
+
+ cy.get("#group1").should("have.attr", "expanded");
+
+ });
+
+ it("Tests collapsing of groups with Minus for rtl", () => {
+ cy.mount(
+
+
+
+
+
+
+
+
+ );
+
+ cy.get("#focusStart").realClick();
+ cy.realPress("ArrowDown");
+ cy.realPress("-");
+
+ cy.get("#group1").should("not.have.attr", "expanded");
- cy.get("#group1").should("not.have.attr", "disabled");
- cy.get("#group1").invoke("prop", "disabled", true);
- cy.get("#group1").should("have.attr", "disabled");
-
- cy.get("#group1").then(($group) => {
- const group = $group[0] as SideNavigationGroup;
- cy.wrap(group.items).each((item: SideNavigationItem) => {
- cy.wrap(item).should("have.prop", "disabled", true);
- });
- });
});
-
});
-});
+});
\ No newline at end of file
diff --git a/packages/fiori/src/SideNavigationGroup.ts b/packages/fiori/src/SideNavigationGroup.ts
index 9abe39c40036..682ba2742c08 100644
--- a/packages/fiori/src/SideNavigationGroup.ts
+++ b/packages/fiori/src/SideNavigationGroup.ts
@@ -155,12 +155,27 @@ class SideNavigationGroup extends SideNavigationItemBase {
}
_onkeydown(e: KeyboardEvent) {
- if (isLeft(e) || isMinus(e)) {
+ const isRTL = this.effectiveDir === "rtl";
+
+ if (isLeft(e)) {
+ e.preventDefault();
+ this.expanded = isRTL;
+ return;
+ }
+
+ if (isRight(e)) {
+ e.preventDefault();
+ this.expanded = !isRTL;
+ }
+
+ if (isMinus(e)) {
+ e.preventDefault();
this.expanded = false;
return;
}
- if (isRight(e) || isPlus(e)) {
+ if (isPlus(e)) {
+ e.preventDefault();
this.expanded = true;
}
}
diff --git a/packages/fiori/src/SideNavigationItem.ts b/packages/fiori/src/SideNavigationItem.ts
index 402d92819fc3..f47d078c6e40 100644
--- a/packages/fiori/src/SideNavigationItem.ts
+++ b/packages/fiori/src/SideNavigationItem.ts
@@ -71,7 +71,7 @@ class SideNavigationItem extends SideNavigationSelectableItemBase {
_fixed = false;
/**
- * Defines nested items by passing `ui5-side-navigation-sub-item` to the default slot.
+ * Defines nested items by passing `ui5-side-navigation-sub-item` to the default slot.
*
* @public
*/
@@ -85,6 +85,10 @@ class SideNavigationItem extends SideNavigationSelectableItemBase {
return [this];
}
+ get hasSubItems() {
+ return this.items.length > 0;
+ }
+
get selectableItems() : Array {
if (this.inPopover && this.unselectable && this.items.length) {
return [...this.items];
@@ -199,12 +203,33 @@ class SideNavigationItem extends SideNavigationSelectableItemBase {
}
_onkeydown(e: KeyboardEvent) {
- if (isLeft(e) || isMinus(e)) {
+ const isRTL = this.effectiveDir === "rtl";
+
+ if (this.sideNavigation.classList.contains("ui5-side-navigation-in-popover") || this.sideNavCollapsed) {
+ super._onkeydown(e);
+ return;
+ }
+
+ if (isLeft(e)) {
+ e.preventDefault();
+ this.expanded = isRTL;
+ return;
+ }
+
+ if (isRight(e)) {
+ e.preventDefault();
+ this.expanded = !isRTL;
+ return;
+ }
+
+ if (isMinus(e)) {
+ e.preventDefault();
this.expanded = false;
return;
}
- if (isRight(e) || isPlus(e)) {
+ if (isPlus(e)) {
+ e.preventDefault();
this.expanded = true;
return;
}
diff --git a/packages/fiori/src/SideNavigationItemBase.ts b/packages/fiori/src/SideNavigationItemBase.ts
index de1b3f989afe..a1f6b6223c5c 100644
--- a/packages/fiori/src/SideNavigationItemBase.ts
+++ b/packages/fiori/src/SideNavigationItemBase.ts
@@ -76,6 +76,10 @@ class SideNavigationItemBase extends UI5Element implements ITabbable {
return this.tooltip || undefined;
}
+ get hasSubItems() {
+ return false;
+ }
+
get classesArray() {
const classes = [];
diff --git a/packages/fiori/src/SideNavigationSelectableItemBase.ts b/packages/fiori/src/SideNavigationSelectableItemBase.ts
index 9ab84f33bd34..00e274de2566 100644
--- a/packages/fiori/src/SideNavigationSelectableItemBase.ts
+++ b/packages/fiori/src/SideNavigationSelectableItemBase.ts
@@ -1,7 +1,12 @@
import customElement from "@ui5/webcomponents-base/dist/decorators/customElement.js";
import property from "@ui5/webcomponents-base/dist/decorators/property.js";
import event from "@ui5/webcomponents-base/dist/decorators/event-strict.js";
-import { isSpace, isEnter } from "@ui5/webcomponents-base/dist/Keys.js";
+import {
+ isSpace,
+ isEnter,
+ isLeft,
+ isRight,
+} from "@ui5/webcomponents-base/dist/Keys.js";
import SideNavigationItemBase from "./SideNavigationItemBase.js";
import type SideNavigationItemDesign from "./types/SideNavigationItemDesign.js";
import type { AccessibilityAttributes } from "@ui5/webcomponents-base/dist/types.js";
@@ -139,6 +144,13 @@ class SideNavigationSelectableItemBase extends SideNavigationItemBase {
@property({ type: Boolean })
isOverflow = false;
+ /**
+ * Reference to the original side navigation item that opened the popover.
+ *
+ * @private
+ */
+ associatedItem?: SideNavigationItemBase;
+
get ariaRole() {
if (this.sideNavCollapsed) {
return this.isOverflow || this.unselectable ? "menuitem" : "menuitemradio";
@@ -194,13 +206,23 @@ class SideNavigationSelectableItemBase extends SideNavigationItemBase {
}
_onkeydown(e: KeyboardEvent) {
- if (isSpace(e)) {
+ const isRTL = this.effectiveDir === "rtl";
+
+ if (isSpace(e) || isRight(e) || isLeft(e)) {
e.preventDefault();
}
if (isEnter(e)) {
this._activate(e);
}
+
+ if ((isRTL ? isLeft(e) : isRight(e)) && this.sideNavCollapsed && this.hasSubItems) {
+ this._activate(e);
+ }
+
+ if ((isRTL ? isRight(e) : isLeft(e)) && this.inPopover) {
+ this.associatedItem?.sideNavigation?.closePicker();
+ }
}
_onkeyup(e: KeyboardEvent) {
diff --git a/packages/fiori/src/themes/SideNavigationGroup.css b/packages/fiori/src/themes/SideNavigationGroup.css
index 13eb25e38500..ef28dc29313e 100644
--- a/packages/fiori/src/themes/SideNavigationGroup.css
+++ b/packages/fiori/src/themes/SideNavigationGroup.css
@@ -9,7 +9,6 @@
.ui5-sn-item.ui5-sn-item-group {
min-height: 2rem;
padding-inline-start: var(--_ui5_side_navigation_group_padding);;
- gap: 0.4375rem;
font-family: var(--sapFontFamily);
font-size: var(--sapFontSize);
}