Skip to content

Commit

Permalink
feat(ui5-navigation-layout): add ui5-navigation-layout component (#9517)
Browse files Browse the repository at this point in the history
feat(ui5-navigation-layout): add ui5-navigation-layout component
  • Loading branch information
TeodorTaushanov authored Oct 30, 2024
1 parent 76b8ce3 commit 463c780
Show file tree
Hide file tree
Showing 25 changed files with 738 additions and 149 deletions.
128 changes: 128 additions & 0 deletions packages/fiori/cypress/specs/NavigationLayout.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import { html } from "lit";
import "../../src/NavigationLayout.js";
import "../../src/SideNavigation.js";
import "../../src/SideNavigationGroup.js";
import "../../src/SideNavigationItem.js";
import "../../src/ShellBar.js";
import "@ui5/webcomponents/dist/Button.js";
import "@ui5/webcomponents-icons/dist/home.js";
import "@ui5/webcomponents-icons/dist/menu.js";

const sampleCode = html`
<ui5-navigation-layout id="nl1">
<ui5-shellbar
slot="header"
primary-title="UI5 Web Components"
>
<ui5-button icon="menu" slot="startButton" id="startButton"></ui5-button>
</ui5-shellbar>
<ui5-side-navigation id="sn1" slot="sideContent">
<!-- Items -->
<ui5-side-navigation-item text="Home" href="#home" icon="home"></ui5-side-navigation-item>
<ui5-side-navigation-group text="Group 1" expanded>
<ui5-side-navigation-item text="Item 1" href="#item1"
icon="home"></ui5-side-navigation-item>
<ui5-side-navigation-item text="Item 2" href="#item2"
icon="home"></ui5-side-navigation-item>
<ui5-side-navigation-item text="Item 3" href="#item3"
icon="home"></ui5-side-navigation-item>
</ui5-side-navigation-group>
<!-- Fixed Items -->
<ui5-side-navigation-item slot="fixedItems"
text="Legal"
href="https://www.sap.com/about/legal/impressum.html"
target="_blank"
icon="home"></ui5-side-navigation-item>
</ui5-side-navigation>
<div>
Content
</div>
</ui5-navigation-layout>`;

describe("Rendering and interaction", () => {
beforeEach(() => {
cy.mount(sampleCode);
});

it("tests initial rendering", () => {
cy.get("[ui5-navigation-layout]")
.shadow()
.find(".ui5-nl-root")
.should("exist");

cy.get("[ui5-navigation-layout]")
.shadow()
.find(".ui5-nl-header")
.should("exist");

cy.get("[ui5-navigation-layout]")
.shadow()
.find(".ui5-nl-section")
.should("exist");

cy.get("[ui5-navigation-layout]")
.shadow()
.find(".ui5-nl-aside")
.should("exist");

cy.get("[ui5-navigation-layout]")
.shadow()
.find(".ui5-nl-content")
.should("exist");
});

it("tests collapsing", () => {
cy.get("[ui5-side-navigation]")
.should("have.prop", "collapsed", false);

cy.get("[ui5-navigation-layout]")
.invoke("prop", "sideCollapsed", true);

cy.get("[ui5-side-navigation]")
.should("have.prop", "collapsed", true);

cy.get("[ui5-navigation-layout]")
.invoke("prop", "sideCollapsed", false);

cy.get("[ui5-side-navigation]")
.should("have.prop", "collapsed", false);
});
});

describe("Navigation Layout on Phone", () => {
beforeEach(() => {
cy.ui5SimulateDevice("phone");
cy.mount(sampleCode);
});

it("tests initial rendering", () => {
cy.get("[ui5-navigation-layout]")
.should("have.prop", "sideCollapsed", true);

cy.get("[ui5-side-navigation]")
.should("have.prop", "collapsed", false);

cy.get("[ui5-navigation-layout]")
.shadow()
.find(".ui5-nl-aside")
.should("not.be.visible");
});

it("tests collapsing", () => {
cy.get("[ui5-navigation-layout]")
.invoke("prop", "sideCollapsed", false);

cy.get("[ui5-navigation-layout]")
.shadow()
.find(".ui5-nl-aside")
.should("be.visible");

cy.get("[ui5-navigation-layout]")
.invoke("prop", "sideCollapsed", true);

cy.get("[ui5-navigation-layout]")
.shadow()
.find(".ui5-nl-aside")
.should("not.be.visible");
});
});
13 changes: 13 additions & 0 deletions packages/fiori/src/NavigationLayout.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<div class="ui5-nl-root">
<header class="ui5-nl-header">
<slot name="header"></slot>
</header>
<section class="ui5-nl-section">
<aside class="ui5-nl-aside">
<slot name="sideContent"></slot>
</aside>
<div class="ui5-nl-content">
<slot></slot>
</div>
</section>
</div>
131 changes: 131 additions & 0 deletions packages/fiori/src/NavigationLayout.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js";
import customElement from "@ui5/webcomponents-base/dist/decorators/customElement.js";
import property from "@ui5/webcomponents-base/dist/decorators/property.js";
import slot from "@ui5/webcomponents-base/dist/decorators/slot.js";
import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js";
import browserScrollbarCSS from "@ui5/webcomponents/dist/generated/themes/BrowserScrollbar.css.js";
import {
isPhone,
isTablet,
isCombi,
} from "@ui5/webcomponents-base/dist/Device.js";
import type SideNavigation from "./SideNavigation.js";

// Template
import NavigationLayoutTemplate from "./generated/templates/NavigationLayoutTemplate.lit.js";

// Styles
import NavigationLayoutCss from "./generated/themes/NavigationLayout.css.js";

/**
* @class
*
* ### Overview
*
* The `ui5-navigation-layout` is a container component that can be used to
* create a layout with a header, a side navigation and a content area.
*
* ### Usage
*
* Use the `ui5-navigation-layout` to create whole screen of an application with vertical navigation.
*
* ### Responsive Behavior
*
* On desktop and tablet devices, the side navigation remains visible and can
* be expanded or collapsed using the `sideCollapsed` property. On phone devices, the side navigation
* is hidden by default but can be displayed using the same `sideCollapsed` property.
*
* ### ES6 Module Import
*
* `import "@ui5/webcomponents-fiori/dist/NavigationLayout.js";`
* @constructor
* @extends UI5Element
* @since 2.4.0
* @public
*/
@customElement({
tag: "ui5-navigation-layout",
languageAware: true,
renderer: litRender,
styles: [
browserScrollbarCSS,
NavigationLayoutCss,
],
template: NavigationLayoutTemplate,
})
class NavigationLayout extends UI5Element {
_sideCollapsed = isPhone() || (isTablet() && !isCombi());

/**
* @private
*/
@property({ type: Boolean })
isPhone = isPhone();

/**
* @private
*/
@property({ type: Boolean })
isTablet = isTablet() && !isCombi();

/**
* Indicates whether the side navigation is collapsed.
* @default false
* @public
*/
@property({ type: Boolean })
set sideCollapsed(value: boolean) {
this._sideCollapsed = value;

if (isPhone()) {
return;
}

const sideNavigation = this.sideContent[0];

if (sideNavigation) {
sideNavigation.collapsed = value;
}
}

get sideCollapsed() : boolean {
return this._sideCollapsed;
}

/**
* Defines the header.
* @public
*/
@slot()
header!: Array<HTMLElement>;

/**
* Defines the side content.
* @public
*/
@slot()
sideContent!: Array<SideNavigation>;

/**
* Defines the content.
* @public
*/
@slot({ type: HTMLElement, "default": true })
content!: Array<HTMLElement>;

onBeforeRendering() {
if (isPhone()) {
return;
}

const sideNavigation = this.sideContent[0];

if (sideNavigation) {
sideNavigation.collapsed = this.sideCollapsed;
}
}
}

NavigationLayout.define();

export default NavigationLayout;
1 change: 1 addition & 0 deletions packages/fiori/src/bundle.esm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import SideNavigationItem from "./SideNavigationItem.js";
import SideNavigationSubItem from "./SideNavigationSubItem.js";
import SortItem from "./SortItem.js";
import Timeline from "./Timeline.js";
import NavigationLayout from "./NavigationLayout.js";
import UploadCollection from "./UploadCollection.js";
import UploadCollectionItem from "./UploadCollectionItem.js";
import ViewSettingsDialog from "./ViewSettingsDialog.js";
Expand Down
65 changes: 65 additions & 0 deletions packages/fiori/src/themes/NavigationLayout.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@

:host(:not([hidden])) {
position: absolute;
inset: 0;
display: block;
background: var(--sapBackgroundColor);
box-sizing: border-box;
overflow: hidden;
}

.ui5-nl-root {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
box-sizing: border-box;
}

.ui5-nl-header {
box-shadow: var(--sapShell_Shadow);
z-index: 2;
}

.ui5-nl-section {
display: flex;
flex: 1;
min-height: 0;
position: relative;
}

.ui5-nl-aside {
transition: transform 0.3s;
z-index: 1;
}

:host([is-phone]) .ui5-nl-aside {
position: absolute;
top: 0;
left: 0;
bottom: 0;
width: 100%;
}

:host([is-phone]) ::slotted([ui5-side-navigation][slot="sideContent"]) {
width: 100%;
box-shadow: none;
}

.ui5-nl-content {
flex: 1;
min-width: 0;
overflow: auto;
}

:host([side-collapsed][is-phone]) .ui5-nl-aside {
transform: translateX(-100%);
}

:host([side-collapsed][is-phone]) :dir(rtl) .ui5-nl-aside {
transform: translateX(100%);
}

::slotted([ui5-shellbar][slot="header"]) {
padding-inline: .5rem;
}
5 changes: 0 additions & 5 deletions packages/fiori/src/themes/SideNavigation.css
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
width: var(--_ui5_side_navigation_width);
max-width: 100%;
transition: width 0.3s, min-width 0.3s;
border-radius: var(--_ui5_side_navigation_border_radius);
box-shadow: var(--_ui5_side_navigation_box_shadow);
font-family: "72override", var(--sapFontFamily);
font-size: var(--sapFontSize);
Expand All @@ -17,10 +16,6 @@
width: var(--_ui5_side_navigation_collapsed_width);
}

