Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 25 additions & 2 deletions packages/fiori/src/SideNavigationItem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ import {
SIDE_NAVIGATION_OVERFLOW_ITEM_LABEL,
SIDE_NAVIGATION_PARENT_ITEM_SELECTABLE_DESCRIPTION,
} from "./generated/i18n/i18n-defaults.js";
import type { DefaultSlot } from "@ui5/webcomponents-base/dist/UI5Element.js";
import type { DefaultSlot, Slot } from "@ui5/webcomponents-base/dist/UI5Element.js";
import "@ui5/webcomponents/dist/Tag.js";

// Templates
import SideNavigationItemTemplate from "./SideNavigationItemTemplate.js";
Expand Down Expand Up @@ -81,6 +82,16 @@ class SideNavigationItem extends SideNavigationSelectableItemBase {
@slot({ type: HTMLElement, invalidateOnChildChange: true, "default": true })
items!: DefaultSlot<SideNavigationSubItem>;

/**
* Defines the tag to be displayed.
* Only `ui5-tag` component should be used.
*
* @public
* @since 2.7.0
*/
@slot({ type: HTMLElement })
tag!: Slot<HTMLElement>;

@i18n("@ui5/webcomponents-fiori")
static i18nBundle: I18nBundle;

Expand Down Expand Up @@ -183,9 +194,21 @@ class SideNavigationItem extends SideNavigationSelectableItemBase {
}

get _describedBy() {
const parts: string[] = [];

if (this.hasTag) {
parts.push(this._tagId);
}

if (!this.effectiveDisabled && this.items.length && !this.unselectable) {
return SideNavigationItem.i18nBundle.getText(SIDE_NAVIGATION_PARENT_ITEM_SELECTABLE_DESCRIPTION, this.text ?? "");
parts.push(SideNavigationItem.i18nBundle.getText(SIDE_NAVIGATION_PARENT_ITEM_SELECTABLE_DESCRIPTION, this.text ?? ""));
}

return parts.length > 0 ? parts.join(" ") : undefined;
}

get hasTag() {
return !!this.tag.length;
}

get classesArray() {
Expand Down
3 changes: 3 additions & 0 deletions packages/fiori/src/SideNavigationItemTemplate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ function ItemTemplate(this: SideNavigationItem) {
this.icon && <Icon class="ui5-sn-item-icon" name={this.icon}/>
}
<div class="ui5-sn-item-text">{this.text}</div>
{this.hasTag &&
<slot name="tag" id={this._tagId} class="ui5-sn-item-tag-slot"></slot>
}
{this.sideNavCollapsed ?
!!this.items.length &&
<Icon class="ui5-sn-item-toggle-icon"
Expand Down
63 changes: 56 additions & 7 deletions packages/fiori/src/SideNavigationPopoverTemplate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,20 @@ export default function SideNavigationTemplate(this: SideNavigation) {
target={item.target}
title={item.title}
tooltip={item._tooltip}
ref={this.captureRef.bind(item)}
ref={(el: HTMLElement | null) => {
if (el && item.tag.length > 0) {
const existingTags = Array.from(el.children).filter(child => child.getAttribute("slot") === "endContent");
if (existingTags.length === 0) {
item.tag.forEach(tagEl => {
const clonedTag = tagEl.cloneNode(true) as HTMLElement;
clonedTag.slot = "endContent";
el.appendChild(clonedTag);
});
}
}
this.captureRef.bind(item)(el);
}}
>

{item.children.length > 0 && !item.unselectable &&
(<NavigationMenuItem
class="ui5-navigation-menu-item-root-parent"
Expand All @@ -31,8 +42,21 @@ export default function SideNavigationTemplate(this: SideNavigation) {
target={item.target}
title={item.title}
tooltip={item._tooltip}
ref={this.captureRef.bind(item)}
></NavigationMenuItem>)
ref={(el: HTMLElement | null) => {
if (el && item.tag.length > 0) {
const existingTags = Array.from(el.children).filter(child => child.getAttribute("slot") === "endContent");
if (existingTags.length === 0) {
item.tag.forEach(tagEl => {
const clonedTag = tagEl.cloneNode(true) as HTMLElement;
clonedTag.slot = "endContent";
el.appendChild(clonedTag);
});
}
}
this.captureRef.bind(item)(el);
}}
>
</NavigationMenuItem>)
}

{(item as any).items?.map(renderMenuItem)}
Expand Down Expand Up @@ -79,7 +103,19 @@ export default function SideNavigationTemplate(this: SideNavigation) {
selected={this._popoverContents.item.selected}
unselectable={this._popoverContents.item.unselectable}
onui5-click={this.handlePopupItemClick}
ref={this.captureRef.bind(this._popoverContents.item)}
ref={(el: HTMLElement | null) => {
if (el && this._popoverContents.item.tag.length > 0) {
const existingTags = Array.from(el.children).filter(child => child.getAttribute("slot") === "tag");
if (existingTags.length === 0) {
this._popoverContents.item.tag.forEach(tagEl => {
const clonedTag = tagEl.cloneNode(true) as HTMLElement;
clonedTag.slot = "tag";
el.appendChild(clonedTag);
});
}
}
this.captureRef.bind(this._popoverContents.item)(el as SideNavigationItem | null);
}}
>
{this._popoverContents.subItems.map(item =>
<SideNavigationSubItem
Expand All @@ -93,8 +129,21 @@ export default function SideNavigationTemplate(this: SideNavigation) {
selected={item.selected}
unselectable={item.unselectable}
onui5-click={this.handlePopupItemClick}
ref={this.captureRef.bind(item)}
/>
ref={(el: HTMLElement | null) => {
if (el && item.tag.length > 0) {
const existingTags = Array.from(el.children).filter(child => child.getAttribute("slot") === "tag");
if (existingTags.length === 0) {
item.tag.forEach(tagEl => {
const clonedTag = tagEl.cloneNode(true) as HTMLElement;
clonedTag.slot = "tag";
el.appendChild(clonedTag);
});
}
}
this.captureRef.bind(item)(el as SideNavigationSubItem | null);
}}
>
</SideNavigationSubItem>
)}
</SideNavigationItem>
</SideNavigation>
Expand Down
4 changes: 4 additions & 0 deletions packages/fiori/src/SideNavigationSelectableItemBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,10 @@ class SideNavigationSelectableItemBase extends SideNavigationItemBase {
return this.selected;
}

get _tagId() {
return `${this._id}-tag`;
}

_onkeydown(e: KeyboardEvent) {
const isRTL = this.effectiveDir === "rtl";

Expand Down
21 changes: 21 additions & 0 deletions packages/fiori/src/SideNavigationSubItem.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import customElement from "@ui5/webcomponents-base/dist/decorators/customElement.js";
import jsxRender from "@ui5/webcomponents-base/dist/renderer/JsxRenderer.js";
import slot from "@ui5/webcomponents-base/dist/decorators/slot-strict.js";
import type { Slot } from "@ui5/webcomponents-base/dist/UI5Element.js";
import SideNavigationSelectableItemBase from "./SideNavigationSelectableItemBase.js";
import SideNavigationSubItemTemplate from "./SideNavigationSubItemTemplate.js";
import "@ui5/webcomponents/dist/Tag.js";

// Styles
import SideNavigationSubItemCss from "./generated/themes/SideNavigationSubItem.css.js";
Expand Down Expand Up @@ -30,6 +33,24 @@ import SideNavigationSubItemCss from "./generated/themes/SideNavigationSubItem.c
styles: SideNavigationSubItemCss,
})
class SideNavigationSubItem extends SideNavigationSelectableItemBase {
/**
* Defines the tag to be displayed.
* Only `ui5-tag` component should be used.
*
* @public
* @since 2.7.0
*/
@slot({ type: HTMLElement })
tag!: Slot<HTMLElement>;

get hasTag() {
return !!this.tag.length;
}

get _describedBy() {
return this.hasTag ? this._tagId : undefined;
}

_onkeydown(e: KeyboardEvent) {
super._onkeydown(e);
}
Expand Down
4 changes: 4 additions & 0 deletions packages/fiori/src/SideNavigationSubItemTemplate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,15 @@ export default function SideNavigationSubItemTemplate(this: SideNavigationSubIte
href={this._href}
target={this._target}
aria-haspopup={this._ariaHasPopup}
aria-describedby={this._describedBy}
>
{this.icon &&
<Icon class="ui5-sn-item-icon" name={this.icon}/>
}
<div class="ui5-sn-item-text">{this.text}</div>
{this.hasTag &&
<slot name="tag" id={this._tagId} class="ui5-sn-item-tag-slot"></slot>
}
{this.isExternalLink &&
<Icon class="ui5-sn-item-external-link-icon"
name={arrowRight}
Expand Down
35 changes: 35 additions & 0 deletions packages/fiori/src/themes/SideNavigationItemBase.css
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,41 @@ and there is an additional border that appears on hover. */
padding-inline-end: 0.375rem;
}

.ui5-sn-item-tag-slot {
padding-inline-start: 0.5rem;
padding-inline-end: 0.375rem;
display: inline-flex;
align-items: center;
}

.ui5-sn-item-tag-slot:has(+ .ui5-sn-item-toggle-icon),
.ui5-sn-item-tag-slot:has(+ .ui5-sn-item-external-link-icon) {
padding-inline-end: 0;
}

.ui5-sn-item-tag-slot + .ui5-sn-item-toggle-icon,
.ui5-sn-item-tag-slot + .ui5-sn-item-external-link-icon {
margin-inline-start: 0.375rem;
}

:host([side-nav-collapsed]) .ui5-sn-item-tag-slot {
display: none;
}

:host([side-nav-collapsed]) .ui5-sn-item:not(.ui5-sn-item-active):not(.ui5-sn-item-no-hover-effect):not(.ui5-sn-item-disabled):hover .ui5-sn-item-tag-slot,
:host([side-nav-collapsed]) .ui5-sn-item:not(.ui5-sn-item-active):not(.ui5-sn-item-no-hover-effect):focus .ui5-sn-item-tag-slot {
display: inline-flex;
max-width: 4rem;
}

:host([in-popover]) .ui5-sn-item-tag-slot {
display: inline-flex;
}

.ui5-sn-item-tag-slot::slotted([ui5-tag]) {
max-width: 4rem;
}

:host([side-nav-collapsed]) .ui5-sn-item-with-expander .ui5-sn-item-icon::after {
display: var(--_ui5_side_navigation_triangle_display);
content: "";
Expand Down
Loading
Loading