:host([is-touch-device]) {
border-radius: var(--_ui5_side_navigation_phone_border_radius);
}

.ui5-sn-root {
height: 100%;
display: flex;
Expand Down
2 changes: 0 additions & 2 deletions packages/fiori/src/themes/base/SideNavigation-parameters.css
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@
--_ui5_side_navigation_navigation_separator_height: calc(2 * var(--sapList_BorderWidth));
--_ui5_side_navigation_triangle_color: var(--sapContent_IconColor);
--_ui5_side_navigation_border_right: 1px solid var(--sapGroup_ContentBorderColor);
--_ui5_side_navigation_border_radius: 0;
--_ui5_side_navigation_phone_border_radius: 0;
--_ui5_side_navigation_box_shadow: none;
--_ui5_side_navigation_triangle_display: block;
--_ui5_side_navigation_phone_width: var(--_ui5_side_navigation_width);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,7 @@
--_ui5_side_navigation_navigation_separator_height: 0.0625rem;
--_ui5_side_navigation_triangle_color: var(--sapContent_NonInteractiveIconColor);
--_ui5_side_navigation_border_right: 0;
--_ui5_side_navigation_border_radius: 0.5rem 0.5rem 0 0;
--_ui5_side_navigation_phone_border_radius: 0.5rem;
--_ui5_side_navigation_shadow_color1: color-mix(in srgb, var(--sapContent_ShadowColor) 16%, transparent);
--_ui5_side_navigation_shadow_color2: color-mix(in srgb, var(--sapContent_ShadowColor) 16%, transparent);
--_ui5_side_navigation_box_shadow: 0 0 0.125rem 0 var(--_ui5_side_navigation_shadow_color1), 0 0.5rem 1rem 0 var(--_ui5_side_navigation_shadow_color2);
--_ui5_side_navigation_box_shadow: var(--sapContent_Shadow0);
--_ui5_side_navigation_triangle_display: none;
--_ui5_side_navigation_phone_width: 100%;

Expand Down
Loading

0 comments on commit 463c780

Please sign in to comment.